From aad0d0c777337cd35006f9f16bcb484099e01116 Mon Sep 17 00:00:00 2001 From: Alex Sharov <AskAlexSharov@gmail.com> Date: Sun, 14 Nov 2021 11:08:52 +0700 Subject: [PATCH] grpc GetBlock api (#2955) --- cmd/rpcdaemon/cli/config.go | 28 +++--- cmd/rpcdaemon/commands/call_traces_test.go | 9 +- .../commands/corner_cases_support_test.go | 5 +- cmd/rpcdaemon/commands/daemon.go | 4 +- cmd/rpcdaemon/commands/debug_api_test.go | 9 +- cmd/rpcdaemon/commands/eth_api.go | 15 +++- cmd/rpcdaemon/commands/eth_api_test.go | 23 ++--- cmd/rpcdaemon/commands/eth_call_test.go | 5 +- cmd/rpcdaemon/commands/eth_ming_test.go | 3 +- cmd/rpcdaemon/commands/eth_subscribe_test.go | 2 +- .../commands/send_transaction_test.go | 3 +- cmd/rpcdaemon/commands/trace_adhoc_test.go | 9 +- cmd/rpcdaemon/commands/txpool_api_test.go | 3 +- cmd/rpcdaemon/interfaces/interfaces.go | 13 +++ cmd/rpcdaemon/main.go | 4 +- cmd/rpcdaemon/rpcdaemontest/test_util.go | 2 +- cmd/rpcdaemon/services/eth_backend.go | 29 +++++- eth/backend.go | 2 +- ethdb/privateapi/ethbackend.go | 36 ++++++-- go.mod | 4 +- go.sum | 6 +- rpc/client_test.go | 6 +- rpc/service.go | 8 +- turbo/adapter/block_getter.go | 24 ----- turbo/adapter/chain_context.go | 90 ------------------- turbo/snapshotsync/block_reader.go | 27 ++++++ 26 files changed, 187 insertions(+), 182 deletions(-) create mode 100644 cmd/rpcdaemon/interfaces/interfaces.go delete mode 100644 turbo/adapter/block_getter.go delete mode 100644 turbo/adapter/chain_context.go create mode 100644 turbo/snapshotsync/block_reader.go diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index a540519cd3..b344eaf91f 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -19,12 +19,14 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/remotedb" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/health" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/services" "github.com/ledgerwatch/erigon/cmd/utils" "github.com/ledgerwatch/erigon/common/paths" "github.com/ledgerwatch/erigon/internal/debug" "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/log/v3" "github.com/spf13/cobra" "google.golang.org/grpc" @@ -213,23 +215,25 @@ func checkDbCompatibility(ctx context.Context, db kv.RoDB) error { return nil } -func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) (db kv.RoDB, eth services.ApiBackend, txPool *services.TxPoolService, mining *services.MiningService, stateCache kvcache.Cache, err error) { +func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) (db kv.RoDB, eth services.ApiBackend, txPool *services.TxPoolService, mining *services.MiningService, stateCache kvcache.Cache, blockReader interfaces.BlockReader, err error) { if !cfg.SingleNodeMode && cfg.PrivateApiAddr == "" { - return nil, nil, nil, nil, nil, fmt.Errorf("either remote db or local db must be specified") + return nil, nil, nil, nil, nil, nil, 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 "" // If PrivateApiAddr is checked first, the Chaindata option will never work if cfg.SingleNodeMode { var rwKv kv.RwDB rwKv, err = kv2.NewMDBX(logger).Path(cfg.Chaindata).Readonly().Open() if err != nil { - return nil, nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, nil, err } if compatErr := checkDbCompatibility(ctx, rwKv); compatErr != nil { - return nil, nil, nil, nil, nil, compatErr + return nil, nil, nil, nil, nil, nil, compatErr } db = rwKv stateCache = kvcache.NewDummy() + blockReader = snapshotsync.NewBlockReader() } else { if cfg.StateCache.KeysLimit > 0 { stateCache = kvcache.New(cfg.StateCache) @@ -240,32 +244,34 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance } if cfg.PrivateApiAddr == "" { - return db, eth, txPool, mining, stateCache, nil + return db, eth, txPool, mining, stateCache, blockReader, nil } creds, err := grpcutil.TLS(cfg.TLSCACert, cfg.TLSCertfile, cfg.TLSKeyFile) if err != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("open tls cert: %w", err) + return nil, nil, nil, nil, nil, nil, fmt.Errorf("open tls cert: %w", err) } conn, err := grpcutil.Connect(creds, cfg.PrivateApiAddr) if err != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to execution service privateApi: %w", err) + return nil, nil, nil, nil, nil, nil, 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, fmt.Errorf("could not connect to remoteKv: %w", err) + return nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to remoteKv: %w", err) } subscribeToStateChangesLoop(ctx, kvClient, stateCache) - remoteEth := services.NewRemoteBackend(conn) + remoteEth := services.NewRemoteBackend(conn, db) + blockReader = remoteEth + txpoolConn := conn if cfg.TxPoolV2 { txpoolConn, err = grpcutil.Connect(creds, cfg.TxPoolApiAddr) if err != nil { - return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to txpool api: %w", err) + return nil, nil, nil, nil, nil, nil, fmt.Errorf("could not connect to txpool api: %w", err) } } mining = services.NewMiningService(txpoolConn) @@ -288,7 +294,7 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance rootCancel() } }() - return db, eth, txPool, mining, stateCache, err + return db, eth, txPool, mining, stateCache, blockReader, err } func StartRpcServer(ctx context.Context, cfg Flags, rpcAPI []rpc.API) error { diff --git a/cmd/rpcdaemon/commands/call_traces_test.go b/cmd/rpcdaemon/commands/call_traces_test.go index f96f7e65b6..95ebddb27e 100644 --- a/cmd/rpcdaemon/commands/call_traces_test.go +++ b/cmd/rpcdaemon/commands/call_traces_test.go @@ -11,6 +11,7 @@ import ( "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/hexutil" "github.com/ledgerwatch/erigon/core" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/stages" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/assert" @@ -50,7 +51,9 @@ func TestCallTraceOneByOne(t *testing.T) { if err != nil { t.Fatalf("generate chain: %v", err) } - api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), false), m.DB, &cli.Flags{}) + api := NewTraceAPI( + NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), snapshotsync.NewBlockReader(), false), + m.DB, &cli.Flags{}) // Insert blocks 1 by 1, to tirgget possible "off by one" errors for i := 0; i < chain.Length; i++ { if err = m.InsertChain(chain.Slice(i, i+1)); err != nil { @@ -95,7 +98,7 @@ func TestCallTraceUnwind(t *testing.T) { if err != nil { t.Fatalf("generate chainB: %v", err) } - api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), false), m.DB, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), snapshotsync.NewBlockReader(), false), m.DB, &cli.Flags{}) if err = m.InsertChain(chainA); err != nil { t.Fatalf("inserting chainA: %v", err) } @@ -155,7 +158,7 @@ func TestFilterNoAddresses(t *testing.T) { if err != nil { t.Fatalf("generate chain: %v", err) } - api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), false), m.DB, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig), snapshotsync.NewBlockReader(), false), m.DB, &cli.Flags{}) // Insert blocks 1 by 1, to tirgget possible "off by one" errors for i := 0; i < chain.Length; i++ { if err = m.InsertChain(chain.Slice(i, i+1)); err != nil { diff --git a/cmd/rpcdaemon/commands/corner_cases_support_test.go b/cmd/rpcdaemon/commands/corner_cases_support_test.go index e4dd2c95f2..1ab11b66ca 100644 --- a/cmd/rpcdaemon/commands/corner_cases_support_test.go +++ b/cmd/rpcdaemon/commands/corner_cases_support_test.go @@ -8,6 +8,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/stretchr/testify/require" ) @@ -18,7 +19,9 @@ func TestNotFoundMustReturnNil(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) defer db.Close() stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI( + NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), + db, nil, nil, nil, 5000000) ctx := context.Background() a, err := api.GetTransactionByBlockNumberAndIndex(ctx, 10_000, 1) diff --git a/cmd/rpcdaemon/commands/daemon.go b/cmd/rpcdaemon/commands/daemon.go index a32f54c466..674ed8e145 100644 --- a/cmd/rpcdaemon/commands/daemon.go +++ b/cmd/rpcdaemon/commands/daemon.go @@ -8,6 +8,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/kvcache" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/services" "github.com/ledgerwatch/erigon/rpc" ) @@ -16,10 +17,11 @@ import ( func APIList(ctx context.Context, db kv.RoDB, eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, filters *filters.Filters, stateCache kvcache.Cache, + blockReader interfaces.BlockReader, cfg cli.Flags, customAPIList []rpc.API) []rpc.API { var defaultAPIList []rpc.API - base := NewBaseApi(filters, stateCache, cfg.SingleNodeMode) + base := NewBaseApi(filters, stateCache, blockReader, cfg.SingleNodeMode) if cfg.TevmEnabled { base.EnableTevmExperiment() } diff --git a/cmd/rpcdaemon/commands/debug_api_test.go b/cmd/rpcdaemon/commands/debug_api_test.go index a0eff1db45..cbba7364c0 100644 --- a/cmd/rpcdaemon/commands/debug_api_test.go +++ b/cmd/rpcdaemon/commands/debug_api_test.go @@ -12,6 +12,7 @@ import ( "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/eth/tracers" "github.com/ledgerwatch/erigon/internal/ethapi" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" ) var debugTraceTransactionTests = []struct { @@ -39,7 +40,9 @@ var debugTraceTransactionNoRefundTests = []struct { func TestTraceTransaction(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewPrivateDebugAPI(NewBaseApi(nil, stateCache, false), db, 0) + api := NewPrivateDebugAPI( + NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), + db, 0) for _, tt := range debugTraceTransactionTests { var buf bytes.Buffer stream := jsoniter.NewStream(jsoniter.ConfigDefault, &buf, 4096) @@ -69,7 +72,9 @@ func TestTraceTransaction(t *testing.T) { func TestTraceTransactionNoRefund(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewPrivateDebugAPI(NewBaseApi(nil, stateCache, false), db, 0) + api := NewPrivateDebugAPI( + NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), + db, 0) for _, tt := range debugTraceTransactionNoRefundTests { var buf bytes.Buffer stream := jsoniter.NewStream(jsoniter.ConfigDefault, &buf, 4096) diff --git a/cmd/rpcdaemon/commands/eth_api.go b/cmd/rpcdaemon/commands/eth_api.go index 6647b05e86..b960c0b77b 100644 --- a/cmd/rpcdaemon/commands/eth_api.go +++ b/cmd/rpcdaemon/commands/eth_api.go @@ -12,6 +12,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/kvcache" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters" + "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/services" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/hexutil" @@ -105,10 +106,11 @@ type BaseAPI struct { _genesis *types.Block _genesisLock sync.RWMutex - TevmEnabled bool // experiment + _blockReader interfaces.BlockReader + TevmEnabled bool // experiment } -func NewBaseApi(f *filters.Filters, stateCache kvcache.Cache, singleNodeMode bool) *BaseAPI { +func NewBaseApi(f *filters.Filters, stateCache kvcache.Cache, blockReader interfaces.BlockReader, singleNodeMode bool) *BaseAPI { blocksLRUSize := 128 // ~32Mb if !singleNodeMode { blocksLRUSize = 512 @@ -118,7 +120,7 @@ func NewBaseApi(f *filters.Filters, stateCache kvcache.Cache, singleNodeMode boo panic(err) } - return &BaseAPI{filters: f, stateCache: stateCache, blocksLRU: blocksLRU} + return &BaseAPI{filters: f, stateCache: stateCache, blocksLRU: blocksLRU, _blockReader: blockReader} } func (api *BaseAPI) chainConfig(tx kv.Tx) (*params.ChainConfig, error) { @@ -159,13 +161,18 @@ func (api *BaseAPI) blockWithSenders(tx kv.Tx, hash common.Hash, number uint64) return it.(*types.Block), nil } } - block, _, err := rawdb.ReadBlockWithSenders(tx, hash, number) + block, _, err := api._blockReader.BlockWithSenders(context.Background(), tx, hash, number) if err != nil { return nil, err } if block == nil { // don't save nil's to cache return nil, nil } + // don't save empty blocks to cache, because in Erigon + // if block become non-canonical - we remove it's transactions, but block can become canonical in future + if block.Transactions().Len() == 0 { + return block, nil + } if api.blocksLRU != nil { api.blocksLRU.Add(hash, block) } diff --git a/cmd/rpcdaemon/commands/eth_api_test.go b/cmd/rpcdaemon/commands/eth_api_test.go index 7b31dc7f8a..de678d383e 100644 --- a/cmd/rpcdaemon/commands/eth_api_test.go +++ b/cmd/rpcdaemon/commands/eth_api_test.go @@ -8,6 +8,7 @@ import ( "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/internal/ethapi" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/stretchr/testify/assert" "github.com/ledgerwatch/erigon-lib/kv/kvcache" @@ -18,7 +19,7 @@ import ( func TestGetTransactionReceipt(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) // Call GetTransactionReceipt for transaction which is not in the database if _, err := api.GetTransactionReceipt(context.Background(), common.Hash{}); err != nil { t.Errorf("calling GetTransactionReceipt with empty hash: %v", err) @@ -28,7 +29,7 @@ func TestGetTransactionReceipt(t *testing.T) { func TestGetTransactionReceiptUnprotected(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) // Call GetTransactionReceipt for un-protected transaction if _, err := api.GetTransactionReceipt(context.Background(), common.HexToHash("0x3f3cb8a0e13ed2481f97f53f7095b9cbc78b6ffb779f2d3e565146371a8830ea")); err != nil { t.Errorf("calling GetTransactionReceipt for unprotected tx: %v", err) @@ -41,7 +42,7 @@ func TestGetStorageAt_ByBlockNumber_WithRequireCanonicalDefault(t *testing.T) { assert := assert.New(t) db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithNumber(0)) @@ -57,7 +58,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault(t *testing.T) { m, _, _ := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), false)) @@ -73,7 +74,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue(t *testing.T) { m, _, _ := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") result, err := api.GetStorageAt(context.Background(), addr, "0x0", rpc.BlockNumberOrHashWithHash(m.Genesis.Hash(), true)) @@ -88,7 +89,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault_BlockNotFoundError m, _, _ := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") offChain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, block *core.BlockGen) { @@ -111,7 +112,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue_BlockNotFoundError(t m, _, _ := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") offChain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, block *core.BlockGen) { @@ -135,7 +136,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalDefault_NonCanonicalBlock( m, _, orphanedChain := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") orphanedBlock := orphanedChain[0].Blocks[0] @@ -152,7 +153,7 @@ func TestGetStorageAt_ByBlockHash_WithRequireCanonicalTrue_NonCanonicalBlock(t * m, _, orphanedChain := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) addr := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") orphanedBlock := orphanedChain[0].Blocks[0] @@ -170,7 +171,7 @@ func TestCall_ByBlockHash_WithRequireCanonicalDefault_NonCanonicalBlock(t *testi m, _, orphanedChain := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) from := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") to := common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e") @@ -195,7 +196,7 @@ func TestCall_ByBlockHash_WithRequireCanonicalTrue_NonCanonicalBlock(t *testing. m, _, orphanedChain := rpcdaemontest.CreateTestSentry(t) db := m.DB stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) from := common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") to := common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e") diff --git a/cmd/rpcdaemon/commands/eth_call_test.go b/cmd/rpcdaemon/commands/eth_call_test.go index aee770f868..b0c7ec1602 100644 --- a/cmd/rpcdaemon/commands/eth_call_test.go +++ b/cmd/rpcdaemon/commands/eth_call_test.go @@ -10,12 +10,13 @@ import ( "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/internal/ethapi" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" ) func TestEstimateGas(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) var from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") var to = common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e") if _, err := api.EstimateGas(context.Background(), ethapi.CallArgs{ @@ -29,7 +30,7 @@ func TestEstimateGas(t *testing.T) { func TestEthCallNonCanonical(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(nil, stateCache, false), db, nil, nil, nil, 5000000) + api := NewEthAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, nil, nil, nil, 5000000) var from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") var to = common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e") if _, err := api.Call(context.Background(), ethapi.CallArgs{ diff --git a/cmd/rpcdaemon/commands/eth_ming_test.go b/cmd/rpcdaemon/commands/eth_ming_test.go index 35e734ed28..f46e2638ca 100644 --- a/cmd/rpcdaemon/commands/eth_ming_test.go +++ b/cmd/rpcdaemon/commands/eth_ming_test.go @@ -11,6 +11,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/stages" "github.com/stretchr/testify/require" ) @@ -20,7 +21,7 @@ func TestPendingBlock(t *testing.T) { mining := txpool.NewMiningClient(conn) ff := filters.New(ctx, nil, nil, mining) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewEthAPI(NewBaseApi(ff, stateCache, false), nil, nil, nil, mining, 5000000) + api := NewEthAPI(NewBaseApi(ff, stateCache, snapshotsync.NewBlockReader(), false), nil, nil, nil, mining, 5000000) expect := uint64(12345) b, err := rlp.EncodeToBytes(types.NewBlockWithHeader(&types.Header{Number: big.NewInt(int64(expect))})) require.NoError(t, err) diff --git a/cmd/rpcdaemon/commands/eth_subscribe_test.go b/cmd/rpcdaemon/commands/eth_subscribe_test.go index 85bd8dd977..41ff3afbc6 100644 --- a/cmd/rpcdaemon/commands/eth_subscribe_test.go +++ b/cmd/rpcdaemon/commands/eth_subscribe_test.go @@ -36,7 +36,7 @@ func TestEthSubscribe(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed ctx, conn := rpcdaemontest.CreateTestGrpcConn(t, m) - backend := services.NewRemoteBackend(conn) + backend := services.NewRemoteBackend(conn, m.DB) ff := filters.New(ctx, backend, nil, nil) newHeads := make(chan *types.Header) diff --git a/cmd/rpcdaemon/commands/send_transaction_test.go b/cmd/rpcdaemon/commands/send_transaction_test.go index 3f0873f59f..e1b39b775f 100644 --- a/cmd/rpcdaemon/commands/send_transaction_test.go +++ b/cmd/rpcdaemon/commands/send_transaction_test.go @@ -20,6 +20,7 @@ import ( "github.com/ledgerwatch/erigon/eth/protocols/eth" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/stages" "github.com/stretchr/testify/require" ) @@ -71,7 +72,7 @@ func TestSendRawTransaction(t *testing.T) { txPool := txpool.NewTxpoolClient(conn) ff := filters.New(ctx, nil, txPool, txpool.NewMiningClient(conn)) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := commands.NewEthAPI(commands.NewBaseApi(ff, stateCache, false), m.DB, nil, txPool, nil, 5000000) + api := commands.NewEthAPI(commands.NewBaseApi(ff, stateCache, snapshotsync.NewBlockReader(), false), m.DB, nil, txPool, nil, 5000000) buf := bytes.NewBuffer(nil) err = txn.MarshalBinary(buf) diff --git a/cmd/rpcdaemon/commands/trace_adhoc_test.go b/cmd/rpcdaemon/commands/trace_adhoc_test.go index 050c5b4e70..efa5c53a1b 100644 --- a/cmd/rpcdaemon/commands/trace_adhoc_test.go +++ b/cmd/rpcdaemon/commands/trace_adhoc_test.go @@ -13,13 +13,14 @@ import ( "github.com/ledgerwatch/erigon/common/hexutil" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/stretchr/testify/require" ) func TestEmptyQuery(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewTraceAPI(NewBaseApi(nil, stateCache, false), db, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, &cli.Flags{}) // Call GetTransactionReceipt for transaction which is not in the database var latest = rpc.LatestBlockNumber results, err := api.CallMany(context.Background(), json.RawMessage("[]"), &rpc.BlockNumberOrHash{BlockNumber: &latest}) @@ -36,7 +37,7 @@ func TestEmptyQuery(t *testing.T) { func TestCoinbaseBalance(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewTraceAPI(NewBaseApi(nil, stateCache, false), db, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, &cli.Flags{}) // Call GetTransactionReceipt for transaction which is not in the database var latest = rpc.LatestBlockNumber results, err := api.CallMany(context.Background(), json.RawMessage(` @@ -63,7 +64,7 @@ func TestCoinbaseBalance(t *testing.T) { func TestReplayTransaction(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewTraceAPI(NewBaseApi(nil, stateCache, false), db, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, &cli.Flags{}) var txnHash common.Hash if err := db.View(context.Background(), func(tx kv.Tx) error { b, err := rawdb.ReadBlockByNumber(tx, 6) @@ -91,7 +92,7 @@ func TestReplayTransaction(t *testing.T) { func TestReplayBlockTransactions(t *testing.T) { db := rpcdaemontest.CreateTestKV(t) stateCache := kvcache.New(kvcache.DefaultCoherentConfig) - api := NewTraceAPI(NewBaseApi(nil, stateCache, false), db, &cli.Flags{}) + api := NewTraceAPI(NewBaseApi(nil, stateCache, snapshotsync.NewBlockReader(), false), db, &cli.Flags{}) // Call GetTransactionReceipt for transaction which is not in the database n := rpc.BlockNumber(6) diff --git a/cmd/rpcdaemon/commands/txpool_api_test.go b/cmd/rpcdaemon/commands/txpool_api_test.go index 95d4a52e21..37cb68187e 100644 --- a/cmd/rpcdaemon/commands/txpool_api_test.go +++ b/cmd/rpcdaemon/commands/txpool_api_test.go @@ -16,6 +16,7 @@ import ( "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/stages" "github.com/stretchr/testify/require" ) @@ -32,7 +33,7 @@ func TestTxPoolContent(t *testing.T) { ctx, conn := rpcdaemontest.CreateTestGrpcConn(t, m) txPool := txpool.NewTxpoolClient(conn) ff := filters.New(ctx, nil, txPool, txpool.NewMiningClient(conn)) - api := NewTxPoolAPI(NewBaseApi(ff, kvcache.New(kvcache.DefaultCoherentConfig), false), m.DB, txPool) + api := NewTxPoolAPI(NewBaseApi(ff, kvcache.New(kvcache.DefaultCoherentConfig), snapshotsync.NewBlockReader(), false), m.DB, txPool) expectValue := uint64(1234) txn, err := types.SignTx(types.NewTransaction(0, common.Address{1}, uint256.NewInt(expectValue), params.TxGas, uint256.NewInt(10*params.GWei), nil), *types.LatestSignerForChainID(m.ChainConfig.ChainID), m.Key) diff --git a/cmd/rpcdaemon/interfaces/interfaces.go b/cmd/rpcdaemon/interfaces/interfaces.go new file mode 100644 index 0000000000..1a1be7cc3c --- /dev/null +++ b/cmd/rpcdaemon/interfaces/interfaces.go @@ -0,0 +1,13 @@ +package interfaces + +import ( + "context" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/common" + "github.com/ledgerwatch/erigon/core/types" +) + +type BlockReader interface { + BlockWithSenders(ctx context.Context, tx kv.Tx, hash common.Hash, blockHeight uint64) (block *types.Block, senders []common.Address, err error) +} diff --git a/cmd/rpcdaemon/main.go b/cmd/rpcdaemon/main.go index a9b525d95f..bb3bab5023 100644 --- a/cmd/rpcdaemon/main.go +++ b/cmd/rpcdaemon/main.go @@ -16,7 +16,7 @@ func main() { rootCtx, rootCancel := utils.RootContext() cmd.RunE = func(cmd *cobra.Command, args []string) error { logger := log.New() - db, backend, txPool, mining, stateCache, err := cli.RemoteServices(cmd.Context(), *cfg, logger, rootCancel) + db, backend, txPool, mining, stateCache, blockReader, err := cli.RemoteServices(cmd.Context(), *cfg, logger, rootCancel) if err != nil { log.Error("Could not connect to DB", "error", err) return nil @@ -30,7 +30,7 @@ func main() { log.Info("filters are not supported in chaindata mode") } - if err := cli.StartRpcServer(cmd.Context(), *cfg, commands.APIList(cmd.Context(), db, backend, txPool, mining, ff, stateCache, *cfg, nil)); err != nil { + if err := cli.StartRpcServer(cmd.Context(), *cfg, commands.APIList(cmd.Context(), db, backend, txPool, mining, ff, stateCache, blockReader, *cfg, nil)); err != nil { log.Error(err.Error()) return nil } diff --git a/cmd/rpcdaemon/rpcdaemontest/test_util.go b/cmd/rpcdaemon/rpcdaemontest/test_util.go index 81b7407fc6..fd5054109b 100644 --- a/cmd/rpcdaemon/rpcdaemontest/test_util.go +++ b/cmd/rpcdaemon/rpcdaemontest/test_util.go @@ -220,7 +220,7 @@ func CreateTestGrpcConn(t *testing.T, m *stages.MockSentry) (context.Context, *g ethashApi := apis[1].Service.(*ethash.API) server := grpc.NewServer() - remote.RegisterETHBACKENDServer(server, privateapi.NewEthBackendServer(ctx, nil, m.Notifications.Events)) + remote.RegisterETHBACKENDServer(server, privateapi.NewEthBackendServer(ctx, nil, m.DB, m.Notifications.Events)) txpool.RegisterTxpoolServer(server, m.TxPoolV2GrpcServer) txpool.RegisterMiningServer(server, privateapi.NewMiningServer(ctx, &IsMiningMock{}, ethashApi)) listener := bufconn.Listen(1024 * 1024) diff --git a/cmd/rpcdaemon/services/eth_backend.go b/cmd/rpcdaemon/services/eth_backend.go index 6b3a45430b..397446a49d 100644 --- a/cmd/rpcdaemon/services/eth_backend.go +++ b/cmd/rpcdaemon/services/eth_backend.go @@ -1,6 +1,7 @@ package services import ( + "bytes" "context" "errors" "fmt" @@ -8,8 +9,11 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common" + "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/ethdb/privateapi" + "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/log/v3" "google.golang.org/grpc" "google.golang.org/grpc/status" @@ -26,19 +30,22 @@ type ApiBackend interface { ProtocolVersion(ctx context.Context) (uint64, error) ClientVersion(ctx context.Context) (string, error) Subscribe(ctx context.Context, cb func(*remote.SubscribeReply)) error + BlockWithSenders(ctx context.Context, tx kv.Tx, hash common.Hash, blockHeight uint64) (block *types.Block, senders []common.Address, err error) } type RemoteBackend struct { remoteEthBackend remote.ETHBACKENDClient log log.Logger version gointerfaces.Version + db kv.RoDB } -func NewRemoteBackend(cc grpc.ClientConnInterface) *RemoteBackend { +func NewRemoteBackend(cc grpc.ClientConnInterface, db kv.RoDB) *RemoteBackend { return &RemoteBackend{ remoteEthBackend: remote.NewETHBACKENDClient(cc), version: gointerfaces.VersionFromProto(privateapi.EthBackendAPIVersion), log: log.New("remote_service", "eth_backend"), + db: db, } } @@ -141,3 +148,23 @@ func (back *RemoteBackend) Subscribe(ctx context.Context, onNewEvent func(*remot } return nil } + +func (back *RemoteBackend) BlockWithSenders(ctx context.Context, _ kv.Tx, hash common.Hash, blockHeight uint64) (block *types.Block, senders []common.Address, err error) { + reply, err := back.remoteEthBackend.Block(ctx, &remote.BlockRequest{BlockHash: gointerfaces.ConvertHashToH256(hash), BlockHeight: blockHeight}) + if err != nil { + return nil, nil, err + } + block = &types.Block{} + err = rlp.Decode(bytes.NewReader(reply.BlockRlp), block) + if err != nil { + return nil, nil, err + } + senders = make([]common.Address, len(reply.Senders)/20) + for i := range senders { + senders[i].SetBytes(reply.Senders[i*20 : (i+1)*20]) + } + if len(senders) == block.Transactions().Len() { //it's fine if no senders provided - they can be lazy recovered + block.SendersToTxs(senders) + } + return block, senders, nil +} diff --git a/eth/backend.go b/eth/backend.go index 367aa21995..67bb28e2be 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -374,7 +374,7 @@ func New(stack *node.Node, config *ethconfig.Config, logger log.Logger) (*Ethere ethashApi = casted.APIs(nil)[1].Service.(*ethash.API) } - ethBackendRPC := privateapi.NewEthBackendServer(ctx, backend, backend.notifications.Events) + ethBackendRPC := privateapi.NewEthBackendServer(ctx, backend, backend.chainDB, backend.notifications.Events) miningRPC = privateapi.NewMiningServer(ctx, backend, ethashApi) if stack.Config().PrivateApiAddr != "" { var creds credentials.TransportCredentials diff --git a/ethdb/privateapi/ethbackend.go b/ethdb/privateapi/ethbackend.go index c9967323fa..41277d8a44 100644 --- a/ethdb/privateapi/ethbackend.go +++ b/ethdb/privateapi/ethbackend.go @@ -7,10 +7,12 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" types2 "github.com/ledgerwatch/erigon-lib/gointerfaces/types" + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/log/v3" "google.golang.org/protobuf/types/known/emptypb" ) @@ -23,9 +25,11 @@ var EthBackendAPIVersion = &types2.VersionReply{Major: 2, Minor: 1, Patch: 0} type EthBackendServer struct { remote.UnimplementedETHBACKENDServer // must be embedded to have forward compatible implementations. - ctx context.Context - eth EthBackend - events *Events + ctx context.Context + eth EthBackend + events *Events + db kv.RoDB + blockReader *snapshotsync.BlockReader } type EthBackend interface { @@ -34,8 +38,8 @@ type EthBackend interface { NetPeerCount() (uint64, error) } -func NewEthBackendServer(ctx context.Context, eth EthBackend, events *Events) *EthBackendServer { - return &EthBackendServer{ctx: ctx, eth: eth, events: events} +func NewEthBackendServer(ctx context.Context, eth EthBackend, db kv.RoDB, events *Events) *EthBackendServer { + return &EthBackendServer{ctx: ctx, eth: eth, events: events, db: db, blockReader: snapshotsync.NewBlockReader()} } func (s *EthBackendServer) Version(context.Context, *emptypb.Empty) (*types2.VersionReply, error) { @@ -121,3 +125,25 @@ func (s *EthBackendServer) ProtocolVersion(_ context.Context, _ *remote.Protocol func (s *EthBackendServer) ClientVersion(_ context.Context, _ *remote.ClientVersionRequest) (*remote.ClientVersionReply, error) { return &remote.ClientVersionReply{NodeName: common.MakeName("erigon", params.Version)}, nil } + +func (s *EthBackendServer) Block(ctx context.Context, req *remote.BlockRequest) (*remote.BlockReply, error) { + tx, err := s.db.BeginRo(ctx) + if err != nil { + return nil, err + } + defer tx.Rollback() + + block, senders, err := s.blockReader.BlockWithSenders(ctx, tx, gointerfaces.ConvertH256ToHash(req.BlockHash), req.BlockHeight) + if err != nil { + return nil, err + } + blockRlp, err := rlp.EncodeToBytes(block) + if err != nil { + return nil, err + } + sendersBytes := make([]byte, 20*len(senders)) + for i := range senders { + sendersBytes = append(sendersBytes, senders[i][:]...) + } + return &remote.BlockReply{BlockRlp: blockRlp, Senders: sendersBytes}, nil +} diff --git a/go.mod b/go.mod index d5be411418..41e78d3214 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,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-20211110145339-ab66a02f5284 + github.com/ledgerwatch/erigon-lib v0.0.0-20211114031802-6f8b7293f1de github.com/ledgerwatch/log/v3 v3.4.0 github.com/ledgerwatch/secp256k1 v1.0.0 github.com/logrusorgru/aurora/v3 v3.0.0 @@ -64,4 +64,4 @@ require ( gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 pgregory.net/rapid v0.4.7 -) \ No newline at end of file +) diff --git a/go.sum b/go.sum index 5564c91b02..c86a13b6da 100644 --- a/go.sum +++ b/go.sum @@ -596,8 +596,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-20211110145339-ab66a02f5284 h1:YV9tJXU5LB7UaVI6CLoSVxk56MaPQGZoaXjzu7me9Sg= -github.com/ledgerwatch/erigon-lib v0.0.0-20211110145339-ab66a02f5284/go.mod h1:CuEZROm43MykZT5CjCj02jw0FOwaDl8Nh+PZkTEGopg= +github.com/ledgerwatch/erigon-lib v0.0.0-20211114031802-6f8b7293f1de h1:zGmryhCgTlnnHBWN1u0m1R6P6NRKf/iszVniVNYXRpU= +github.com/ledgerwatch/erigon-lib v0.0.0-20211114031802-6f8b7293f1de/go.mod h1:CuEZROm43MykZT5CjCj02jw0FOwaDl8Nh+PZkTEGopg= 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= @@ -1514,4 +1514,4 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= \ No newline at end of file +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/rpc/client_test.go b/rpc/client_test.go index 4a00912987..c3a2e7118d 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -24,13 +24,13 @@ import ( "net/http" "net/http/httptest" "reflect" - "runtime" "strings" "sync" "testing" "time" "github.com/davecgh/go-spew/spew" + "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/log/v3" ) @@ -259,10 +259,8 @@ func TestClientSubscribeInvalidArg(t *testing.T) { } if !shouldPanic && err != nil { t.Errorf("EthSubscribe shouldn't have panicked for %#v", arg) - buf := make([]byte, 1024*1024) - buf = buf[:runtime.Stack(buf, false)] t.Error(err) - t.Error(string(buf)) + t.Error(dbg.Stack()) } }() client.EthSubscribe(context.Background(), arg, "foo_bar") diff --git a/rpc/service.go b/rpc/service.go index b0b0e08f3c..25b01a9e72 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -21,7 +21,7 @@ import ( "errors" "fmt" "reflect" - "runtime" + "runtime/debug" "strings" "sync" "unicode" @@ -214,12 +214,8 @@ func (c *callback) call(ctx context.Context, method string, args []reflect.Value // Catch panic while running the callback. defer func() { if err := recover(); err != nil { - const size = 64 << 10 - buf := make([]byte, size) - buf = buf[:runtime.Stack(buf, false)] - log.Error("RPC method " + method + " crashed: " + fmt.Sprintf("%v\n%s", err, buf)) + log.Error("RPC method " + method + " crashed: " + fmt.Sprintf("%v\n%s", err, debug.Stack())) errRes = errors.New("method handler crashed") - //debug.WriteStackTraceOnPanic(string(buf)) } }() // Run the callback. diff --git a/turbo/adapter/block_getter.go b/turbo/adapter/block_getter.go deleted file mode 100644 index c92fa56d54..0000000000 --- a/turbo/adapter/block_getter.go +++ /dev/null @@ -1,24 +0,0 @@ -package adapter - -import ( - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/common" - "github.com/ledgerwatch/erigon/core/rawdb" - "github.com/ledgerwatch/erigon/core/types" -) - -func NewBlockGetter(tx kv.Tx) *blockGetter { - return &blockGetter{tx} -} - -type blockGetter struct { - tx kv.Tx -} - -func (g *blockGetter) GetBlockByHash(hash common.Hash) (*types.Block, error) { - return rawdb.ReadBlockByHash(g.tx, hash) -} - -func (g *blockGetter) GetBlock(hash common.Hash, number uint64) *types.Block { - return rawdb.ReadBlock(g.tx, hash, number) -} diff --git a/turbo/adapter/chain_context.go b/turbo/adapter/chain_context.go deleted file mode 100644 index 8224efd258..0000000000 --- a/turbo/adapter/chain_context.go +++ /dev/null @@ -1,90 +0,0 @@ -package adapter - -import ( - "math/big" - - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/common" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/core/rawdb" - "github.com/ledgerwatch/erigon/core/state" - "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/params" - "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/erigon/rpc" -) - -type chainContext struct { - tx kv.Tx -} - -func NewChainContext(tx kv.Tx) *chainContext { - return &chainContext{ - tx: tx, - } -} - -type powEngine struct { -} - -func (c *powEngine) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - - panic("must not be called") -} -func (c *powEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) error { - panic("must not be called") -} -func (c *powEngine) VerifyUncles(chain consensus.ChainReader, block *types.Header, uncles []*types.Header) error { - panic("must not be called") -} -func (c *powEngine) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { - panic("must not be called") -} -func (c *powEngine) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - panic("must not be called") -} -func (c *powEngine) Initialize(config *params.ChainConfig, chain consensus.ChainHeaderReader, e consensus.EpochReader, header *types.Header, txs []types.Transaction, uncles []*types.Header, syscall consensus.SystemCall) { - panic("must not be called") -} -func (c *powEngine) Finalize(config *params.ChainConfig, header *types.Header, state *state.IntraBlockState, txs []types.Transaction, uncles []*types.Header, r types.Receipts, e consensus.EpochReader, chain consensus.ChainHeaderReader, syscall consensus.SystemCall) error { - panic("must not be called") -} -func (c *powEngine) FinalizeAndAssemble(chainConfig *params.ChainConfig, header *types.Header, state *state.IntraBlockState, - txs []types.Transaction, uncles []*types.Header, receipts types.Receipts, - e consensus.EpochReader, h consensus.ChainHeaderReader, syscall consensus.SystemCall, call consensus.Call) (*types.Block, error) { - panic("must not be called") -} - -func (c *powEngine) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - panic("must not be called") -} -func (c *powEngine) SealHash(header *types.Header) common.Hash { - panic("must not be called") -} - -func (c *powEngine) GenerateSeal(chain consensus.ChainHeaderReader, currnt, parent *types.Header, call consensus.Call) []rlp.RawValue { - return nil -} - -func (c *powEngine) CalcDifficulty(chain consensus.ChainHeaderReader, time, parentTime uint64, parentDifficulty *big.Int, parentNumber uint64, parentHash, parentUncleHash common.Hash, _ []rlp.RawValue) *big.Int { - panic("must not be called") -} -func (c *powEngine) APIs(chain consensus.ChainHeaderReader) []rpc.API { - panic("must not be called") -} - -func (c *powEngine) Close() error { - panic("must not be called") -} - -func (c *powEngine) Author(header *types.Header) (common.Address, error) { - return header.Coinbase, nil -} - -func (c *chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { - return rawdb.ReadHeader(c.tx, hash, number) -} - -func (c *chainContext) Engine() consensus.Engine { - return &powEngine{} -} diff --git a/turbo/snapshotsync/block_reader.go b/turbo/snapshotsync/block_reader.go new file mode 100644 index 0000000000..83f2efacfd --- /dev/null +++ b/turbo/snapshotsync/block_reader.go @@ -0,0 +1,27 @@ +package snapshotsync + +import ( + "context" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/common" + "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/types" +) + +// BlockReader can read blocks from db and snapshots +type BlockReader struct { +} + +func NewBlockReader() *BlockReader { + return &BlockReader{} +} + +func (back *BlockReader) BlockWithSenders(ctx context.Context, tx kv.Tx, hash common.Hash, blockHeight uint64) (block *types.Block, senders []common.Address, err error) { + block, senders, err = rawdb.ReadBlockWithSenders(tx, hash, blockHeight) + if err != nil { + return nil, nil, err + } + //TODO: read snapshots + return block, senders, nil +} -- GitLab