Skip to content

Commit 234c6c5

Browse files
committed
sql: add Bloom filters for ATXs and malicious identities
1 parent 5091028 commit 234c6c5

File tree

13 files changed

+1101
-55
lines changed

13 files changed

+1101
-55
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22.4
55
require (
66
cloud.google.com/go/storage v1.43.0
77
github.com/ALTree/bigfloat v0.2.0
8+
github.com/bits-and-blooms/bloom/v3 v3.7.0
89
github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240913055630-bfe8736306b4
910
github.com/cosmos/btcutil v1.0.5
1011
github.com/go-llsqlite/crawshaw v0.5.5
@@ -35,6 +36,7 @@ require (
3536
github.com/prometheus/client_model v0.6.1
3637
github.com/prometheus/common v0.59.1
3738
github.com/quic-go/quic-go v0.46.0
39+
github.com/rqlite/sql v0.0.0-20240312185922-ffac88a740bd
3840
github.com/rs/cors v1.11.1
3941
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
4042
github.com/seehuhn/mt19937 v1.0.0
@@ -80,6 +82,7 @@ require (
8082
github.com/anacrolix/sync v0.3.0 // indirect
8183
github.com/benbjohnson/clock v1.3.5 // indirect
8284
github.com/beorn7/perks v1.0.1 // indirect
85+
github.com/bits-and-blooms/bitset v1.10.0 // indirect
8386
github.com/c0mm4nd/go-ripemd v0.0.0-20200326052756-bd1759ad7d10 // indirect
8487
github.com/cespare/xxhash/v2 v2.3.0 // indirect
8588
github.com/containerd/cgroups v1.1.0 // indirect

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
4848
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
4949
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
5050
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
51+
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
52+
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
53+
github.com/bits-and-blooms/bloom/v3 v3.7.0 h1:VfknkqV4xI+PsaDIsoHueyxVDZrfvMn56jeWUzvzdls=
54+
github.com/bits-and-blooms/bloom/v3 v3.7.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg=
5155
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
5256
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
5357
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c h1:FUUopH4brHNO2kJoNN3pV+OBEYmgraLT/KHZrMM69r0=
@@ -152,6 +156,8 @@ github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+
152156
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
153157
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
154158
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
159+
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
160+
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
155161
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
156162
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
157163
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -551,6 +557,8 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
551557
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
552558
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
553559
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
560+
github.com/rqlite/sql v0.0.0-20240312185922-ffac88a740bd h1:wW6BtayFoKaaDeIvXRE3SZVPOscSKlYD+X3bB749+zk=
561+
github.com/rqlite/sql v0.0.0-20240312185922-ffac88a740bd/go.mod h1:ib9zVtNgRKiGuoMyUqqL5aNpk+r+++YlyiVIkclVqPg=
554562
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
555563
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
556564
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@@ -656,6 +664,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70
656664
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
657665
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
658666
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
667+
github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
668+
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
659669
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
660670
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
661671
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=

node/node.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import (
7474
"github.com/spacemeshos/go-spacemesh/sql"
7575
"github.com/spacemeshos/go-spacemesh/sql/activesets"
7676
"github.com/spacemeshos/go-spacemesh/sql/atxs"
77+
"github.com/spacemeshos/go-spacemesh/sql/identities"
7778
"github.com/spacemeshos/go-spacemesh/sql/layers"
7879
"github.com/spacemeshos/go-spacemesh/sql/localsql"
7980
localmigrations "github.com/spacemeshos/go-spacemesh/sql/localsql/migrations"
@@ -1979,6 +1980,15 @@ func (app *App) setupDBs(ctx context.Context, lg log.Log) error {
19791980
}
19801981
{
19811982
warmupLog := app.log.Zap().Named("warmup")
1983+
app.log.Info("loading Bloom filters")
1984+
_, err := atxs.LoadBloomFilter(app.db, warmupLog)
1985+
if err != nil {
1986+
return fmt.Errorf("loading ATX Bloom filter: %w", err)
1987+
}
1988+
_, err = identities.LoadBloomFilter(app.db, warmupLog)
1989+
if err != nil {
1990+
return fmt.Errorf("loading malicious identity Bloom filter: %w", err)
1991+
}
19821992
app.log.Info("starting cache warmup")
19831993
applied, err := layers.GetLastApplied(app.db)
19841994
if err != nil {

sql/atxs/atxs.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package atxs
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"time"
78

89
sqlite "github.com/go-llsqlite/crawshaw"
10+
"go.uber.org/zap"
911

1012
"github.com/spacemeshos/go-spacemesh/common/types"
1113
"github.com/spacemeshos/go-spacemesh/sql"
@@ -15,6 +17,11 @@ import (
1517
const (
1618
CacheKindEpochATXs sql.QueryCacheKind = "epoch-atxs"
1719
CacheKindATXBlob sql.QueryCacheKind = "atx-blob"
20+
// Bloom filter size is < 115 MiB while below 100M ATXs.
21+
// TODO: adjust Bloom filter settings after ATX merge & checkpointing.
22+
BloomFilterFalsePositiveRate = 0.01
23+
BloomFilterMinSize = 100_000_000
24+
BloomFilterExtraCoef = 1.2
1825
)
1926

2027
// Query to retrieve ATXs.
@@ -120,8 +127,28 @@ func GetByEpochAndNodeID(
120127
return id, nil
121128
}
122129

130+
// LoadBloomFilter intializes and loads the bloom filter for ATXs.
131+
func LoadBloomFilter(db sql.StateDatabase, logger *zap.Logger) (*sql.DBBloomFilter, error) {
132+
bf := sql.NewDBBloomFilter(
133+
"atxs", "select id from atxs", "id",
134+
BloomFilterMinSize, BloomFilterExtraCoef, BloomFilterFalsePositiveRate)
135+
if err := bf.Load(db, logger); err != nil {
136+
return nil, fmt.Errorf("load bloom filter: %w", err)
137+
}
138+
db.AddSet(bf)
139+
return bf, nil
140+
}
141+
123142
// Has checks if an ATX exists by a given ATX ID.
143+
// It tries to do so using Bloom filter first, and falls back to a direct query if the filter is not available.
124144
func Has(db sql.Executor, id types.ATXID) (bool, error) {
145+
has, err := sql.Contains(db, "atxs", id[:])
146+
if err == nil {
147+
return has, nil
148+
} else if !errors.Is(err, sql.ErrNoSet) {
149+
return false, fmt.Errorf("check if have id %s: %w", id, err)
150+
}
151+
125152
rows, err := db.Exec("select 1 from atxs where id = ?1;",
126153
func(stmt *sql.Statement) {
127154
stmt.BindBytes(1, id.Bytes())
@@ -486,7 +513,12 @@ func Add(db sql.Executor, atx *types.ActivationTx, blob types.AtxBlob) error {
486513
return fmt.Errorf("insert ATX ID %v: %w", atx.ID(), err)
487514
}
488515

489-
return AddBlob(db, atx.ID(), blob.Blob, blob.Version)
516+
if err := AddBlob(db, atx.ID(), blob.Blob, blob.Version); err != nil {
517+
return err
518+
}
519+
520+
sql.AddToSet(db, "atxs", atx.ID().Bytes())
521+
return err
490522
}
491523

492524
func AddBlob(db sql.Executor, id types.ATXID, blob []byte, version types.AtxVersion) error {

0 commit comments

Comments
 (0)