diff --git a/cmd/downloader/downloadergrpc/client.go b/cmd/downloader/downloadergrpc/client.go index ec7284491..47ae9492f 100644 --- a/cmd/downloader/downloadergrpc/client.go +++ b/cmd/downloader/downloadergrpc/client.go @@ -10,12 +10,10 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces" proto_downloader "github.com/ledgerwatch/erigon-lib/gointerfaces/downloader" prototypes "github.com/ledgerwatch/erigon-lib/gointerfaces/types" - "github.com/ledgerwatch/erigon/cmd/downloader/downloader" "github.com/ledgerwatch/erigon/common" "google.golang.org/grpc" "google.golang.org/grpc/backoff" "google.golang.org/grpc/keepalive" - "google.golang.org/protobuf/types/known/emptypb" ) func NewClient(ctx context.Context, downloaderAddr string) (proto_downloader.DownloaderClient, error) { @@ -64,18 +62,3 @@ func String2Proto(in string) *prototypes.H160 { copy(infoHash[:], common.FromHex(in)) return gointerfaces.ConvertAddressToH160(infoHash) } - -type ClientDirect struct { - server *downloader.GrpcServer -} - -func NewClientDirect(server *downloader.GrpcServer) *ClientDirect { - return &ClientDirect{server: server} -} - -func (c *ClientDirect) Download(ctx context.Context, in *proto_downloader.DownloadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { - return c.server.Download(ctx, in) -} -func (c *ClientDirect) Stats(ctx context.Context, in *proto_downloader.StatsRequest, opts ...grpc.CallOption) (*proto_downloader.StatsReply, error) { - return c.server.Stats(ctx, in) -} diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index eaa2031a9..4c2dbcec8 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/ledgerwatch/erigon-lib/direct" "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" @@ -21,6 +22,7 @@ import ( kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx" "github.com/ledgerwatch/erigon-lib/kv/remotedb" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/health" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/services" @@ -238,11 +240,36 @@ func checkDbCompatibility(ctx context.Context, db kv.RoDB) error { return nil } +func EmbeddedServices(ctx context.Context, erigonDB kv.RoDB, stateCacheCfg kvcache.CoherentConfig, blockReader interfaces.BlockAndTxnReader, ethBackendServer remote.ETHBACKENDServer, + txPoolServer txpool.TxpoolServer, miningServer txpool.MiningServer) (eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, starknet *services.StarknetService, stateCache kvcache.Cache, ff *filters.Filters, err error) { + if stateCacheCfg.KeysLimit > 0 { + stateCache = kvcache.New(stateCacheCfg) + } else { + stateCache = kvcache.NewDummy() + } + kvRPC := remotedbserver.NewKvServer(ctx, erigonDB) + stateDiffClient := direct.NewStateDiffClientDirect(kvRPC) + subscribeToStateChangesLoop(ctx, stateDiffClient, stateCache) + + directClient := direct.NewEthBackendClientDirect(ethBackendServer) + + eth = services.NewRemoteBackend(directClient, erigonDB, blockReader) + txPool = direct.NewTxPoolClient(txPoolServer) + mining = direct.NewMiningClient(miningServer) + ff = filters.New(ctx, eth, txPool, mining) + return +} + // RemoteServices - use when RPCDaemon run as independent process. Still it can use --datadir flag to enable // `cfg.SingleNodeMode` (mode when it on 1 machine with Erigon) -func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) (db kv.RoDB, borDb kv.RoDB, eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, starknet *services.StarknetService, stateCache kvcache.Cache, blockReader interfaces.BlockAndTxnReader, err error) { +func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) ( + db kv.RoDB, borDb kv.RoDB, + eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, + starknet *services.StarknetService, + stateCache kvcache.Cache, blockReader interfaces.BlockAndTxnReader, + ff *filters.Filters, err error) { if !cfg.SingleNodeMode && cfg.PrivateApiAddr == "" { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("either remote db or local db must be specified") + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("either remote db or local db must be specified") } // Do not change the order of these checks. Chaindata needs to be checked first, because PrivateApiAddr has default value which is not "" @@ -252,10 +279,10 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance log.Trace("Creating chain db", "path", cfg.Chaindata) rwKv, err = kv2.NewMDBX(logger).Path(cfg.Chaindata).Readonly().Open() if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, ff, err } if compatErr := checkDbCompatibility(ctx, rwKv); compatErr != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, compatErr + return nil, nil, nil, nil, nil, nil, nil, nil, ff, compatErr } db = rwKv stateCache = kvcache.NewDummy() @@ -268,14 +295,14 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance // ensure db exist tmpDb, err := kv2.NewMDBX(logger).Path(borDbPath).Label(kv.ConsensusDB).Open() if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, ff, err } tmpDb.Close() } log.Trace("Creating consensus db", "path", borDbPath) borKv, err = kv2.NewMDBX(logger).Path(borDbPath).Label(kv.ConsensusDB).Readonly().Open() if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, ff, err } // Skip the compatibility check, until we have a schema in erigon-lib borDb = borKv @@ -302,10 +329,10 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance } return nil }); err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, nil, nil, ff, err } if cc == nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("chain config not found in db. Need start erigon at least once on this db") + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("chain config not found in db. Need start erigon at least once on this db") } allSnapshots := snapshotsync.NewAllSnapshots(cfg.Snapshot, path.Join(cfg.Datadir, "snapshots")) @@ -315,23 +342,20 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance blockReader = snapshotsync.NewBlockReader() } } - if cfg.PrivateApiAddr == "" { - return db, borDb, eth, txPool, mining, starknet, stateCache, blockReader, nil - } creds, err := grpcutil.TLS(cfg.TLSCACert, cfg.TLSCertfile, cfg.TLSKeyFile) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("open tls cert: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("open tls cert: %w", err) } conn, err := grpcutil.Connect(creds, cfg.PrivateApiAddr) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to execution service privateApi: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("could not connect to execution service privateApi: %w", err) } kvClient := remote.NewKVClient(conn) remoteKv, err := remotedb.NewRemote(gointerfaces.VersionFromProto(remotedbserver.KvServiceAPIVersion), logger, kvClient).Open() if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to remoteKv: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("could not connect to remoteKv: %w", err) } subscribeToStateChangesLoop(ctx, kvClient, stateCache) @@ -346,7 +370,7 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance if cfg.TxPoolApiAddr != cfg.PrivateApiAddr { txpoolConn, err = grpcutil.Connect(creds, cfg.TxPoolApiAddr) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to txpool api: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("could not connect to txpool api: %w", err) } } @@ -376,12 +400,14 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance if cfg.StarknetGRPCAddress != "" { starknetConn, err := grpcutil.Connect(creds, cfg.StarknetGRPCAddress) if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to starknet api: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, ff, fmt.Errorf("could not connect to starknet api: %w", err) } starknet = services.NewStarknetService(starknetConn) } - return db, borDb, eth, txPool, mining, starknet, stateCache, blockReader, err + ff = filters.New(ctx, eth, txPool, mining) + + return db, borDb, eth, txPool, mining, starknet, stateCache, blockReader, ff, err } func StartRpcServer(ctx context.Context, cfg Flags, rpcAPI []rpc.API) error { diff --git a/cmd/rpcdaemon/commands/daemon.go b/cmd/rpcdaemon/commands/daemon.go index 4f5acadc7..af3f6a863 100644 --- a/cmd/rpcdaemon/commands/daemon.go +++ b/cmd/rpcdaemon/commands/daemon.go @@ -1,8 +1,6 @@ package commands import ( - "context" - "github.com/ledgerwatch/erigon-lib/gointerfaces/starknet" "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" "github.com/ledgerwatch/erigon-lib/kv" @@ -15,11 +13,10 @@ import ( ) // APIList describes the list of available RPC apis -func APIList(ctx context.Context, db kv.RoDB, borDb kv.RoDB, - eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, - starknet starknet.CAIROVMClient, filters *filters.Filters, - stateCache kvcache.Cache, - blockReader interfaces.BlockAndTxnReader, +func APIList(db kv.RoDB, borDb kv.RoDB, eth services.ApiBackend, + txPool txpool.TxpoolClient, mining txpool.MiningClient, + starknet starknet.CAIROVMClient, + filters *filters.Filters, stateCache kvcache.Cache, blockReader interfaces.BlockAndTxnReader, cfg cli.Flags, customAPIList []rpc.API) []rpc.API { var defaultAPIList []rpc.API diff --git a/cmd/rpcdaemon/commands/debug_api.go b/cmd/rpcdaemon/commands/debug_api.go index eb3d4814d..893967c05 100644 --- a/cmd/rpcdaemon/commands/debug_api.go +++ b/cmd/rpcdaemon/commands/debug_api.go @@ -13,7 +13,6 @@ import ( "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/eth" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/eth/tracers" "github.com/ledgerwatch/erigon/ethdb" @@ -22,6 +21,9 @@ import ( "github.com/ledgerwatch/erigon/turbo/transactions" ) +// AccountRangeMaxResults is the maximum number of results to be returned per call +const AccountRangeMaxResults = 256 + // PrivateDebugAPI Exposed RPC endpoints for debugging use type PrivateDebugAPI interface { StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex uint64, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) @@ -121,8 +123,8 @@ func (api *PrivateDebugAPIImpl) AccountRange(ctx context.Context, blockNrOrHash blockNumber = block.NumberU64() } - if maxResults > eth.AccountRangeMaxResults || maxResults <= 0 { - maxResults = eth.AccountRangeMaxResults + if maxResults > AccountRangeMaxResults || maxResults <= 0 { + maxResults = AccountRangeMaxResults } dumper := state.NewDumper(tx, blockNumber) diff --git a/cmd/rpcdaemon/main.go b/cmd/rpcdaemon/main.go index ccf6c87f5..eb24e1e28 100644 --- a/cmd/rpcdaemon/main.go +++ b/cmd/rpcdaemon/main.go @@ -6,7 +6,6 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/commands" - "github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters" "github.com/ledgerwatch/log/v3" "github.com/spf13/cobra" ) @@ -15,22 +14,18 @@ func main() { cmd, cfg := cli.RootCommand() rootCtx, rootCancel := common.RootContext() cmd.RunE = func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() logger := log.New() - db, borDb, backend, txPool, mining, starknet, stateCache, blockReader, err := cli.RemoteServices(cmd.Context(), *cfg, logger, rootCancel) + db, borDb, backend, txPool, mining, starknet, stateCache, blockReader, ff, err := cli.RemoteServices(ctx, *cfg, logger, rootCancel) if err != nil { log.Error("Could not connect to DB", "error", err) return nil } defer db.Close() + defer borDb.Close() - var ff *filters.Filters - if backend != nil { - ff = filters.New(rootCtx, backend, txPool, mining) - } else { - log.Info("filters are not supported in chaindata mode") - } - - if err := cli.StartRpcServer(cmd.Context(), *cfg, commands.APIList(cmd.Context(), db, borDb, backend, txPool, mining, starknet, ff, stateCache, blockReader, *cfg, nil)); err != nil { + apiList := commands.APIList(db, borDb, backend, txPool, mining, starknet, ff, stateCache, blockReader, *cfg, nil) + if err := cli.StartRpcServer(ctx, *cfg, apiList); err != nil { log.Error(err.Error()) return nil } diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index e6f041ad8..1f59ccb2a 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -206,7 +206,7 @@ func BorRLP(header *types.Header, c *params.BorConfig) []byte { type Bor struct { chainConfig *params.ChainConfig // Chain config config *params.BorConfig // Consensus engine configuration parameters for bor consensus - db kv.RwDB // Database to store and retrieve snapshot checkpoints + DB kv.RwDB // Database to store and retrieve snapshot checkpoints recents *lru.ARCCache // Snapshots for recent block to speed up reorgs signatures *lru.ARCCache // Signatures of recent blocks to speed up mining @@ -253,7 +253,7 @@ func New( c := &Bor{ chainConfig: chainConfig, config: borConfig, - db: db, + DB: db, recents: recents, signatures: signatures, validatorSetABI: vABI, @@ -442,7 +442,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co // If an on-disk checkpoint snapshot can be found, use that if number%checkpointInterval == 0 { - if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil { + if s, err := loadSnapshot(c.config, c.signatures, c.DB, hash); err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s break @@ -468,7 +468,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co // new snap shot snap = newSnapshot(c.config, c.signatures, number, hash, validators) - if err := snap.store(c.db); err != nil { + if err := snap.store(c.DB); err != nil { return nil, err } log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) @@ -514,7 +514,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co // If we've generated a new checkpoint snapshot, save to disk if snap.Number%checkpointInterval == 0 && len(headers) > 0 { - if err = snap.store(c.db); err != nil { + if err = snap.store(c.DB); err != nil { return nil, err } log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) @@ -908,6 +908,7 @@ func (c *Bor) APIs(chain consensus.ChainHeaderReader) []rpc.API { // Close implements consensus.Engine. It's a noop for bor as there are no background threads. func (c *Bor) Close() error { + c.DB.Close() return nil } diff --git a/eth/api.go b/eth/api.go index fbd0c1354..604f7bea3 100644 --- a/eth/api.go +++ b/eth/api.go @@ -15,6 +15,3 @@ // along with the go-ethereum library. If not, see . package eth - -// AccountRangeMaxResults is the maximum number of results to be returned per call -const AccountRangeMaxResults = 256 diff --git a/eth/backend.go b/eth/backend.go index 674656637..42e1dfbb9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -47,21 +47,18 @@ import ( txpool2 "github.com/ledgerwatch/erigon-lib/txpool" "github.com/ledgerwatch/erigon-lib/txpool/txpooluitl" "github.com/ledgerwatch/erigon/cmd/downloader/downloader" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/snapshotsynccli" - "github.com/ledgerwatch/log/v3" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - - "github.com/ledgerwatch/erigon/consensus/parlia" - "github.com/ledgerwatch/erigon/cmd/downloader/downloadergrpc" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/commands" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/ethash" + "github.com/ledgerwatch/erigon/consensus/parlia" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" @@ -81,7 +78,11 @@ import ( "github.com/ledgerwatch/erigon/turbo/shards" "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/snapshotsync/snapshothashes" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/snapshotsynccli" stages2 "github.com/ledgerwatch/erigon/turbo/stages" + "github.com/ledgerwatch/log/v3" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" ) // Config contains the configuration options of the ETH protocol. @@ -331,7 +332,7 @@ func New(stack *node.Node, config *ethconfig.Config, txpoolCfg txpool2.Config, l return nil, fmt.Errorf("new server: %w", err) } - backend.downloaderClient = downloadergrpc.NewClientDirect(bittorrentServer) + backend.downloaderClient = direct.NewDownloaderClient(bittorrentServer) } if err != nil { return nil, err @@ -526,6 +527,31 @@ func New(stack *node.Node, config *ethconfig.Config, txpoolCfg txpool2.Config, l } //eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) + // start HTTP API + httpRpcCfg := cli.Flags{} // TODO: add rpcdaemon cli flags to Erigon and fill this struct (or break it to smaller config objects) + ethRpcClient, txPoolRpcClient, miningRpcClient, starkNetRpcClient, stateCache, ff, err := cli.EmbeddedServices( + ctx, chainKv, httpRpcCfg.StateCache, blockReader, + ethBackendRPC, + backend.txPool2GrpcServer, + miningRPC, + ) + if err != nil { + return nil, err + } + + var borDb kv.RoDB + if casted, ok := backend.engine.(*bor.Bor); ok { + borDb = casted.DB + } + apiList := commands.APIList(chainKv, borDb, ethRpcClient, txPoolRpcClient, miningRpcClient, starkNetRpcClient, ff, stateCache, blockReader, httpRpcCfg, nil) + go func() { + _ = apiList + //if err := cli.StartRpcServer(ctx, httpRpcCfg, apiList); err != nil { + // log.Error(err.Error()) + // return + //} + }() + // Register the backend on the node stack.RegisterAPIs(backend.APIs()) stack.RegisterLifecycle(backend) diff --git a/go.mod b/go.mod index 86c024b0b..e6c594737 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/julienschmidt/httprouter v1.3.0 github.com/kevinburke/go-bindata v3.21.0+incompatible - github.com/ledgerwatch/erigon-lib v0.0.0-20220212030730-fc0a90f3b518 + github.com/ledgerwatch/erigon-lib v0.0.0-20220212114842-31982dacc8a5 github.com/ledgerwatch/log/v3 v3.4.0 github.com/ledgerwatch/secp256k1 v1.0.0 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect diff --git a/go.sum b/go.sum index be2a89e0f..403febb80 100644 --- a/go.sum +++ b/go.sum @@ -632,8 +632,8 @@ github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3P github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 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-20220212030730-fc0a90f3b518 h1:4SPtNxvC6AkdD6e5oLdIhTa770CEIDoj8xyMfDm/T0M= -github.com/ledgerwatch/erigon-lib v0.0.0-20220212030730-fc0a90f3b518/go.mod h1:NzHpr5GGDbLM/hYSU4BWB0INU6ZALzMzaqX4i03R6i0= +github.com/ledgerwatch/erigon-lib v0.0.0-20220212114842-31982dacc8a5 h1:P8LFJVTTfh3s+vjWa8g7tK8MyEF0fuIz+36Ksj1iAz8= +github.com/ledgerwatch/erigon-lib v0.0.0-20220212114842-31982dacc8a5/go.mod h1:phuzMr8tLvqjo5cQVA9jj8odAso6eLyS4LFmUJrDFGw= github.com/ledgerwatch/log/v3 v3.4.0 h1:SEIOcv5a2zkG3PmoT5jeTU9m/0nEUv0BJS5bzsjwKCI= github.com/ledgerwatch/log/v3 v3.4.0/go.mod h1:VXcz6Ssn6XEeU92dCMc39/g1F0OYAjw1Mt+dGP5DjXY= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ=