From 7cee93aa10442796c5fb480ab7655d24523a0a14 Mon Sep 17 00:00:00 2001 From: awskii Date: Fri, 17 Mar 2023 00:38:38 +0000 Subject: [PATCH] E4 metrics upd (#7122) --- cmd/integration/Readme.md | 4 + cmd/integration/commands/flags.go | 4 +- cmd/integration/commands/stages.go | 17 +- cmd/integration/commands/state_domains.go | 209 +++++++++++++++++++--- cmd/state/commands/erigon4.go | 16 +- go.mod | 2 +- go.sum | 4 +- 7 files changed, 211 insertions(+), 45 deletions(-) diff --git a/cmd/integration/Readme.md b/cmd/integration/Readme.md index 41fb8852026..68997f858d3 100644 --- a/cmd/integration/Readme.md +++ b/cmd/integration/Readme.md @@ -34,6 +34,10 @@ integration stage_exec --prune.to=N integration stage_history --prune.to=N ... +# Run tx replay with domains [requires 6th stage to be done before run] +integration state_domains --chain goerli --last-step=4 # stop replay when 4th step is merged +integration read_domains --chain goerli account ... # read values for given accounts + # hack which allows to force clear unwind stack of all stages clear_unwind_stack ``` diff --git a/cmd/integration/commands/flags.go b/cmd/integration/commands/flags.go index 35c065ca4e9..328bb8661ac 100644 --- a/cmd/integration/commands/flags.go +++ b/cmd/integration/commands/flags.go @@ -155,7 +155,7 @@ func withWorkers(cmd *cobra.Command) { } func withStartTx(cmd *cobra.Command) { - cmd.Flags().Uint64Var(&startTxNum, "startTx", 0, "start processing from tx") + cmd.Flags().Uint64Var(&startTxNum, "tx", 0, "start processing from tx") } func withTraceFromTx(cmd *cobra.Command) { @@ -165,5 +165,5 @@ func withTraceFromTx(cmd *cobra.Command) { func withCommitment(cmd *cobra.Command) { cmd.Flags().StringVar(&commitmentMode, "commitment.mode", "direct", "defines the way to calculate commitments: 'direct' mode reads from state directly, 'update' accumulate updates before commitment, 'off' actually disables commitment calculation") cmd.Flags().StringVar(&commitmentTrie, "commitment.trie", "hex", "hex - use Hex Patricia Hashed Trie for commitments, bin - use of binary patricia trie") - cmd.Flags().IntVar(&commitmentFreq, "commitment.freq", 25000, "how many blocks to skip between calculating commitment") + cmd.Flags().IntVar(&commitmentFreq, "commitment.freq", 1000000, "how many blocks to skip between calculating commitment") } diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index fc5d7dd9c4f..466b8323ef7 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -11,6 +11,11 @@ import ( "time" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/secp256k1" + "github.com/spf13/cobra" + "golang.org/x/exp/slices" + chain2 "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/commitment" common2 "github.com/ledgerwatch/erigon-lib/common" @@ -21,10 +26,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/kvcfg" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" libstate "github.com/ledgerwatch/erigon-lib/state" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/secp256k1" - "github.com/spf13/cobra" - "golang.org/x/exp/slices" "github.com/ledgerwatch/erigon/cmd/hack/tool/fromdb" "github.com/ledgerwatch/erigon/cmd/sentry/sentry" @@ -1239,7 +1240,7 @@ func getBlockReader(db kv.RoDB) (blockReader services.FullBlockReader) { var openDomainsOnce sync.Once var _aggDomainSingleton *libstate.Aggregator -func allDomains(ctx context.Context, db kv.RoDB, mode libstate.CommitmentMode, trie commitment.TrieVariant) (*snapshotsync.RoSnapshots, *libstate.Aggregator) { +func allDomains(ctx context.Context, db kv.RoDB, stepSize uint64, mode libstate.CommitmentMode, trie commitment.TrieVariant) (*snapshotsync.RoSnapshots, *libstate.Aggregator) { openDomainsOnce.Do(func() { var useSnapshots bool _ = db.View(context.Background(), func(tx kv.Tx) error { @@ -1253,7 +1254,7 @@ func allDomains(ctx context.Context, db kv.RoDB, mode libstate.CommitmentMode, t _allSnapshotsSingleton = snapshotsync.NewRoSnapshots(snapCfg, dirs.Snap) var err error - _aggDomainSingleton, err = libstate.NewAggregator(filepath.Join(dirs.DataDir, "state"), dirs.Tmp, ethconfig.HistoryV3AggregationStep, mode, trie) + _aggDomainSingleton, err = libstate.NewAggregator(filepath.Join(dirs.DataDir, "state"), dirs.Tmp, stepSize, mode, trie) if err != nil { panic(err) } @@ -1278,7 +1279,7 @@ func allDomains(ctx context.Context, db kv.RoDB, mode libstate.CommitmentMode, t return _allSnapshotsSingleton, _aggDomainSingleton } -func newDomains(ctx context.Context, db kv.RwDB, mode libstate.CommitmentMode, trie commitment.TrieVariant) (consensus.Engine, ethconfig.Config, *snapshotsync.RoSnapshots, *libstate.Aggregator) { +func newDomains(ctx context.Context, db kv.RwDB, stepSize uint64, mode libstate.CommitmentMode, trie commitment.TrieVariant) (consensus.Engine, ethconfig.Config, *snapshotsync.RoSnapshots, *libstate.Aggregator) { historyV3, pm := kvcfg.HistoryV3.FromDB(db), fromdb.PruneMode(db) //events := shards.NewEvents() genesis := core.DefaultGenesisBlockByChainName(chain) @@ -1310,7 +1311,7 @@ func newDomains(ctx context.Context, db kv.RwDB, mode libstate.CommitmentMode, t //} cfg.Dirs = datadir.New(datadirCli) - allSn, agg := allDomains(ctx, db, mode, trie) + allSn, agg := allDomains(ctx, db, stepSize, mode, trie) cfg.Snapshot = allSn.Cfg() engine := initConsensusEngine(chainConfig, cfg.Dirs.DataDir, db) diff --git a/cmd/integration/commands/state_domains.go b/cmd/integration/commands/state_domains.go index cfde33bbb35..b6329b2ce1f 100644 --- a/cmd/integration/commands/state_domains.go +++ b/cmd/integration/commands/state_domains.go @@ -3,11 +3,14 @@ package commands import ( "bytes" "context" + "encoding/hex" "errors" "fmt" "math/bits" + "os" "path/filepath" "runtime" + "strings" "time" "github.com/VictoriaMetrics/metrics" @@ -20,6 +23,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dbg" + "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/kv" kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx" libstate "github.com/ledgerwatch/erigon-lib/state" @@ -53,20 +57,160 @@ func init() { withStartTx(stateDomains) withCommitment(stateDomains) withTraceFromTx(stateDomains) + + stateDomains.Flags().Uint64Var(&stepSize, "step-size", ethconfig.HistoryV3AggregationStep, "size of aggregation step, tx") + stateDomains.Flags().Uint64Var(&lastStep, "last-step", 0, "step of last aggregation, step=txnum/step-size, unsigned integers only") + rootCmd.AddCommand(stateDomains) + + withDataDir(readDomains) + withChain(readDomains) + withHeimdall(readDomains) + withWorkers(readDomains) + withStartTx(readDomains) + + rootCmd.AddCommand(readDomains) } // if trie variant is not hex, we could not have another rootHash with to verify it var ( + stepSize uint64 + lastStep uint64 dirtySpaceThreshold = uint64(2 * 1024 * 1024 * 1024) /* threshold of dirty space in MDBX transaction that triggers a commit */ blockRootMismatchExpected bool mxBlockExecutionTimer = metrics.GetOrCreateSummary("chain_execution_seconds") - mxTxProcessed = metrics.GetOrCreateCounter("domain_tx_processed") - mxBlockProcessed = metrics.GetOrCreateCounter("domain_block_processed") - mxRunningCommits = metrics.GetOrCreateCounter("domain_running_commits") + mxCommitTook = metrics.GetOrCreateHistogram("domain_commit_took") ) +// write command to just seek and query state by addr and domain from state db and files (if any) +var readDomains = &cobra.Command{ + Use: "read_domains", + Short: `Run block execution and commitment with Domains.`, + Example: "go run ./cmd/integration read_domains --datadir=... --verbosity=3", + ValidArgs: []string{"account", "storage", "code", "commitment"}, + Args: cobra.ArbitraryArgs, + Run: func(cmd *cobra.Command, args []string) { + ctx, _ := libcommon.RootContext() + cfg := &nodecfg.DefaultConfig + utils.SetNodeConfigCobra(cmd, cfg) + ethConfig := ðconfig.Defaults + ethConfig.Genesis = core.DefaultGenesisBlockByChainName(chain) + erigoncli.ApplyFlagsForEthConfigCobra(cmd.Flags(), ethConfig) + + var readFromDomain string + var addrs [][]byte + for i := 0; i < len(args); i++ { + if i == 0 { + switch s := strings.ToLower(args[i]); s { + case "account", "storage", "code", "commitment": + readFromDomain = s + default: + log.Error("invalid domain to read from", "arg", args[i]) + return + } + continue + } + addr, err := hex.DecodeString(strings.TrimPrefix(args[i], "0x")) + if err != nil { + log.Warn("invalid address passed", "str", args[i], "at position", i, "err", err) + continue + } + addrs = append(addrs, addr) + } + + dirs := datadir.New(datadirCli) + chainDb := openDB(dbCfg(kv.ChainDB, dirs.Chaindata), true) + defer chainDb.Close() + + stateDb, err := kv2.NewMDBX(log.New()).Path(filepath.Join(dirs.DataDir, "statedb")).WriteMap().Open() + if err != nil { + return + } + defer stateDb.Close() + + if err := requestDomains(chainDb, stateDb, ctx, readFromDomain, addrs); err != nil { + if !errors.Is(err, context.Canceled) { + log.Error(err.Error()) + } + return + } + }, +} + +func requestDomains(chainDb, stateDb kv.RwDB, ctx context.Context, readDomain string, addrs [][]byte) error { + trieVariant := commitment.ParseTrieVariant(commitmentTrie) + if trieVariant != commitment.VariantHexPatriciaTrie { + blockRootMismatchExpected = true + } + mode := libstate.ParseCommitmentMode(commitmentMode) + libstate.COMPARE_INDEXES = true + + _, _, _, agg := newDomains(ctx, chainDb, stepSize, mode, trieVariant) + defer agg.Close() + + histTx, err := chainDb.BeginRo(ctx) + must(err) + defer histTx.Rollback() + + stateTx, err := stateDb.BeginRw(ctx) + must(err) + defer stateTx.Rollback() + + agg.SetTx(stateTx) + defer agg.StartWrites().FinishWrites() + + latestBlock, latestTx, err := agg.SeekCommitment() + if err != nil && startTxNum != 0 { + return fmt.Errorf("failed to seek commitment to tx %d: %w", startTxNum, err) + } + if latestTx < startTxNum { + return fmt.Errorf("latest available tx to start is %d and its less than start tx %d", latestTx, startTxNum) + } + if latestTx > 0 { + log.Info("aggregator files opened", "txn", latestTx, "block", latestBlock) + } + agg.SetTxNum(latestTx) + + r := ReaderWrapper4{ + roTx: histTx, + ac: agg.MakeContext(), + } + + switch readDomain { + case "account": + for _, addr := range addrs { + acc, err := r.ReadAccountData(libcommon.BytesToAddress(addr)) + if err != nil { + log.Error("failed to read account", "addr", addr, "err", err) + continue + } + fmt.Printf("%x: nonce=%d balance=%d code=%x root=%x\n", addr, acc.Nonce, acc.Balance.Uint64(), acc.CodeHash, acc.Root) + } + case "storage": + for _, addr := range addrs { + a, s := libcommon.BytesToAddress(addr[:length.Addr]), libcommon.BytesToHash(addr[length.Addr:]) + st, err := r.ReadAccountStorage(a, 0, &s) + if err != nil { + log.Error("failed to read storage", "addr", a.String(), "key", s.String(), "err", err) + continue + } + fmt.Printf("%s %s -> %x\n", a.String(), s.String(), st) + } + case "code": + for _, addr := range addrs { + code, err := r.ReadAccountCode(libcommon.BytesToAddress(addr), 0, libcommon.Hash{}) + if err != nil { + log.Error("failed to read code", "addr", addr, "err", err) + continue + } + fmt.Printf("%s: %x\n", addr, code) + } + } + return nil +} + +// write command to just seek and query state by addr and domain from state db and files (if any) var stateDomains = &cobra.Command{ Use: "state_domains", Short: `Run block execution and commitment with Domains.`, @@ -111,7 +255,7 @@ func loopProcessDomains(chainDb, stateDb kv.RwDB, ctx context.Context) error { } mode := libstate.ParseCommitmentMode(commitmentMode) - engine, _, _, agg := newDomains(ctx, chainDb, mode, trieVariant) + engine, _, _, agg := newDomains(ctx, chainDb, stepSize, mode, trieVariant) defer agg.Close() histTx, err := chainDb.BeginRo(ctx) @@ -125,7 +269,7 @@ func loopProcessDomains(chainDb, stateDb kv.RwDB, ctx context.Context) error { agg.SetTx(stateTx) defer agg.StartWrites().FinishWrites() - latestTx, err := agg.SeekCommitment() + latestBlock, latestTx, err := agg.SeekCommitment() if err != nil && startTxNum != 0 { return fmt.Errorf("failed to seek commitment to tx %d: %w", startTxNum, err) } @@ -133,7 +277,7 @@ func loopProcessDomains(chainDb, stateDb kv.RwDB, ctx context.Context) error { return fmt.Errorf("latest available tx to start is %d and its less than start tx %d", latestTx, startTxNum) } if latestTx > 0 { - log.Info("Max txNum in files", "txn", latestTx) + log.Info("aggregator files opened", "txn", latestTx, "block", latestBlock) } aggWriter, aggReader := WrapAggregator(agg, stateTx) @@ -146,12 +290,20 @@ func loopProcessDomains(chainDb, stateDb kv.RwDB, ctx context.Context) error { blockReader: getBlockReader(chainDb), stateTx: stateTx, stateDb: stateDb, + blockNum: latestBlock, + txNum: latestTx, startTxNum: latestTx, histTx: histTx, agg: agg, logger: log.New(), stat: stat4{startedAt: time.Now()}, } + if proc.txNum > 0 { + proc.txNum-- + } + if proc.blockNum == 0 { + proc.txNum = 2 + } mergedRoots := agg.AggregatedRoots() go proc.PrintStatsLoop(ctx, 30*time.Second) @@ -164,32 +316,38 @@ func loopProcessDomains(chainDb, stateDb kv.RwDB, ctx context.Context) error { } for { - err := proc.ProcessNext(ctx) - if err != nil { - return err - } - // Check for interrupts select { case <-ctx.Done(): - // Commit transaction only when interrupted or just before computing commitment (so it can be re-done) - if err := proc.agg.Flush(ctx); err != nil { - log.Error("aggregator flush", "err", err) + log.Info(fmt.Sprintf("interrupted, please wait for commitment and cleanup, next time start with --tx %d", proc.txNum)) + rh, err := proc.agg.ComputeCommitment(true, false) + if err != nil { + log.Error("failed to compute commitment", "err", err) } - - log.Info(fmt.Sprintf("interrupted, please wait for cleanup, next time start with --tx %d", proc.txNum)) - - if err := proc.commit(ctx); err != nil { - log.Error("chainDb commit", "err", err) + log.Info("commitment: state root computed", "root", hex.EncodeToString(rh)) + if err := agg.Flush(ctx); err != nil { + log.Error("failed to flush aggregator", "err", err) } - return nil + os.Exit(0) case <-mergedRoots: // notified with rootHash of latest aggregation if err := proc.commit(ctx); err != nil { log.Error("chainDb commit on merge", "err", err) } default: } + + if lastStep > 0 && proc.txNum/stepSize >= lastStep { + log.Info("last step reached") + // Commit transaction only when interrupted or just before computing commitment (so it can be re-done) + break + } + + err := proc.ProcessNext(ctx) + if err != nil { + return err + } } + return nil } type blockProcessor struct { @@ -224,8 +382,9 @@ func (b *blockProcessor) commit(ctx context.Context) error { return fmt.Errorf("commit failed due to invalid chainDb/rwTx") } - mxRunningCommits.Inc() - defer mxRunningCommits.Dec() + s := time.Now() + defer mxCommitTook.UpdateDuration(s) + var spaceDirty uint64 var err error if spaceDirty, _, err = b.stateTx.(*kv2.MdbxTx).SpaceDirty(); err != nil { @@ -313,6 +472,7 @@ func (b *blockProcessor) ProcessNext(ctx context.Context) error { b.agg.SetTx(b.stateTx) b.agg.SetTxNum(b.txNum) + b.agg.SetBlockNum(b.blockNum) if _, err = b.applyBlock(ctx, block); err != nil { b.logger.Error("processing error", "block", b.blockNum, "err", err) @@ -351,7 +511,6 @@ func (b *blockProcessor) applyBlock( } b.txNum++ // Pre-block transaction - mxTxProcessed.Inc() b.writer.w.SetTxNum(b.txNum) if err := b.writer.w.FinishTx(); err != nil { return nil, fmt.Errorf("finish pre-block tx %d (block %d) has failed: %w", b.txNum, block.NumberU64(), err) @@ -398,7 +557,6 @@ func (b *blockProcessor) applyBlock( } } b.txNum++ - mxTxProcessed.Inc() b.writer.w.SetTxNum(b.txNum) } @@ -440,7 +598,6 @@ func (b *blockProcessor) applyBlock( } b.txNum++ // Post-block transaction - mxTxProcessed.Inc() b.writer.w.SetTxNum(b.txNum) if b.txNum >= b.startTxNum { if block.Number().Uint64()%uint64(commitmentFreq) == 0 { @@ -458,8 +615,6 @@ func (b *blockProcessor) applyBlock( } } - mxTxProcessed.Inc() - mxBlockProcessed.Inc() return receipts, nil } diff --git a/cmd/state/commands/erigon4.go b/cmd/state/commands/erigon4.go index 22d9daf1612..c9e2f35e1de 100644 --- a/cmd/state/commands/erigon4.go +++ b/cmd/state/commands/erigon4.go @@ -51,7 +51,7 @@ func init() { withDataDir(erigon4Cmd) withChain(erigon4Cmd) - erigon4Cmd.Flags().IntVar(&commitmentFrequency, "commfreq", 25000, "how many blocks to skip between calculating commitment") + erigon4Cmd.Flags().IntVar(&commitmentFrequency, "commfreq", 125000, "how many blocks to skip between calculating commitment") erigon4Cmd.Flags().BoolVar(&commitments, "commitments", false, "set to true to calculate commitments") erigon4Cmd.Flags().StringVar(&commitmentMode, "commitments.mode", "direct", "defines the way to calculate commitments: 'direct' mode reads from state directly, 'update' accumulate updates before commitment") erigon4Cmd.Flags().Uint64Var(&startTxNumFrom, "tx", 0, "tx number to start from") @@ -160,7 +160,7 @@ func Erigon4(genesis *core.Genesis, chainConfig *chain2.Config, logger log.Logge agg.StartWrites() defer agg.FinishWrites() - latestTx, err := agg.SeekCommitment() + latestBlock, latestTx, err := agg.SeekCommitment() if err != nil && startTxNum != 0 { return fmt.Errorf("failed to seek commitment to tx %d: %w", startTxNum, err) } @@ -197,7 +197,7 @@ func Erigon4(genesis *core.Genesis, chainConfig *chain2.Config, logger log.Logge } } - logger.Info("Initialised chain configuration", "startTxNum", startTxNum, "config", chainConfig) + logger.Info("Initialised chain configuration", "startTxNum", startTxNum, "block", latestBlock, "config", chainConfig) var ( blockNum uint64 @@ -207,6 +207,11 @@ func Erigon4(genesis *core.Genesis, chainConfig *chain2.Config, logger log.Logge started = time.Now() ) + if startTxNum != 0 { + txNum = startTxNum + blockNum = latestBlock + } + logEvery := time.NewTicker(logInterval) defer logEvery.Stop() @@ -295,6 +300,7 @@ func Erigon4(genesis *core.Genesis, chainConfig *chain2.Config, logger log.Logge } agg.SetTx(rwTx) agg.SetTxNum(txNum) + agg.SetBlockNum(blockNum) if txNum, _, err = processBlock23(startTxNum, trace, txNum, readWrapper, writeWrapper, chainConfig, engine, getHeader, b, vmConfig); err != nil { log.Error("processing error", "block", blockNum, "err", err) @@ -309,7 +315,7 @@ func Erigon4(genesis *core.Genesis, chainConfig *chain2.Config, logger log.Logge log.Error("aggregator flush", "err", err) } - log.Info(fmt.Sprintf("interrupted, please wait for cleanup, next time start with --tx %d", txNum)) + log.Info(fmt.Sprintf("interrupted, please wait for cleanup, next time start with --tx %d", agg.Stats().TxCount)) if err := commitFn(txNum); err != nil { log.Error("db commit", "err", err) } @@ -490,7 +496,7 @@ func processBlock23(startTxNum uint64, trace bool, txNumStart uint64, rw *Reader txNum++ // Post-block transaction ww.w.SetTxNum(txNum) if txNum >= startTxNum { - if commitments && block.Number().Uint64()%uint64(commitmentFrequency) == 0 { + if commitments && commitmentFrequency > 0 && block.Number().Uint64()%uint64(commitmentFrequency) == 0 { rootHash, err := ww.w.ComputeCommitment(true, trace) if err != nil { return 0, nil, err diff --git a/go.mod b/go.mod index 68c7384ebf2..ff49fd5d74c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon go 1.18 require ( - github.com/ledgerwatch/erigon-lib v0.0.0-20230316033808-b3d75ec0c1d3 + github.com/ledgerwatch/erigon-lib v0.0.0-20230316233025-cbeed45a789d github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230306083105-1391330d62a3 github.com/ledgerwatch/log/v3 v3.7.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/go.sum b/go.sum index 1dee60750e3..d8555e3b5b3 100644 --- a/go.sum +++ b/go.sum @@ -517,8 +517,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-lib v0.0.0-20230316033808-b3d75ec0c1d3 h1:5PXzSu0mVq/hWvTo9pdtkQRX3xo7YBIuCBHWcxsOess= -github.com/ledgerwatch/erigon-lib v0.0.0-20230316033808-b3d75ec0c1d3/go.mod h1:HbqSyXJh/Xd7a5WQScXOhAOTFyCuFu7OLJQfpCsYMnc= +github.com/ledgerwatch/erigon-lib v0.0.0-20230316233025-cbeed45a789d h1:pAZOiH8WzsmncFxdwb2itbYwBKtIa1eTJFV4d3LomYI= +github.com/ledgerwatch/erigon-lib v0.0.0-20230316233025-cbeed45a789d/go.mod h1:HbqSyXJh/Xd7a5WQScXOhAOTFyCuFu7OLJQfpCsYMnc= github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230306083105-1391330d62a3 h1:tfzawK1gIIgRjVZeANXOr0Ziu+kqCIBuKMe0TXfl5Aw= github.com/ledgerwatch/erigon-snapshot v1.1.1-0.20230306083105-1391330d62a3/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.7.0 h1:aFPEZdwZx4jzA3+/Pf8wNDN5tCI0cIolq/kfvgcM+og=