Skip to content

Commit 0ffae31

Browse files
committed
chain validation and fix command
1 parent f520cfc commit 0ffae31

File tree

12 files changed

+1351
-49
lines changed

12 files changed

+1351
-49
lines changed

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ func init() {
198198
viper.BindPFlag("publisher.events.topic0Filter", rootCmd.PersistentFlags().Lookup("publisher-events-topic0Filter"))
199199
rootCmd.AddCommand(orchestratorCmd)
200200
rootCmd.AddCommand(apiCmd)
201+
rootCmd.AddCommand(validateCmd)
201202
}
202203

203204
func initConfig() {

cmd/validate.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package cmd
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"math/big"
7+
"strconv"
8+
9+
"github.com/ClickHouse/clickhouse-go/v2"
10+
"github.com/rs/zerolog/log"
11+
"github.com/spf13/cobra"
12+
config "github.com/thirdweb-dev/indexer/configs"
13+
"github.com/thirdweb-dev/indexer/internal/rpc"
14+
"github.com/thirdweb-dev/indexer/internal/storage"
15+
"github.com/thirdweb-dev/indexer/internal/validation"
16+
)
17+
18+
var (
19+
validateCmd = &cobra.Command{
20+
Use: "validate",
21+
Short: "TBD",
22+
Long: "TBD",
23+
Run: func(cmd *cobra.Command, args []string) {
24+
RunValidate(cmd, args)
25+
},
26+
}
27+
)
28+
29+
func RunValidate(cmd *cobra.Command, args []string) {
30+
batchSize := big.NewInt(1000)
31+
fixBatchSize := 0 // default is no batch size
32+
if len(args) > 0 {
33+
batchSizeFromArgs, err := strconv.Atoi(args[0])
34+
if err != nil {
35+
log.Fatal().Err(err).Msg("Failed to parse batch size")
36+
}
37+
if batchSizeFromArgs < 1 {
38+
batchSizeFromArgs = 1
39+
}
40+
batchSize = big.NewInt(int64(batchSizeFromArgs))
41+
log.Info().Msgf("Using batch size %d from args", batchSize)
42+
}
43+
if len(args) > 1 {
44+
fixBatchSizeFromArgs, err := strconv.Atoi(args[1])
45+
if err != nil {
46+
log.Fatal().Err(err).Msg("Failed to parse fix batch size")
47+
}
48+
fixBatchSize = fixBatchSizeFromArgs
49+
}
50+
log.Debug().Msgf("Batch size: %d, fix batch size: %d", batchSize, fixBatchSize)
51+
batchSize = new(big.Int).Sub(batchSize, big.NewInt(1)) // -1 because range ends are inclusive
52+
53+
rpcClient, err := rpc.Initialize()
54+
if err != nil {
55+
log.Fatal().Err(err).Msg("Failed to initialize RPC")
56+
}
57+
log.Info().Msgf("Running validation for chain %d", rpcClient.GetChainID())
58+
59+
s, err := storage.NewStorageConnector(&config.Cfg.Storage)
60+
if err != nil {
61+
log.Fatal().Err(err).Msg("Failed to initialize storage")
62+
}
63+
cursor, err := validation.InitCursor(rpcClient.GetChainID(), s)
64+
if err != nil {
65+
log.Fatal().Err(err).Msg("Failed to initialize cursor")
66+
}
67+
log.Debug().Msgf("Cursor initialized for chain %d, starting from block %d", rpcClient.GetChainID(), cursor.LastScannedBlockNumber)
68+
69+
conn, err := clickhouse.Open(&clickhouse.Options{
70+
Addr: []string{fmt.Sprintf("%s:%d", config.Cfg.Storage.Main.Clickhouse.Host, config.Cfg.Storage.Main.Clickhouse.Port)},
71+
Protocol: clickhouse.Native,
72+
TLS: &tls.Config{},
73+
Auth: clickhouse.Auth{
74+
Username: config.Cfg.Storage.Main.Clickhouse.Username,
75+
Password: config.Cfg.Storage.Main.Clickhouse.Password,
76+
},
77+
Settings: func() clickhouse.Settings {
78+
settings := clickhouse.Settings{
79+
"do_not_merge_across_partitions_select_final": "1",
80+
"use_skip_indexes_if_final": "1",
81+
"optimize_move_to_prewhere_if_final": "1",
82+
"async_insert": "1",
83+
"wait_for_async_insert": "1",
84+
}
85+
return settings
86+
}(),
87+
})
88+
if err != nil {
89+
log.Fatal().Err(err).Msg("Failed to connect to ClickHouse")
90+
}
91+
defer conn.Close()
92+
93+
startBlock := new(big.Int).Add(cursor.LastScannedBlockNumber, big.NewInt(1))
94+
95+
for startBlock.Cmp(cursor.MaxBlockNumber) <= 0 {
96+
batchEndBlock := new(big.Int).Add(startBlock, batchSize)
97+
if batchEndBlock.Cmp(cursor.MaxBlockNumber) > 0 {
98+
batchEndBlock = new(big.Int).Set(cursor.MaxBlockNumber)
99+
}
100+
101+
log.Info().Msgf("Validating batch of blocks from %s to %s", startBlock.String(), batchEndBlock.String())
102+
err := validateAndFixRange(rpcClient, s, conn, startBlock, batchEndBlock, fixBatchSize)
103+
if err != nil {
104+
log.Fatal().Err(err).Msgf("failed to validate range %v-%v", startBlock, batchEndBlock)
105+
}
106+
107+
startBlock = new(big.Int).Add(batchEndBlock, big.NewInt(1))
108+
cursor.Update(batchEndBlock)
109+
}
110+
}
111+
112+
/**
113+
* Validates a range of blocks (end and start are inclusive) for a given chain and fixes any problems it finds
114+
*/
115+
func validateAndFixRange(rpcClient rpc.IRPCClient, s storage.IStorage, conn clickhouse.Conn, startBlock *big.Int, endBlock *big.Int, fixBatchSize int) error {
116+
chainId := rpcClient.GetChainID()
117+
err := validation.FindAndRemoveDuplicates(conn, chainId, startBlock, endBlock)
118+
if err != nil {
119+
log.Fatal().Err(err).Msg("Failed to find and fix duplicates")
120+
}
121+
122+
err = validation.FindAndFixGaps(rpcClient, s, conn, chainId, startBlock, endBlock)
123+
if err != nil {
124+
log.Fatal().Err(err).Msg("Failed to find and fix gaps")
125+
}
126+
127+
err = validation.ValidateAndFixBlocks(rpcClient, s, conn, startBlock, endBlock, fixBatchSize)
128+
if err != nil {
129+
log.Fatal().Err(err).Msg("Failed to validate and fix blocks")
130+
}
131+
132+
log.Debug().Msgf("Validation complete for range %v-%v", startBlock, endBlock)
133+
return nil
134+
}

