diff --git a/README.md b/README.md index 40cd3a8407..08ea17aa62 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Coreth and the C-Chain -[Avalanche](https://docs.avax.network/intro) is a network composed of multiple blockchains. +[Avalanche](https://www.avax.network/) is a network composed of multiple blockchains. Each blockchain is an instance of a Virtual Machine (VM), much like an object in an object-oriented language is an instance of a class. That is, the VM defines the behavior of the blockchain. Coreth (from core Ethereum) is the [Virtual Machine (VM)](https://docs.avax.network/learn/virtual-machines) that defines the Contract Chain (C-Chain). @@ -39,7 +39,7 @@ Full documentation for the C-Chain's API can be found [here.](https://docs.avax. ## Compatibility -The C-Chain is compatible with almost all Ethereum tooling, including [Core,](https://docs.avax.network/build/dapp/launch-dapp#through-core) [Metamask,](https://docs.avax.network/build/dapp/launch-dapp#through-metamask) [Remix](https://docs.avax.network/build/tutorials/smart-contracts/deploy-a-smart-contract-on-avalanche-using-remix-and-metamask) and [Truffle.](https://docs.avax.network/build/tutorials/smart-contracts/using-truffle-with-the-avalanche-c-chain) +The C-Chain is compatible with almost all Ethereum tooling, including [Core,](https://docs.avax.network/build/dapp/launch-dapp#through-core) [Metamask,](https://docs.avax.network/build/dapp/launch-dapp#through-metamask) [Remix](https://docs.avax.network/dapps/smart-contract-dev/deploy-with-remix-ide) and [Truffle.](https://docs.avax.network/build/tutorials/smart-contracts/using-truffle-with-the-avalanche-c-chain) ## Differences Between Avalanche C-Chain and Ethereum diff --git a/RELEASES.md b/RELEASES.md index bce253816e..628e454843 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,6 +1,13 @@ # Release Notes +## Pending Release + ## [v0.14.1](https://github.com/ava-labs/coreth/releases/tag/v0.14.1) + +- Removed deprecated `ExportKey`, `ExportAVAX`, `Export`, `ImportKey`, `ImportAVAX`, `Import` APIs +- IMPORTANT: `eth_getProof` calls for historical state will be rejected by default. + - On archive nodes (`"pruning-enabled": false`): queries for historical proofs for state older than approximately 24 hours preceding the last accepted block will be rejected by default. This can be adjusted with the new option `historical-proof-query-window` which defines the number of blocks before the last accepted block which should be accepted for state proof queries, or set to `0` to accept any block number state query (previous behavior). + - On `pruning` nodes: queries for proofs past the tip buffer (32 blocks) will be rejected. This is in support of moving to a path based storage scheme, which does not support historical state proofs. - Remove API eth_getAssetBalance that was used to query ANT balances (deprecated since v0.10.0) - Remove legacy gossip handler and metrics (deprecated since v0.10.0) - Refactored trie_prefetcher.go to be structurally similar to [upstream](https://github.com/ethereum/go-ethereum/tree/v1.13.14). diff --git a/core/state_manager.go b/core/state_manager.go index 8fc7de11c3..59447055b7 100644 --- a/core/state_manager.go +++ b/core/state_manager.go @@ -41,12 +41,12 @@ func init() { } const ( - // tipBufferSize is the number of recent accepted tries to keep in the TrieDB + // TipBufferSize is the number of recent accepted tries to keep in the TrieDB // dirties cache at tip (only applicable in [pruning] mode). // // Keeping extra tries around at tip enables clients to query data from // recent trie roots. - tipBufferSize = 32 + TipBufferSize = 32 // flushWindow is the distance to the [commitInterval] when we start // optimistically flushing trie nodes to disk (only applicable in [pruning] @@ -79,7 +79,7 @@ func NewTrieWriter(db TrieDB, config *CacheConfig) TrieWriter { targetCommitSize: common.StorageSize(config.TrieDirtyCommitTarget) * 1024 * 1024, imageCap: 4 * 1024 * 1024, commitInterval: config.CommitInterval, - tipBuffer: NewBoundedBuffer(tipBufferSize, db.Dereference), + tipBuffer: NewBoundedBuffer(TipBufferSize, db.Dereference), } cm.flushStepSize = (cm.memoryCap - cm.targetCommitSize) / common.StorageSize(flushWindow) return cm diff --git a/core/state_manager_test.go b/core/state_manager_test.go index 2fb47add49..cddb0a6dd8 100644 --- a/core/state_manager_test.go +++ b/core/state_manager_test.go @@ -53,10 +53,10 @@ func TestCappedMemoryTrieWriter(t *testing.T) { assert.Equal(common.Hash{}, m.LastCommit, "should not have committed block on insert") w.AcceptTrie(block) - if i <= tipBufferSize { + if i <= TipBufferSize { assert.Equal(common.Hash{}, m.LastDereference, "should not have dereferenced block on accept") } else { - assert.Equal(common.BigToHash(big.NewInt(int64(i-tipBufferSize))), m.LastDereference, "should have dereferenced old block on last accept") + assert.Equal(common.BigToHash(big.NewInt(int64(i-TipBufferSize))), m.LastDereference, "should have dereferenced old block on last accept") m.LastDereference = common.Hash{} } if i < int(cacheConfig.CommitInterval) { @@ -77,7 +77,7 @@ func TestNoPruningTrieWriter(t *testing.T) { m := &MockTrieDB{} w := NewTrieWriter(m, &CacheConfig{}) assert := assert.New(t) - for i := 0; i < tipBufferSize+1; i++ { + for i := 0; i < TipBufferSize+1; i++ { bigI := big.NewInt(int64(i)) block := types.NewBlock( &types.Header{ diff --git a/eth/api_backend.go b/eth/api_backend.go index b66c4b5415..bf6b578780 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -60,6 +60,10 @@ type EthAPIBackend struct { allowUnfinalizedQueries bool eth *Ethereum gpo *gasprice.Oracle + + // historicalProofQueryWindow is the number of blocks before the last accepted block to be accepted for + // state queries when running archive mode. + historicalProofQueryWindow uint64 } // ChainConfig returns the active chain configuration. @@ -67,6 +71,17 @@ func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { return b.eth.blockchain.Config() } +// IsArchive returns true if the node is running in archive mode, false otherwise. +func (b *EthAPIBackend) IsArchive() bool { + return !b.eth.config.Pruning +} + +// HistoricalProofQueryWindow returns the number of blocks before the last accepted block to be accepted for state queries. +// It returns 0 to indicate to accept any block number for state queries. +func (b *EthAPIBackend) HistoricalProofQueryWindow() uint64 { + return b.historicalProofQueryWindow +} + func (b *EthAPIBackend) IsAllowUnfinalizedQueries() bool { return b.allowUnfinalizedQueries } diff --git a/eth/backend.go b/eth/backend.go index 480730d5d3..79dce86db3 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -263,11 +263,12 @@ func New( } eth.APIBackend = &EthAPIBackend{ - extRPCEnabled: stack.Config().ExtRPCEnabled(), - allowUnprotectedTxs: config.AllowUnprotectedTxs, - allowUnprotectedTxHashes: allowUnprotectedTxHashes, - allowUnfinalizedQueries: config.AllowUnfinalizedQueries, - eth: eth, + extRPCEnabled: stack.Config().ExtRPCEnabled(), + allowUnprotectedTxs: config.AllowUnprotectedTxs, + allowUnprotectedTxHashes: allowUnprotectedTxHashes, + allowUnfinalizedQueries: config.AllowUnfinalizedQueries, + historicalProofQueryWindow: config.HistoricalProofQueryWindow, + eth: eth, } if config.AllowUnprotectedTxs { log.Info("Unprotected transactions allowed") diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index e82d73d4e2..f7697112ef 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -137,6 +137,11 @@ type Config struct { // AllowUnfinalizedQueries allow unfinalized queries AllowUnfinalizedQueries bool + // HistoricalProofQueryWindow is the number of blocks before the last accepted block to be accepted for state queries. + // For archive nodes, it defaults to 43200 and can be set to 0 to indicate to accept any block query. + // For non-archive nodes, it is forcibly set to the value of [core.TipBufferSize]. + HistoricalProofQueryWindow uint64 + // AllowUnprotectedTxs allow unprotected transactions to be locally issued. // Unprotected transactions are transactions that are signed without EIP-155 // replay protection. diff --git a/go.mod b/go.mod index 0b095d2f54..9e8a97ed02 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.8 require ( github.com/VictoriaMetrics/fastcache v1.12.1 - github.com/ava-labs/avalanchego v1.12.2-0.20250106102004-902377d447ba + github.com/ava-labs/avalanchego v1.12.2-0.20250116172728-54d8b06b8625 github.com/cespare/cp v0.1.0 github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 9c19c061be..2090275d01 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,8 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.12.2-0.20250106102004-902377d447ba h1:7t2ORGM53sqdsczNZGFQIK99of9yeetCld90keJ47Os= -github.com/ava-labs/avalanchego v1.12.2-0.20250106102004-902377d447ba/go.mod h1:oK/C7ZGo5cAEayBKBoawh2EpOo3E9gD1rpd9NAM0RkQ= +github.com/ava-labs/avalanchego v1.12.2-0.20250116172728-54d8b06b8625 h1:sbmfwhpetCKI7Unzw9jJ+2HWLRFM7vq7th0pH2LclCQ= +github.com/ava-labs/avalanchego v1.12.2-0.20250116172728-54d8b06b8625/go.mod h1:oK/C7ZGo5cAEayBKBoawh2EpOo3E9gD1rpd9NAM0RkQ= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 93aadbe14c..9e7ad54dde 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -676,7 +676,14 @@ func (n *proofList) Delete(key []byte) error { } // GetProof returns the Merkle-proof for a given account and optionally some storage keys. +// If the requested block is part of historical blocks and the node does not accept +// getting proofs for historical blocks, an error is returned. func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { + err := s.stateQueryBlockNumberAllowed(blockNrOrHash) + if err != nil { + return nil, fmt.Errorf("historical proof query not allowed: %s", err) + } + var ( keys = make([]common.Hash, len(storageKeys)) keyLengths = make([]int, len(storageKeys)) diff --git a/internal/ethapi/api_extra.go b/internal/ethapi/api_extra.go index a56830988f..63cf84f48e 100644 --- a/internal/ethapi/api_extra.go +++ b/internal/ethapi/api_extra.go @@ -92,3 +92,42 @@ func (s *BlockChainAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, erro } return results, nil } + +// stateQueryBlockNumberAllowed returns a nil error if: +// - the node is configured to accept any state query (the query window is zero) +// - the block given has its number within the query window before the last accepted block. +// This query window is set to [core.TipBufferSize] when running in a non-archive mode. +// +// Otherwise, it returns a non-nil error containing block number information. +func (s *BlockChainAPI) stateQueryBlockNumberAllowed(blockNumOrHash rpc.BlockNumberOrHash) (err error) { + queryWindow := uint64(core.TipBufferSize) + if s.b.IsArchive() { + queryWindow = s.b.HistoricalProofQueryWindow() + if queryWindow == 0 { + return nil + } + } + + lastAcceptedNumber := s.b.LastAcceptedBlock().NumberU64() + + var number uint64 + if blockNumOrHash.BlockNumber != nil { + number = uint64(blockNumOrHash.BlockNumber.Int64()) + } else { + block, err := s.b.BlockByNumberOrHash(context.Background(), blockNumOrHash) + if err != nil { + return fmt.Errorf("failed to get block from hash: %s", err) + } + number = block.NumberU64() + } + + var oldestAllowed uint64 + if lastAcceptedNumber > queryWindow { + oldestAllowed = lastAcceptedNumber - queryWindow + } + if number >= oldestAllowed { + return nil + } + return fmt.Errorf("block number %d is before the oldest allowed block number %d (window of %d blocks)", + number, oldestAllowed, queryWindow) +} diff --git a/internal/ethapi/api_extra_test.go b/internal/ethapi/api_extra_test.go new file mode 100644 index 0000000000..28843b4cb6 --- /dev/null +++ b/internal/ethapi/api_extra_test.go @@ -0,0 +1,132 @@ +// (c) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package ethapi + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/rpc" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" +) + +func TestBlockChainAPI_stateQueryBlockNumberAllowed(t *testing.T) { + t.Parallel() + + const queryWindow uint64 = 1024 + + makeBlockWithNumber := func(number uint64) *types.Block { + header := &types.Header{ + Number: big.NewInt(int64(number)), + } + return types.NewBlock(header, nil, nil, nil, nil) + } + + testCases := map[string]struct { + blockNumOrHash rpc.BlockNumberOrHash + makeBackend func(ctrl *gomock.Controller) *MockBackend + wantErrMessage string + }{ + "zero_query_window": { + blockNumOrHash: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(1000)), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(uint64(0)) + return backend + }, + }, + "block_number_allowed_below_window": { + blockNumOrHash: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(1000)), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(queryWindow) + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(1020)) + return backend + }, + }, + "block_number_allowed": { + blockNumOrHash: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(2000)), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(queryWindow) + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(2200)) + return backend + }, + }, + "block_number_allowed_by_hash": { + blockNumOrHash: rpc.BlockNumberOrHashWithHash(common.Hash{99}, false), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(queryWindow) + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(2200)) + backend.EXPECT(). + BlockByNumberOrHash(gomock.Any(), gomock.Any()). + Return(makeBlockWithNumber(2000), nil) + return backend + }, + }, + "block_number_allowed_by_hash_error": { + blockNumOrHash: rpc.BlockNumberOrHashWithHash(common.Hash{99}, false), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(queryWindow) + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(2200)) + backend.EXPECT(). + BlockByNumberOrHash(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("test error")) + return backend + }, + wantErrMessage: "failed to get block from hash: test error", + }, + "block_number_out_of_window": { + blockNumOrHash: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(1000)), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(true) + backend.EXPECT().HistoricalProofQueryWindow().Return(queryWindow) + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(2200)) + return backend + }, + wantErrMessage: "block number 1000 is before the oldest allowed block number 1176 (window of 1024 blocks)", + }, + "block_number_out_of_window_non_archive": { + blockNumOrHash: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(1000)), + makeBackend: func(ctrl *gomock.Controller) *MockBackend { + backend := NewMockBackend(ctrl) + backend.EXPECT().IsArchive().Return(false) + // query window is 32 as set to core.TipBufferSize + backend.EXPECT().LastAcceptedBlock().Return(makeBlockWithNumber(1033)) + return backend + }, + wantErrMessage: "block number 1000 is before the oldest allowed block number 1001 (window of 32 blocks)", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + + api := &BlockChainAPI{ + b: testCase.makeBackend(ctrl), + } + + err := api.stateQueryBlockNumberAllowed(testCase.blockNumOrHash) + if testCase.wantErrMessage == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, err, testCase.wantErrMessage) + } + }) + } +} diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 87a7176026..f76c5dff49 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -625,6 +625,12 @@ func (b testBackend) LastAcceptedBlock() *types.Block { panic("implement me") } func (b testBackend) SuggestPrice(ctx context.Context) (*big.Int, error) { panic("implement me") } +func (b testBackend) IsArchive() bool { + panic("implement me") +} +func (b testBackend) HistoricalProofQueryWindow() (queryWindow uint64) { + panic("implement me") +} func TestEstimateGas(t *testing.T) { t.Parallel() diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index accfda57aa..473a5eda11 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -80,6 +80,8 @@ type Backend interface { SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription BadBlocks() ([]*types.Block, []*core.BadBlockReason) + IsArchive() bool + HistoricalProofQueryWindow() uint64 // Transaction pool API SendTx(ctx context.Context, signedTx *types.Transaction) error diff --git a/internal/ethapi/mocks_generate_test.go b/internal/ethapi/mocks_generate_test.go new file mode 100644 index 0000000000..7784142351 --- /dev/null +++ b/internal/ethapi/mocks_generate_test.go @@ -0,0 +1,3 @@ +package ethapi + +//go:generate go run go.uber.org/mock/mockgen -package=$GOPACKAGE -destination=mocks_test.go . Backend diff --git a/internal/ethapi/mocks_test.go b/internal/ethapi/mocks_test.go new file mode 100644 index 0000000000..95b2ca4985 --- /dev/null +++ b/internal/ethapi/mocks_test.go @@ -0,0 +1,757 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ava-labs/coreth/internal/ethapi (interfaces: Backend) +// +// Generated by this command: +// +// mockgen -package=ethapi -destination=mocks_test.go . Backend +// + +// Package ethapi is a generated GoMock package. +package ethapi + +import ( + context "context" + big "math/big" + reflect "reflect" + time "time" + + accounts "github.com/ava-labs/coreth/accounts" + consensus "github.com/ava-labs/coreth/consensus" + core "github.com/ava-labs/coreth/core" + bloombits "github.com/ava-labs/coreth/core/bloombits" + state "github.com/ava-labs/coreth/core/state" + types "github.com/ava-labs/coreth/core/types" + vm "github.com/ava-labs/coreth/core/vm" + params "github.com/ava-labs/coreth/params" + rpc "github.com/ava-labs/coreth/rpc" + common "github.com/ethereum/go-ethereum/common" + ethdb "github.com/ethereum/go-ethereum/ethdb" + event "github.com/ethereum/go-ethereum/event" + gomock "go.uber.org/mock/gomock" +) + +// MockBackend is a mock of Backend interface. +type MockBackend struct { + ctrl *gomock.Controller + recorder *MockBackendMockRecorder + isgomock struct{} +} + +// MockBackendMockRecorder is the mock recorder for MockBackend. +type MockBackendMockRecorder struct { + mock *MockBackend +} + +// NewMockBackend creates a new mock instance. +func NewMockBackend(ctrl *gomock.Controller) *MockBackend { + mock := &MockBackend{ctrl: ctrl} + mock.recorder = &MockBackendMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBackend) EXPECT() *MockBackendMockRecorder { + return m.recorder +} + +// AccountManager mocks base method. +func (m *MockBackend) AccountManager() *accounts.Manager { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AccountManager") + ret0, _ := ret[0].(*accounts.Manager) + return ret0 +} + +// AccountManager indicates an expected call of AccountManager. +func (mr *MockBackendMockRecorder) AccountManager() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountManager", reflect.TypeOf((*MockBackend)(nil).AccountManager)) +} + +// BadBlocks mocks base method. +func (m *MockBackend) BadBlocks() ([]*types.Block, []*core.BadBlockReason) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BadBlocks") + ret0, _ := ret[0].([]*types.Block) + ret1, _ := ret[1].([]*core.BadBlockReason) + return ret0, ret1 +} + +// BadBlocks indicates an expected call of BadBlocks. +func (mr *MockBackendMockRecorder) BadBlocks() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BadBlocks", reflect.TypeOf((*MockBackend)(nil).BadBlocks)) +} + +// BlockByHash mocks base method. +func (m *MockBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockByHash", ctx, hash) + ret0, _ := ret[0].(*types.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BlockByHash indicates an expected call of BlockByHash. +func (mr *MockBackendMockRecorder) BlockByHash(ctx, hash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHash", reflect.TypeOf((*MockBackend)(nil).BlockByHash), ctx, hash) +} + +// BlockByNumber mocks base method. +func (m *MockBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockByNumber", ctx, number) + ret0, _ := ret[0].(*types.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BlockByNumber indicates an expected call of BlockByNumber. +func (mr *MockBackendMockRecorder) BlockByNumber(ctx, number any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumber", reflect.TypeOf((*MockBackend)(nil).BlockByNumber), ctx, number) +} + +// BlockByNumberOrHash mocks base method. +func (m *MockBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockByNumberOrHash", ctx, blockNrOrHash) + ret0, _ := ret[0].(*types.Block) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BlockByNumberOrHash indicates an expected call of BlockByNumberOrHash. +func (mr *MockBackendMockRecorder) BlockByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).BlockByNumberOrHash), ctx, blockNrOrHash) +} + +// BloomStatus mocks base method. +func (m *MockBackend) BloomStatus() (uint64, uint64) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BloomStatus") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(uint64) + return ret0, ret1 +} + +// BloomStatus indicates an expected call of BloomStatus. +func (mr *MockBackendMockRecorder) BloomStatus() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BloomStatus", reflect.TypeOf((*MockBackend)(nil).BloomStatus)) +} + +// ChainConfig mocks base method. +func (m *MockBackend) ChainConfig() *params.ChainConfig { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChainConfig") + ret0, _ := ret[0].(*params.ChainConfig) + return ret0 +} + +// ChainConfig indicates an expected call of ChainConfig. +func (mr *MockBackendMockRecorder) ChainConfig() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainConfig", reflect.TypeOf((*MockBackend)(nil).ChainConfig)) +} + +// ChainDb mocks base method. +func (m *MockBackend) ChainDb() ethdb.Database { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChainDb") + ret0, _ := ret[0].(ethdb.Database) + return ret0 +} + +// ChainDb indicates an expected call of ChainDb. +func (mr *MockBackendMockRecorder) ChainDb() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainDb", reflect.TypeOf((*MockBackend)(nil).ChainDb)) +} + +// CurrentBlock mocks base method. +func (m *MockBackend) CurrentBlock() *types.Header { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentBlock") + ret0, _ := ret[0].(*types.Header) + return ret0 +} + +// CurrentBlock indicates an expected call of CurrentBlock. +func (mr *MockBackendMockRecorder) CurrentBlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentBlock", reflect.TypeOf((*MockBackend)(nil).CurrentBlock)) +} + +// CurrentHeader mocks base method. +func (m *MockBackend) CurrentHeader() *types.Header { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentHeader") + ret0, _ := ret[0].(*types.Header) + return ret0 +} + +// CurrentHeader indicates an expected call of CurrentHeader. +func (mr *MockBackendMockRecorder) CurrentHeader() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentHeader", reflect.TypeOf((*MockBackend)(nil).CurrentHeader)) +} + +// Engine mocks base method. +func (m *MockBackend) Engine() consensus.Engine { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Engine") + ret0, _ := ret[0].(consensus.Engine) + return ret0 +} + +// Engine indicates an expected call of Engine. +func (mr *MockBackendMockRecorder) Engine() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Engine", reflect.TypeOf((*MockBackend)(nil).Engine)) +} + +// EstimateBaseFee mocks base method. +func (m *MockBackend) EstimateBaseFee(ctx context.Context) (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EstimateBaseFee", ctx) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EstimateBaseFee indicates an expected call of EstimateBaseFee. +func (mr *MockBackendMockRecorder) EstimateBaseFee(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EstimateBaseFee", reflect.TypeOf((*MockBackend)(nil).EstimateBaseFee), ctx) +} + +// ExtRPCEnabled mocks base method. +func (m *MockBackend) ExtRPCEnabled() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExtRPCEnabled") + ret0, _ := ret[0].(bool) + return ret0 +} + +// ExtRPCEnabled indicates an expected call of ExtRPCEnabled. +func (mr *MockBackendMockRecorder) ExtRPCEnabled() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtRPCEnabled", reflect.TypeOf((*MockBackend)(nil).ExtRPCEnabled)) +} + +// FeeHistory mocks base method. +func (m *MockBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FeeHistory", ctx, blockCount, lastBlock, rewardPercentiles) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].([][]*big.Int) + ret2, _ := ret[2].([]*big.Int) + ret3, _ := ret[3].([]float64) + ret4, _ := ret[4].(error) + return ret0, ret1, ret2, ret3, ret4 +} + +// FeeHistory indicates an expected call of FeeHistory. +func (mr *MockBackendMockRecorder) FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeHistory", reflect.TypeOf((*MockBackend)(nil).FeeHistory), ctx, blockCount, lastBlock, rewardPercentiles) +} + +// GetBody mocks base method. +func (m *MockBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBody", ctx, hash, number) + ret0, _ := ret[0].(*types.Body) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetBody indicates an expected call of GetBody. +func (mr *MockBackendMockRecorder) GetBody(ctx, hash, number any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBody", reflect.TypeOf((*MockBackend)(nil).GetBody), ctx, hash, number) +} + +// GetEVM mocks base method. +func (m *MockBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEVM", ctx, msg, state, header, vmConfig, blockCtx) + ret0, _ := ret[0].(*vm.EVM) + return ret0 +} + +// GetEVM indicates an expected call of GetEVM. +func (mr *MockBackendMockRecorder) GetEVM(ctx, msg, state, header, vmConfig, blockCtx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEVM", reflect.TypeOf((*MockBackend)(nil).GetEVM), ctx, msg, state, header, vmConfig, blockCtx) +} + +// GetLogs mocks base method. +func (m *MockBackend) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLogs", ctx, blockHash, number) + ret0, _ := ret[0].([][]*types.Log) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLogs indicates an expected call of GetLogs. +func (mr *MockBackendMockRecorder) GetLogs(ctx, blockHash, number any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockBackend)(nil).GetLogs), ctx, blockHash, number) +} + +// GetPoolNonce mocks base method. +func (m *MockBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPoolNonce", ctx, addr) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPoolNonce indicates an expected call of GetPoolNonce. +func (mr *MockBackendMockRecorder) GetPoolNonce(ctx, addr any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolNonce", reflect.TypeOf((*MockBackend)(nil).GetPoolNonce), ctx, addr) +} + +// GetPoolTransaction mocks base method. +func (m *MockBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPoolTransaction", txHash) + ret0, _ := ret[0].(*types.Transaction) + return ret0 +} + +// GetPoolTransaction indicates an expected call of GetPoolTransaction. +func (mr *MockBackendMockRecorder) GetPoolTransaction(txHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolTransaction", reflect.TypeOf((*MockBackend)(nil).GetPoolTransaction), txHash) +} + +// GetPoolTransactions mocks base method. +func (m *MockBackend) GetPoolTransactions() (types.Transactions, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPoolTransactions") + ret0, _ := ret[0].(types.Transactions) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPoolTransactions indicates an expected call of GetPoolTransactions. +func (mr *MockBackendMockRecorder) GetPoolTransactions() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolTransactions", reflect.TypeOf((*MockBackend)(nil).GetPoolTransactions)) +} + +// GetReceipts mocks base method. +func (m *MockBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetReceipts", ctx, hash) + ret0, _ := ret[0].(types.Receipts) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetReceipts indicates an expected call of GetReceipts. +func (mr *MockBackendMockRecorder) GetReceipts(ctx, hash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), ctx, hash) +} + +// GetTransaction mocks base method. +func (m *MockBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTransaction", ctx, txHash) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(*types.Transaction) + ret2, _ := ret[2].(common.Hash) + ret3, _ := ret[3].(uint64) + ret4, _ := ret[4].(uint64) + ret5, _ := ret[5].(error) + return ret0, ret1, ret2, ret3, ret4, ret5 +} + +// GetTransaction indicates an expected call of GetTransaction. +func (mr *MockBackendMockRecorder) GetTransaction(ctx, txHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTransaction", reflect.TypeOf((*MockBackend)(nil).GetTransaction), ctx, txHash) +} + +// HeaderByHash mocks base method. +func (m *MockBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeaderByHash", ctx, hash) + ret0, _ := ret[0].(*types.Header) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeaderByHash indicates an expected call of HeaderByHash. +func (mr *MockBackendMockRecorder) HeaderByHash(ctx, hash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHash", reflect.TypeOf((*MockBackend)(nil).HeaderByHash), ctx, hash) +} + +// HeaderByNumber mocks base method. +func (m *MockBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeaderByNumber", ctx, number) + ret0, _ := ret[0].(*types.Header) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeaderByNumber indicates an expected call of HeaderByNumber. +func (mr *MockBackendMockRecorder) HeaderByNumber(ctx, number any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumber", reflect.TypeOf((*MockBackend)(nil).HeaderByNumber), ctx, number) +} + +// HeaderByNumberOrHash mocks base method. +func (m *MockBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeaderByNumberOrHash", ctx, blockNrOrHash) + ret0, _ := ret[0].(*types.Header) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeaderByNumberOrHash indicates an expected call of HeaderByNumberOrHash. +func (mr *MockBackendMockRecorder) HeaderByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).HeaderByNumberOrHash), ctx, blockNrOrHash) +} + +// HistoricalProofQueryWindow mocks base method. +func (m *MockBackend) HistoricalProofQueryWindow() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HistoricalProofQueryWindow") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// HistoricalProofQueryWindow indicates an expected call of HistoricalProofQueryWindow. +func (mr *MockBackendMockRecorder) HistoricalProofQueryWindow() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HistoricalProofQueryWindow", reflect.TypeOf((*MockBackend)(nil).HistoricalProofQueryWindow)) +} + +// IsArchive mocks base method. +func (m *MockBackend) IsArchive() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsArchive") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsArchive indicates an expected call of IsArchive. +func (mr *MockBackendMockRecorder) IsArchive() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsArchive", reflect.TypeOf((*MockBackend)(nil).IsArchive)) +} + +// LastAcceptedBlock mocks base method. +func (m *MockBackend) LastAcceptedBlock() *types.Block { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LastAcceptedBlock") + ret0, _ := ret[0].(*types.Block) + return ret0 +} + +// LastAcceptedBlock indicates an expected call of LastAcceptedBlock. +func (mr *MockBackendMockRecorder) LastAcceptedBlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastAcceptedBlock", reflect.TypeOf((*MockBackend)(nil).LastAcceptedBlock)) +} + +// RPCEVMTimeout mocks base method. +func (m *MockBackend) RPCEVMTimeout() time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RPCEVMTimeout") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// RPCEVMTimeout indicates an expected call of RPCEVMTimeout. +func (mr *MockBackendMockRecorder) RPCEVMTimeout() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCEVMTimeout", reflect.TypeOf((*MockBackend)(nil).RPCEVMTimeout)) +} + +// RPCGasCap mocks base method. +func (m *MockBackend) RPCGasCap() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RPCGasCap") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// RPCGasCap indicates an expected call of RPCGasCap. +func (mr *MockBackendMockRecorder) RPCGasCap() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCGasCap", reflect.TypeOf((*MockBackend)(nil).RPCGasCap)) +} + +// RPCTxFeeCap mocks base method. +func (m *MockBackend) RPCTxFeeCap() float64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RPCTxFeeCap") + ret0, _ := ret[0].(float64) + return ret0 +} + +// RPCTxFeeCap indicates an expected call of RPCTxFeeCap. +func (mr *MockBackendMockRecorder) RPCTxFeeCap() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCTxFeeCap", reflect.TypeOf((*MockBackend)(nil).RPCTxFeeCap)) +} + +// SendTx mocks base method. +func (m *MockBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendTx", ctx, signedTx) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendTx indicates an expected call of SendTx. +func (mr *MockBackendMockRecorder) SendTx(ctx, signedTx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTx", reflect.TypeOf((*MockBackend)(nil).SendTx), ctx, signedTx) +} + +// ServiceFilter mocks base method. +func (m *MockBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ServiceFilter", ctx, session) +} + +// ServiceFilter indicates an expected call of ServiceFilter. +func (mr *MockBackendMockRecorder) ServiceFilter(ctx, session any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServiceFilter", reflect.TypeOf((*MockBackend)(nil).ServiceFilter), ctx, session) +} + +// StateAndHeaderByNumber mocks base method. +func (m *MockBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateAndHeaderByNumber", ctx, number) + ret0, _ := ret[0].(*state.StateDB) + ret1, _ := ret[1].(*types.Header) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// StateAndHeaderByNumber indicates an expected call of StateAndHeaderByNumber. +func (mr *MockBackendMockRecorder) StateAndHeaderByNumber(ctx, number any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumber", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumber), ctx, number) +} + +// StateAndHeaderByNumberOrHash mocks base method. +func (m *MockBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateAndHeaderByNumberOrHash", ctx, blockNrOrHash) + ret0, _ := ret[0].(*state.StateDB) + ret1, _ := ret[1].(*types.Header) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// StateAndHeaderByNumberOrHash indicates an expected call of StateAndHeaderByNumberOrHash. +func (mr *MockBackendMockRecorder) StateAndHeaderByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumberOrHash), ctx, blockNrOrHash) +} + +// Stats mocks base method. +func (m *MockBackend) Stats() (int, int) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Stats") + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(int) + return ret0, ret1 +} + +// Stats indicates an expected call of Stats. +func (mr *MockBackendMockRecorder) Stats() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stats", reflect.TypeOf((*MockBackend)(nil).Stats)) +} + +// SubscribeChainEvent mocks base method. +func (m *MockBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeChainEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeChainEvent indicates an expected call of SubscribeChainEvent. +func (mr *MockBackendMockRecorder) SubscribeChainEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainEvent), ch) +} + +// SubscribeChainHeadEvent mocks base method. +func (m *MockBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeChainHeadEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeChainHeadEvent indicates an expected call of SubscribeChainHeadEvent. +func (mr *MockBackendMockRecorder) SubscribeChainHeadEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainHeadEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainHeadEvent), ch) +} + +// SubscribeChainSideEvent mocks base method. +func (m *MockBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeChainSideEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeChainSideEvent indicates an expected call of SubscribeChainSideEvent. +func (mr *MockBackendMockRecorder) SubscribeChainSideEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainSideEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainSideEvent), ch) +} + +// SubscribeLogsEvent mocks base method. +func (m *MockBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeLogsEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeLogsEvent indicates an expected call of SubscribeLogsEvent. +func (mr *MockBackendMockRecorder) SubscribeLogsEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeLogsEvent), ch) +} + +// SubscribeNewTxsEvent mocks base method. +func (m *MockBackend) SubscribeNewTxsEvent(arg0 chan<- core.NewTxsEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeNewTxsEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeNewTxsEvent indicates an expected call of SubscribeNewTxsEvent. +func (mr *MockBackendMockRecorder) SubscribeNewTxsEvent(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeNewTxsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeNewTxsEvent), arg0) +} + +// SubscribePendingLogsEvent mocks base method. +func (m *MockBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribePendingLogsEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribePendingLogsEvent indicates an expected call of SubscribePendingLogsEvent. +func (mr *MockBackendMockRecorder) SubscribePendingLogsEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribePendingLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribePendingLogsEvent), ch) +} + +// SubscribeRemovedLogsEvent mocks base method. +func (m *MockBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeRemovedLogsEvent", ch) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeRemovedLogsEvent indicates an expected call of SubscribeRemovedLogsEvent. +func (mr *MockBackendMockRecorder) SubscribeRemovedLogsEvent(ch any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeRemovedLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeRemovedLogsEvent), ch) +} + +// SuggestGasTipCap mocks base method. +func (m *MockBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SuggestGasTipCap", ctx) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SuggestGasTipCap indicates an expected call of SuggestGasTipCap. +func (mr *MockBackendMockRecorder) SuggestGasTipCap(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SuggestGasTipCap", reflect.TypeOf((*MockBackend)(nil).SuggestGasTipCap), ctx) +} + +// SuggestPrice mocks base method. +func (m *MockBackend) SuggestPrice(ctx context.Context) (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SuggestPrice", ctx) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SuggestPrice indicates an expected call of SuggestPrice. +func (mr *MockBackendMockRecorder) SuggestPrice(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SuggestPrice", reflect.TypeOf((*MockBackend)(nil).SuggestPrice), ctx) +} + +// TxPoolContent mocks base method. +func (m *MockBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TxPoolContent") + ret0, _ := ret[0].(map[common.Address][]*types.Transaction) + ret1, _ := ret[1].(map[common.Address][]*types.Transaction) + return ret0, ret1 +} + +// TxPoolContent indicates an expected call of TxPoolContent. +func (mr *MockBackendMockRecorder) TxPoolContent() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxPoolContent", reflect.TypeOf((*MockBackend)(nil).TxPoolContent)) +} + +// TxPoolContentFrom mocks base method. +func (m *MockBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TxPoolContentFrom", addr) + ret0, _ := ret[0].([]*types.Transaction) + ret1, _ := ret[1].([]*types.Transaction) + return ret0, ret1 +} + +// TxPoolContentFrom indicates an expected call of TxPoolContentFrom. +func (mr *MockBackendMockRecorder) TxPoolContentFrom(addr any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxPoolContentFrom", reflect.TypeOf((*MockBackend)(nil).TxPoolContentFrom), addr) +} + +// UnprotectedAllowed mocks base method. +func (m *MockBackend) UnprotectedAllowed(tx *types.Transaction) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnprotectedAllowed", tx) + ret0, _ := ret[0].(bool) + return ret0 +} + +// UnprotectedAllowed indicates an expected call of UnprotectedAllowed. +func (mr *MockBackendMockRecorder) UnprotectedAllowed(tx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnprotectedAllowed", reflect.TypeOf((*MockBackend)(nil).UnprotectedAllowed), tx) +} diff --git a/plugin/evm/api.go b/plugin/evm/api.go index 49ad2a895f..12791d4e08 100644 --- a/plugin/evm/api.go +++ b/plugin/evm/api.go @@ -19,7 +19,6 @@ import ( "github.com/ava-labs/coreth/plugin/evm/atomic" "github.com/ava-labs/coreth/plugin/evm/client" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" ) @@ -33,10 +32,9 @@ const ( ) var ( - errNoAddresses = errors.New("no addresses provided") - errNoSourceChain = errors.New("no source chain provided") - errNilTxID = errors.New("nil transaction ID") - errMissingPrivateKey = errors.New("argument 'privateKey' not given") + errNoAddresses = errors.New("no addresses provided") + errNoSourceChain = errors.New("no source chain provided") + errNilTxID = errors.New("nil transaction ID") initialBaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee) ) @@ -71,17 +69,6 @@ func (api *SnowmanAPI) IssueBlock(ctx context.Context) error { // AvaxAPI offers Avalanche network related API methods type AvaxAPI struct{ vm *VM } -// parseAssetID parses an assetID string into an ID -func (service *AvaxAPI) parseAssetID(assetID string) (ids.ID, error) { - if assetID == "" { - return ids.ID{}, fmt.Errorf("assetID is required") - } else if assetID == "AVAX" { - return service.vm.ctx.AVAXAssetID, nil - } else { - return ids.FromString(assetID) - } -} - type VersionReply struct { Version string `json:"version"` } @@ -92,198 +79,6 @@ func (service *AvaxAPI) Version(r *http.Request, _ *struct{}, reply *VersionRepl return nil } -// ExportKey returns a private key from the provided user -func (service *AvaxAPI) ExportKey(r *http.Request, args *client.ExportKeyArgs, reply *client.ExportKeyReply) error { - log.Info("EVM: ExportKey called") - - address, err := client.ParseEthAddress(args.Address) - if err != nil { - return fmt.Errorf("couldn't parse %s to address: %s", args.Address, err) - } - - service.vm.ctx.Lock.Lock() - defer service.vm.ctx.Lock.Unlock() - - db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) - if err != nil { - return fmt.Errorf("problem retrieving user '%s': %w", args.Username, err) - } - defer db.Close() - - user := user{db: db} - reply.PrivateKey, err = user.getKey(address) - if err != nil { - return fmt.Errorf("problem retrieving private key: %w", err) - } - reply.PrivateKeyHex = hexutil.Encode(reply.PrivateKey.Bytes()) - return nil -} - -// ImportKey adds a private key to the provided user -func (service *AvaxAPI) ImportKey(r *http.Request, args *client.ImportKeyArgs, reply *api.JSONAddress) error { - log.Info("EVM: ImportKey called", "username", args.Username) - - if args.PrivateKey == nil { - return errMissingPrivateKey - } - - reply.Address = args.PrivateKey.EthAddress().Hex() - - service.vm.ctx.Lock.Lock() - defer service.vm.ctx.Lock.Unlock() - - db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) - if err != nil { - return fmt.Errorf("problem retrieving data: %w", err) - } - defer db.Close() - - user := user{db: db} - if err := user.putAddress(args.PrivateKey); err != nil { - return fmt.Errorf("problem saving key %w", err) - } - return nil -} - -// ImportAVAX is a deprecated name for Import. -func (service *AvaxAPI) ImportAVAX(_ *http.Request, args *client.ImportArgs, response *api.JSONTxID) error { - return service.Import(nil, args, response) -} - -// Import issues a transaction to import AVAX from the X-chain. The AVAX -// must have already been exported from the X-Chain. -func (service *AvaxAPI) Import(_ *http.Request, args *client.ImportArgs, response *api.JSONTxID) error { - log.Info("EVM: ImportAVAX called") - - chainID, err := service.vm.ctx.BCLookup.Lookup(args.SourceChain) - if err != nil { - return fmt.Errorf("problem parsing chainID %q: %w", args.SourceChain, err) - } - - service.vm.ctx.Lock.Lock() - defer service.vm.ctx.Lock.Unlock() - - // Get the user's info - db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) - if err != nil { - return fmt.Errorf("couldn't get user '%s': %w", args.Username, err) - } - defer db.Close() - - user := user{db: db} - privKeys, err := user.getKeys() - if err != nil { // Get keys - return fmt.Errorf("couldn't get keys controlled by the user: %w", err) - } - - var baseFee *big.Int - if args.BaseFee == nil { - // Get the base fee to use - baseFee, err = service.vm.estimateBaseFee(context.Background()) - if err != nil { - return err - } - } else { - baseFee = args.BaseFee.ToInt() - } - - tx, err := service.vm.newImportTx(chainID, args.To, baseFee, privKeys) - if err != nil { - return err - } - - response.TxID = tx.ID() - if err := service.vm.mempool.AddLocalTx(tx); err != nil { - return err - } - service.vm.atomicTxPushGossiper.Add(&atomic.GossipAtomicTx{Tx: tx}) - return nil -} - -// ExportAVAX exports AVAX from the C-Chain to the X-Chain -// It must be imported on the X-Chain to complete the transfer -func (service *AvaxAPI) ExportAVAX(_ *http.Request, args *client.ExportAVAXArgs, response *api.JSONTxID) error { - return service.Export(nil, &client.ExportArgs{ - ExportAVAXArgs: *args, - AssetID: service.vm.ctx.AVAXAssetID.String(), - }, response) -} - -// Export exports an asset from the C-Chain to the X-Chain -// It must be imported on the X-Chain to complete the transfer -func (service *AvaxAPI) Export(_ *http.Request, args *client.ExportArgs, response *api.JSONTxID) error { - log.Info("EVM: Export called") - - assetID, err := service.parseAssetID(args.AssetID) - if err != nil { - return err - } - - if args.Amount == 0 { - return errors.New("argument 'amount' must be > 0") - } - - // Get the chainID and parse the to address - chainID, to, err := service.vm.ParseAddress(args.To) - if err != nil { - chainID, err = service.vm.ctx.BCLookup.Lookup(args.TargetChain) - if err != nil { - return err - } - to, err = ids.ShortFromString(args.To) - if err != nil { - return err - } - } - - service.vm.ctx.Lock.Lock() - defer service.vm.ctx.Lock.Unlock() - - // Get this user's data - db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password) - if err != nil { - return fmt.Errorf("problem retrieving user '%s': %w", args.Username, err) - } - defer db.Close() - - user := user{db: db} - privKeys, err := user.getKeys() - if err != nil { - return fmt.Errorf("couldn't get addresses controlled by the user: %w", err) - } - - var baseFee *big.Int - if args.BaseFee == nil { - // Get the base fee to use - baseFee, err = service.vm.estimateBaseFee(context.Background()) - if err != nil { - return err - } - } else { - baseFee = args.BaseFee.ToInt() - } - - // Create the transaction - tx, err := service.vm.newExportTx( - assetID, // AssetID - uint64(args.Amount), // Amount - chainID, // ID of the chain to send the funds to - to, // Address - baseFee, - privKeys, // Private keys - ) - if err != nil { - return fmt.Errorf("couldn't create tx: %w", err) - } - - response.TxID = tx.ID() - if err := service.vm.mempool.AddLocalTx(tx); err != nil { - return err - } - service.vm.atomicTxPushGossiper.Add(&atomic.GossipAtomicTx{Tx: tx}) - return nil -} - // GetUTXOs gets all utxos for passed in addresses func (service *AvaxAPI) GetUTXOs(r *http.Request, args *api.GetUTXOsArgs, reply *api.GetUTXOsReply) error { log.Info("EVM: GetUTXOs called", "Addresses", args.Addresses) diff --git a/plugin/evm/client/client.go b/plugin/evm/client/client.go index a6716b4b27..b507342405 100644 --- a/plugin/evm/client/client.go +++ b/plugin/evm/client/client.go @@ -8,13 +8,10 @@ import ( "errors" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "golang.org/x/exp/slog" "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/json" @@ -34,11 +31,6 @@ type Client interface { GetAtomicTxStatus(ctx context.Context, txID ids.ID, options ...rpc.Option) (atomic.Status, error) GetAtomicTx(ctx context.Context, txID ids.ID, options ...rpc.Option) ([]byte, error) GetAtomicUTXOs(ctx context.Context, addrs []ids.ShortID, sourceChain string, limit uint32, startAddress ids.ShortID, startUTXOID ids.ID, options ...rpc.Option) ([][]byte, ids.ShortID, ids.ID, error) - ExportKey(ctx context.Context, userPass api.UserPass, addr common.Address, options ...rpc.Option) (*secp256k1.PrivateKey, string, error) - ImportKey(ctx context.Context, userPass api.UserPass, privateKey *secp256k1.PrivateKey, options ...rpc.Option) (common.Address, error) - Import(ctx context.Context, userPass api.UserPass, to common.Address, sourceChain string, options ...rpc.Option) (ids.ID, error) - ExportAVAX(ctx context.Context, userPass api.UserPass, amount uint64, to ids.ShortID, targetChain string, options ...rpc.Option) (ids.ID, error) - Export(ctx context.Context, userPass api.UserPass, amount uint64, to ids.ShortID, targetChain string, assetID string, options ...rpc.Option) (ids.ID, error) StartCPUProfiler(ctx context.Context, options ...rpc.Option) error StopCPUProfiler(ctx context.Context, options ...rpc.Option) error MemoryProfile(ctx context.Context, options ...rpc.Option) error @@ -143,139 +135,6 @@ func (c *client) GetAtomicUTXOs(ctx context.Context, addrs []ids.ShortID, source return utxos, endAddr, endUTXOID, err } -// ExportKeyArgs are arguments for ExportKey -type ExportKeyArgs struct { - api.UserPass - Address string `json:"address"` -} - -// ExportKeyReply is the response for ExportKey -type ExportKeyReply struct { - // The decrypted PrivateKey for the Address provided in the arguments - PrivateKey *secp256k1.PrivateKey `json:"privateKey"` - PrivateKeyHex string `json:"privateKeyHex"` -} - -// ExportKey returns the private key corresponding to [addr] controlled by [user] -// in both Avalanche standard format and hex format -func (c *client) ExportKey(ctx context.Context, user api.UserPass, addr common.Address, options ...rpc.Option) (*secp256k1.PrivateKey, string, error) { - res := &ExportKeyReply{} - err := c.requester.SendRequest(ctx, "avax.exportKey", &ExportKeyArgs{ - UserPass: user, - Address: addr.Hex(), - }, res, options...) - return res.PrivateKey, res.PrivateKeyHex, err -} - -// ImportKeyArgs are arguments for ImportKey -type ImportKeyArgs struct { - api.UserPass - PrivateKey *secp256k1.PrivateKey `json:"privateKey"` -} - -// ImportKey imports [privateKey] to [user] -func (c *client) ImportKey(ctx context.Context, user api.UserPass, privateKey *secp256k1.PrivateKey, options ...rpc.Option) (common.Address, error) { - res := &api.JSONAddress{} - err := c.requester.SendRequest(ctx, "avax.importKey", &ImportKeyArgs{ - UserPass: user, - PrivateKey: privateKey, - }, res, options...) - if err != nil { - return common.Address{}, err - } - return ParseEthAddress(res.Address) -} - -// ImportArgs are arguments for passing into Import requests -type ImportArgs struct { - api.UserPass - - // Fee that should be used when creating the tx - BaseFee *hexutil.Big `json:"baseFee"` - - // Chain the funds are coming from - SourceChain string `json:"sourceChain"` - - // The address that will receive the imported funds - To common.Address `json:"to"` -} - -// Import sends an import transaction to import funds from [sourceChain] and -// returns the ID of the newly created transaction -func (c *client) Import(ctx context.Context, user api.UserPass, to common.Address, sourceChain string, options ...rpc.Option) (ids.ID, error) { - res := &api.JSONTxID{} - err := c.requester.SendRequest(ctx, "avax.import", &ImportArgs{ - UserPass: user, - To: to, - SourceChain: sourceChain, - }, res, options...) - return res.TxID, err -} - -// ExportAVAX sends AVAX from this chain to the address specified by [to]. -// Returns the ID of the newly created atomic transaction -func (c *client) ExportAVAX( - ctx context.Context, - user api.UserPass, - amount uint64, - to ids.ShortID, - targetChain string, - options ...rpc.Option, -) (ids.ID, error) { - return c.Export(ctx, user, amount, to, targetChain, "AVAX", options...) -} - -// ExportAVAXArgs are the arguments to ExportAVAX -type ExportAVAXArgs struct { - api.UserPass - - // Fee that should be used when creating the tx - BaseFee *hexutil.Big `json:"baseFee"` - - // Amount of asset to send - Amount json.Uint64 `json:"amount"` - - // Chain the funds are going to. Optional. Used if To address does not - // include the chainID. - TargetChain string `json:"targetChain"` - - // ID of the address that will receive the AVAX. This address may include - // the chainID, which is used to determine what the destination chain is. - To string `json:"to"` -} - -// ExportArgs are the arguments to Export -type ExportArgs struct { - ExportAVAXArgs - // AssetID of the tokens - AssetID string `json:"assetID"` -} - -// Export sends an asset from this chain to the P/C-Chain. -// After this tx is accepted, the AVAX must be imported to the P/C-chain with an importTx. -// Returns the ID of the newly created atomic transaction -func (c *client) Export( - ctx context.Context, - user api.UserPass, - amount uint64, - to ids.ShortID, - targetChain string, - assetID string, - options ...rpc.Option, -) (ids.ID, error) { - res := &api.JSONTxID{} - err := c.requester.SendRequest(ctx, "avax.export", &ExportArgs{ - ExportAVAXArgs: ExportAVAXArgs{ - UserPass: user, - Amount: json.Uint64(amount), - TargetChain: targetChain, - To: to.String(), - }, - AssetID: assetID, - }, res, options...) - return res.TxID, err -} - func (c *client) StartCPUProfiler(ctx context.Context, options ...rpc.Option) error { return c.adminRequester.SendRequest(ctx, "admin.startCPUProfiler", struct{}{}, &api.EmptyReply{}, options...) } diff --git a/plugin/evm/client/client_interface_test.go b/plugin/evm/client/client_interface_test.go deleted file mode 100644 index 332bb8bcf4..0000000000 --- a/plugin/evm/client/client_interface_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package client - -import ( - "reflect" - "testing" -) - -func TestInterfaceStructOneToOne(t *testing.T) { - // checks struct provides at least the methods signatures in the interface - var _ Client = (*client)(nil) - // checks interface and struct have the same number of methods - clientType := reflect.TypeOf(&client{}) - ClientType := reflect.TypeOf((*Client)(nil)).Elem() - if clientType.NumMethod() != ClientType.NumMethod() { - t.Fatalf("no 1 to 1 compliance between struct methods (%v) and interface methods (%v)", clientType.NumMethod(), ClientType.NumMethod()) - } -} diff --git a/plugin/evm/config/config.go b/plugin/evm/config/config.go index f5bf644657..3104b0faa9 100644 --- a/plugin/evm/config/config.go +++ b/plugin/evm/config/config.go @@ -59,6 +59,9 @@ const ( // - state sync time: ~6 hrs. defaultStateSyncMinBlocks = 300_000 DefaultStateSyncRequestSize = 1024 // the number of key/values to ask peers for per request + + estimatedBlockAcceptPeriod = 2 * time.Second + defaultHistoricalProofQueryWindow = uint64(24 * time.Hour / estimatedBlockAcceptPeriod) ) var ( @@ -124,6 +127,10 @@ type Config struct { PopulateMissingTriesParallelism int `json:"populate-missing-tries-parallelism"` // Number of concurrent readers to use when re-populating missing tries on startup. PruneWarpDB bool `json:"prune-warp-db-enabled"` // Determines if the warpDB should be cleared on startup + // HistoricalProofQueryWindow is, when running in archive mode only, the number of blocks before the + // last accepted block to be accepted for proof state queries. + HistoricalProofQueryWindow uint64 `json:"historical-proof-query-window,omitempty"` + // Metric Settings MetricsExpensiveEnabled bool `json:"metrics-expensive-enabled"` // Debug-level metrics that might impact runtime performance @@ -288,6 +295,7 @@ func (c *Config) SetDefaults(txPoolConfig TxPoolConfig) { c.StateSyncRequestSize = DefaultStateSyncRequestSize c.AllowUnprotectedTxHashes = defaultAllowUnprotectedTxHashes c.AcceptedCacheSize = defaultAcceptedCacheSize + c.HistoricalProofQueryWindow = defaultHistoricalProofQueryWindow } func (d *Duration) UnmarshalJSON(data []byte) (err error) { diff --git a/plugin/evm/user.go b/plugin/evm/user.go deleted file mode 100644 index 8cb3f73f34..0000000000 --- a/plugin/evm/user.go +++ /dev/null @@ -1,137 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package evm - -import ( - "errors" - - "github.com/ava-labs/avalanchego/database/encdb" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/coreth/plugin/evm/atomic" - "github.com/ethereum/go-ethereum/common" -) - -// Key in the database whose corresponding value is the list of -// addresses this user controls -var addressesKey = ids.Empty[:] - -var ( - errDBNil = errors.New("db uninitialized") - errKeyNil = errors.New("key uninitialized") -) - -type user struct { - // This user's database, acquired from the keystore - db *encdb.Database -} - -// Get the addresses controlled by this user -func (u *user) getAddresses() ([]common.Address, error) { - if u.db == nil { - return nil, errDBNil - } - - // If user has no addresses, return empty list - hasAddresses, err := u.db.Has(addressesKey) - if err != nil { - return nil, err - } - if !hasAddresses { - return nil, nil - } - - // User has addresses. Get them. - bytes, err := u.db.Get(addressesKey) - if err != nil { - return nil, err - } - addresses := []common.Address{} - if _, err := atomic.Codec.Unmarshal(bytes, &addresses); err != nil { - return nil, err - } - return addresses, nil -} - -// controlsAddress returns true iff this user controls the given address -func (u *user) controlsAddress(address common.Address) (bool, error) { - if u.db == nil { - return false, errDBNil - //} else if address.IsZero() { - // return false, errEmptyAddress - } - return u.db.Has(address.Bytes()) -} - -// putAddress persists that this user controls address controlled by [privKey] -func (u *user) putAddress(privKey *secp256k1.PrivateKey) error { - if privKey == nil { - return errKeyNil - } - - address := privKey.EthAddress() // address the privKey controls - controlsAddress, err := u.controlsAddress(address) - if err != nil { - return err - } - if controlsAddress { // user already controls this address. Do nothing. - return nil - } - - if err := u.db.Put(address.Bytes(), privKey.Bytes()); err != nil { // Address --> private key - return err - } - - addresses := make([]common.Address, 0) // Add address to list of addresses user controls - userHasAddresses, err := u.db.Has(addressesKey) - if err != nil { - return err - } - if userHasAddresses { // Get addresses this user already controls, if they exist - if addresses, err = u.getAddresses(); err != nil { - return err - } - } - addresses = append(addresses, address) - bytes, err := atomic.Codec.Marshal(atomic.CodecVersion, addresses) - if err != nil { - return err - } - if err := u.db.Put(addressesKey, bytes); err != nil { - return err - } - return nil -} - -// Key returns the private key that controls the given address -func (u *user) getKey(address common.Address) (*secp256k1.PrivateKey, error) { - if u.db == nil { - return nil, errDBNil - //} else if address.IsZero() { - // return nil, errEmptyAddress - } - - bytes, err := u.db.Get(address.Bytes()) - if err != nil { - return nil, err - } - return secp256k1.ToPrivateKey(bytes) -} - -// Return all private keys controlled by this user -func (u *user) getKeys() ([]*secp256k1.PrivateKey, error) { - addrs, err := u.getAddresses() - if err != nil { - return nil, err - } - keys := make([]*secp256k1.PrivateKey, len(addrs)) - for i, addr := range addrs { - key, err := u.getKey(addr) - if err != nil { - return nil, err - } - keys[i] = key - } - return keys, nil -} diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 3928f80577..a7990e16f6 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -502,6 +502,7 @@ func (vm *VM) Initialize( vm.ethConfig.SnapshotDelayInit = vm.stateSyncEnabled(lastAcceptedHeight) vm.ethConfig.SnapshotWait = vm.config.SnapshotWait vm.ethConfig.SnapshotVerify = vm.config.SnapshotVerify + vm.ethConfig.HistoricalProofQueryWindow = vm.config.HistoricalProofQueryWindow vm.ethConfig.OfflinePruning = vm.config.OfflinePruning vm.ethConfig.OfflinePruningBloomFilterSize = vm.config.OfflinePruningBloomFilterSize vm.ethConfig.OfflinePruningDataDirectory = vm.config.OfflinePruningDataDirectory @@ -1766,23 +1767,6 @@ func (vm *VM) startContinuousProfiler() { <-vm.shutdownChan } -func (vm *VM) estimateBaseFee(ctx context.Context) (*big.Int, error) { - // Get the base fee to use - baseFee, err := vm.eth.APIBackend.EstimateBaseFee(ctx) - if err != nil { - return nil, err - } - if baseFee == nil { - baseFee = initialBaseFee - } else { - // give some breathing room - baseFee.Mul(baseFee, big.NewInt(11)) - baseFee.Div(baseFee, big.NewInt(10)) - } - - return baseFee, nil -} - // readLastAccepted reads the last accepted hash from [acceptedBlockDB] and returns the // last accepted block hash and height by reading directly from [vm.chaindb] instead of relying // on [chain]. diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index fbae28b871..ef0f557904 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -33,7 +33,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/api/keystore" avalancheatomic "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" @@ -45,7 +44,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/utils/units" @@ -72,8 +70,6 @@ var ( testKeys []*secp256k1.PrivateKey testEthAddrs []common.Address // testEthAddrs[i] corresponds to testKeys[i] testShortIDAddrs []ids.ShortID - username = "Johns" - password = "CjasdjhiPeirbSenfeI13" // #nosec G101 genesisJSON = func(cfg *params.ChainConfig) string { g := new(core.Genesis) @@ -219,12 +215,6 @@ func setupGenesis( // The caller of this function is responsible for unlocking. ctx.Lock.Lock() - userKeystore := keystore.New(logging.NoLog{}, memdb.New()) - if err := userKeystore.CreateUser(username, password); err != nil { - t.Fatal(err) - } - ctx.Keystore = userKeystore.NewBlockchainKeyStore(ctx.ChainID) - issuer := make(chan commonEng.Message, 1) prefixedDB := prefixdb.New([]byte{1}, baseDB) return ctx, prefixedDB, genesisBytes, issuer, atomicMemory diff --git a/scripts/versions.sh b/scripts/versions.sh index ba63c1148c..42e3dcf479 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -6,4 +6,4 @@ set -euo pipefail # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'902377d447ba'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'54d8b06b'}