go.mod

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
module github.com/thirdweb-dev/indexer
22

3-
go 1.23
3+
go 1.23.0
44

55
require (
66
github.com/ClickHouse/clickhouse-go/v2 v2.30.1
7-
github.com/ethereum/go-ethereum v1.14.8
7+
github.com/ethereum/go-ethereum v1.15.11
88
github.com/gin-gonic/gin v1.10.0
99
github.com/gorilla/schema v1.4.1
10+
github.com/holiman/uint256 v1.3.2
1011
github.com/prometheus/client_golang v1.20.4
1112
github.com/rs/zerolog v1.33.0
1213
github.com/spf13/cobra v1.8.1
@@ -20,27 +21,39 @@ require (
2021

2122
require (
2223
github.com/ClickHouse/ch-go v0.63.1 // indirect
24+
github.com/DataDog/zstd v1.4.5 // indirect
2325
github.com/KyleBanks/depth v1.2.1 // indirect
2426
github.com/Microsoft/go-winio v0.6.2 // indirect
2527
github.com/andybalholm/brotli v1.1.1 // indirect
2628
github.com/beorn7/perks v1.0.1 // indirect
27-
github.com/bits-and-blooms/bitset v1.10.0 // indirect
29+
github.com/bits-and-blooms/bitset v1.20.0 // indirect
2830
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
2931
github.com/bytedance/sonic v1.12.6 // indirect
3032
github.com/bytedance/sonic/loader v0.2.1 // indirect
3133
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3234
github.com/cloudwego/base64x v0.1.4 // indirect
3335
github.com/cloudwego/iasm v0.2.0 // indirect
34-
github.com/consensys/bavard v0.1.13 // indirect
35-
github.com/consensys/gnark-crypto v0.12.1 // indirect
36+
github.com/cockroachdb/errors v1.11.3 // indirect
37+
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
38+
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
39+
github.com/cockroachdb/pebble v1.1.2 // indirect
40+
github.com/cockroachdb/redact v1.1.5 // indirect
41+
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
42+
github.com/consensys/bavard v0.1.27 // indirect
43+
github.com/consensys/gnark-crypto v0.16.0 // indirect
3644
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
37-
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
45+
github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
46+
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
47+
github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect
3848
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
3949
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
4050
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
4151
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
52+
github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
53+
github.com/ethereum/go-verkle v0.2.2 // indirect
4254
github.com/fsnotify/fsnotify v1.7.0 // indirect
4355
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
56+
github.com/getsentry/sentry-go v0.27.0 // indirect
4457
github.com/gin-contrib/sse v0.1.0 // indirect
4558
github.com/go-faster/city v1.0.1 // indirect
4659
github.com/go-faster/errors v0.7.1 // indirect
@@ -53,26 +66,32 @@ require (
5366
github.com/go-playground/universal-translator v0.18.1 // indirect
5467
github.com/go-playground/validator/v10 v10.23.0 // indirect
5568
github.com/goccy/go-json v0.10.4 // indirect
69+
github.com/gofrs/flock v0.8.1 // indirect
70+
github.com/gogo/protobuf v1.3.2 // indirect
5671
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
72+
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
5773
github.com/google/uuid v1.6.0 // indirect
5874
github.com/gorilla/websocket v1.4.2 // indirect
5975
github.com/hashicorp/hcl v1.0.0 // indirect
60-
github.com/holiman/uint256 v1.3.1 // indirect
6176
github.com/inconshreveable/mousetrap v1.1.0 // indirect
6277
github.com/josharian/intern v1.0.0 // indirect
6378
github.com/json-iterator/go v1.1.12 // indirect
6479
github.com/klauspost/compress v1.17.11 // indirect
6580
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
81+
github.com/kr/pretty v0.3.1 // indirect
82+
github.com/kr/text v0.2.0 // indirect
6683
github.com/leodido/go-urn v1.4.0 // indirect
6784
github.com/magiconair/properties v1.8.7 // indirect
6885
github.com/mailru/easyjson v0.7.7 // indirect
6986
github.com/mattn/go-colorable v0.1.13 // indirect
7087
github.com/mattn/go-isatty v0.0.20 // indirect
88+
github.com/mattn/go-runewidth v0.0.13 // indirect
7189
github.com/mitchellh/mapstructure v1.5.0 // indirect
7290
github.com/mmcloughlin/addchain v0.4.0 // indirect
7391
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
7492
github.com/modern-go/reflect2 v1.0.2 // indirect
7593
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
94+
github.com/olekukonko/tablewriter v0.0.5 // indirect
7695
github.com/paulmach/orb v0.11.1 // indirect
7796
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
7897
github.com/pierrec/lz4/v4 v4.1.22 // indirect
@@ -81,6 +100,8 @@ require (
81100
github.com/prometheus/client_model v0.6.1 // indirect
82101
github.com/prometheus/common v0.55.0 // indirect
83102
github.com/prometheus/procfs v0.15.1 // indirect
103+
github.com/rivo/uniseg v0.2.0 // indirect
104+
github.com/rogpeppe/go-internal v1.12.0 // indirect
84105
github.com/sagikazarmark/locafero v0.4.0 // indirect
85106
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
86107
github.com/segmentio/asm v1.2.0 // indirect
@@ -92,25 +113,26 @@ require (
92113
github.com/spf13/pflag v1.0.5 // indirect
93114
github.com/stretchr/objx v0.5.2 // indirect
94115
github.com/subosito/gotenv v1.6.0 // indirect
95-
github.com/supranational/blst v0.3.11 // indirect
116+
github.com/supranational/blst v0.3.14 // indirect
117+
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
96118
github.com/tklauser/go-sysconf v0.3.12 // indirect
97119
github.com/tklauser/numcpus v0.6.1 // indirect
98120
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
99121
github.com/twmb/franz-go/pkg/kmsg v1.9.0 // indirect
100122
github.com/ugorji/go/codec v1.2.12 // indirect
101-
github.com/urfave/cli/v2 v2.27.4 // indirect
123+
github.com/urfave/cli/v2 v2.27.5 // indirect
102124
github.com/yusufpapurcu/wmi v1.2.3 // indirect
103125
go.opentelemetry.io/otel v1.26.0 // indirect
104126
go.opentelemetry.io/otel/trace v1.26.0 // indirect
105127
go.uber.org/multierr v1.11.0 // indirect
106128
golang.org/x/arch v0.12.0 // indirect
107-
golang.org/x/crypto v0.33.0 // indirect
129+
golang.org/x/crypto v0.35.0 // indirect
108130
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
109-
golang.org/x/net v0.35.0 // indirect
131+
golang.org/x/net v0.36.0 // indirect
110132
golang.org/x/sync v0.11.0 // indirect
111133
golang.org/x/sys v0.30.0 // indirect
112134
golang.org/x/text v0.22.0 // indirect
113-
golang.org/x/tools v0.25.0 // indirect
135+
golang.org/x/tools v0.29.0 // indirect
114136
google.golang.org/protobuf v1.36.1 // indirect
115137
gopkg.in/ini.v1 v1.67.0 // indirect
116138
gopkg.in/yaml.v3 v3.0.1 // indirect

0 commit comments

Comments
 (0)