From b16fc67e21d07b9b3a934ce3fe3ba49bc3bad310 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 7 Jan 2025 13:30:33 +0100 Subject: [PATCH 01/11] chore(scripts): simplify mocks generation (#721) * header.yml is missing so removing ineffective go-license * Remove unneeded source constants * Remove unneeded source versions * Use go generate commands to generate mocks * Remove the need to install mockgen in the script * Add mock-up-to-date step to test CI workflow * Remove all mocks before generating them in CI * Add generate command for non-tracked mock (Note using source mode was compulsory due to CGO) * Use bash shell for mock check step * Remove script mock.gen.sh * docs(contributing): add mocks section * mockgen version used is the one defined in go.mod - requires a `tools.go` blank importing golang.org/x/tools/imports in order to have the `golang.org/x/tools` dependency satisfied for mockgen v0.4 - less future deltas when upgrading mockgen * ci: use more precise go generate regex * Add `git add --intent-to-add --all` to detect untracked files * Add copyright notices --- .github/CONTRIBUTING.md | 33 +++++++++++ .github/workflows/ci.yml | 7 +++ go.mod | 3 +- go.sum | 14 ++--- precompile/contract/mocks.go | 45 ++++++++------- precompile/contract/mocks_generate_test.go | 6 ++ precompile/precompileconfig/mocks.go | 38 +++++++------ .../precompileconfig/mocks_generate_test.go | 6 ++ scripts/mock.gen.sh | 44 --------------- scripts/mocks.mockgen.txt | 2 - tools.go | 8 +++ warp/aggregator/mock_signature_getter.go | 55 +++++++++++++++++-- warp/aggregator/mocks_generate_test.go | 6 ++ 13 files changed, 167 insertions(+), 100 deletions(-) create mode 100644 precompile/contract/mocks_generate_test.go create mode 100644 precompile/precompileconfig/mocks_generate_test.go delete mode 100755 scripts/mock.gen.sh delete mode 100644 scripts/mocks.mockgen.txt create mode 100644 tools.go create mode 100644 warp/aggregator/mocks_generate_test.go diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 87c79fcfe2..9e89d2d0da 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,3 +33,36 @@ Please make sure your contributions adhere to our coding guidelines: Before you submit a feature request, please check and make sure that it isn't possible through some other means. +## Mocks + +Mocks are auto-generated using [mockgen](https://pkg.go.dev/go.uber.org/mock/mockgen) and `//go:generate` commands in the code. + +* To **re-generate all mocks**, use the command below from the root of the project: + + ```sh + go generate -run "go.uber.org/mock/mockgen" ./... + ``` + +* To **add** an interface that needs a corresponding mock generated: + * if the file `mocks_generate_test.go` exists in the package where the interface is located, either: + * modify its `//go:generate go run go.uber.org/mock/mockgen` to generate a mock for your interface (preferred); or + * add another `//go:generate go run go.uber.org/mock/mockgen` to generate a mock for your interface according to specific mock generation settings + * if the file `mocks_generate_test.go` does not exist in the package where the interface is located, create it with content (adapt as needed): + + ```go + // Copyright (C) 2025-2025, Ava Labs, Inc. All rights reserved. + // See the file LICENSE for licensing terms. + + package mypackage + + //go:generate go run go.uber.org/mock/mockgen -package=${GOPACKAGE} -destination=mocks_test.go . YourInterface + ``` + + Notes: + 1. Ideally generate all mocks to `mocks_test.go` for the package you need to use the mocks for and do not export mocks to other packages. This reduces package dependencies, reduces production code pollution and forces to have locally defined narrow interfaces. + 1. Prefer using reflect mode to generate mocks than source mode, unless you need a mock for an unexported interface, which should be rare. +* To **remove** an interface from having a corresponding mock generated: + 1. Edit the `mocks_generate_test.go` file in the directory where the interface is defined + 1. If the `//go:generate` mockgen command line: + * generates a mock file for multiple interfaces, remove your interface from the line + * generates a mock file only for the interface, remove the entire line. If the file is empty, remove `mocks_generate_test.go` as well. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 553c2761d7..48056c04f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,13 @@ jobs: run: echo "TIMEOUT=1200s" >> "$GITHUB_ENV" - run: go mod download shell: bash + - name: Mocks are up to date + shell: bash + run: | + grep -lr -E '^// Code generated by MockGen\. DO NOT EDIT\.$' . | xargs -r rm + go generate -run "go.uber.org/mock/mockgen" ./... + git add --intent-to-add --all + git diff --exit-code - run: ./scripts/build.sh evm shell: bash - run: ./scripts/build_test.sh diff --git a/go.mod b/go.mod index a4acd1705f..63146cd8d2 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( golang.org/x/sys v0.28.0 golang.org/x/text v0.21.0 golang.org/x/time v0.3.0 + golang.org/x/tools v0.22.0 google.golang.org/protobuf v1.34.2 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -120,7 +121,7 @@ require ( go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/mod v0.18.0 // indirect + golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/term v0.27.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect diff --git a/go.sum b/go.sum index 4bf0d64d42..9391e7bb79 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,6 @@ 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.20241224161435-3998475d671d h1:QCtjS4ANcNfCdL6Z2sKpanDVJNt1MU0bUyVdW0g5zuU= -github.com/ava-labs/avalanchego v1.12.2-0.20241224161435-3998475d671d/go.mod h1:cDoT0Hq3P+/XfCyVvzrBj66yoid2I5LnMuj7LIkap+o= -github.com/ava-labs/avalanchego v1.12.2-0.20241224181600-fade5be3051d h1:iPlsqC9pIy4emCo8wyI/VmVmfljpzmw58ZqahVdcehI= -github.com/ava-labs/avalanchego v1.12.2-0.20241224181600-fade5be3051d/go.mod h1:dKawab3nXqwI7ZcOFatTOv//l1V0t8MRBnhXoOqbN4E= 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/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -586,8 +582,6 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -647,8 +641,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -693,8 +687,6 @@ golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -865,6 +857,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/precompile/contract/mocks.go b/precompile/contract/mocks.go index 94bf9c5ba0..546090339f 100644 --- a/precompile/contract/mocks.go +++ b/precompile/contract/mocks.go @@ -3,7 +3,7 @@ // // Generated by this command: // -// mockgen -package=contract -destination=precompile/contract/mocks.go github.com/ava-labs/coreth/precompile/contract BlockContext,AccessibleState,StateDB +// mockgen -package=contract -destination=mocks.go . BlockContext,AccessibleState,StateDB // // Package contract is a generated GoMock package. @@ -24,6 +24,7 @@ import ( type MockBlockContext struct { ctrl *gomock.Controller recorder *MockBlockContextMockRecorder + isgomock struct{} } // MockBlockContextMockRecorder is the mock recorder for MockBlockContext. @@ -44,17 +45,17 @@ func (m *MockBlockContext) EXPECT() *MockBlockContextMockRecorder { } // GetPredicateResults mocks base method. -func (m *MockBlockContext) GetPredicateResults(arg0 common.Hash, arg1 common.Address) []byte { +func (m *MockBlockContext) GetPredicateResults(txHash common.Hash, precompileAddress common.Address) []byte { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPredicateResults", arg0, arg1) + ret := m.ctrl.Call(m, "GetPredicateResults", txHash, precompileAddress) ret0, _ := ret[0].([]byte) return ret0 } // GetPredicateResults indicates an expected call of GetPredicateResults. -func (mr *MockBlockContextMockRecorder) GetPredicateResults(arg0, arg1 any) *gomock.Call { +func (mr *MockBlockContextMockRecorder) GetPredicateResults(txHash, precompileAddress any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPredicateResults", reflect.TypeOf((*MockBlockContext)(nil).GetPredicateResults), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPredicateResults", reflect.TypeOf((*MockBlockContext)(nil).GetPredicateResults), txHash, precompileAddress) } // Number mocks base method. @@ -89,6 +90,7 @@ func (mr *MockBlockContextMockRecorder) Timestamp() *gomock.Call { type MockAccessibleState struct { ctrl *gomock.Controller recorder *MockAccessibleStateMockRecorder + isgomock struct{} } // MockAccessibleStateMockRecorder is the mock recorder for MockAccessibleState. @@ -165,9 +167,9 @@ func (mr *MockAccessibleStateMockRecorder) GetStateDB() *gomock.Call { } // NativeAssetCall mocks base method. -func (m *MockAccessibleState) NativeAssetCall(arg0 common.Address, arg1 []byte, arg2, arg3 uint64, arg4 bool) ([]byte, uint64, error) { +func (m *MockAccessibleState) NativeAssetCall(caller common.Address, input []byte, suppliedGas, gasCost uint64, readOnly bool) ([]byte, uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NativeAssetCall", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "NativeAssetCall", caller, input, suppliedGas, gasCost, readOnly) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(uint64) ret2, _ := ret[2].(error) @@ -175,15 +177,16 @@ func (m *MockAccessibleState) NativeAssetCall(arg0 common.Address, arg1 []byte, } // NativeAssetCall indicates an expected call of NativeAssetCall. -func (mr *MockAccessibleStateMockRecorder) NativeAssetCall(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call { +func (mr *MockAccessibleStateMockRecorder) NativeAssetCall(caller, input, suppliedGas, gasCost, readOnly any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NativeAssetCall", reflect.TypeOf((*MockAccessibleState)(nil).NativeAssetCall), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NativeAssetCall", reflect.TypeOf((*MockAccessibleState)(nil).NativeAssetCall), caller, input, suppliedGas, gasCost, readOnly) } // MockStateDB is a mock of StateDB interface. type MockStateDB struct { ctrl *gomock.Controller recorder *MockStateDBMockRecorder + isgomock struct{} } // MockStateDBMockRecorder is the mock recorder for MockStateDB. @@ -216,15 +219,15 @@ func (mr *MockStateDBMockRecorder) AddBalance(arg0, arg1 any) *gomock.Call { } // AddLog mocks base method. -func (m *MockStateDB) AddLog(arg0 common.Address, arg1 []common.Hash, arg2 []byte, arg3 uint64) { +func (m *MockStateDB) AddLog(addr common.Address, topics []common.Hash, data []byte, blockNumber uint64) { m.ctrl.T.Helper() - m.ctrl.Call(m, "AddLog", arg0, arg1, arg2, arg3) + m.ctrl.Call(m, "AddLog", addr, topics, data, blockNumber) } // AddLog indicates an expected call of AddLog. -func (mr *MockStateDBMockRecorder) AddLog(arg0, arg1, arg2, arg3 any) *gomock.Call { +func (mr *MockStateDBMockRecorder) AddLog(addr, topics, data, blockNumber any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLog", reflect.TypeOf((*MockStateDB)(nil).AddLog), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLog", reflect.TypeOf((*MockStateDB)(nil).AddLog), addr, topics, data, blockNumber) } // CreateAccount mocks base method. @@ -311,18 +314,18 @@ func (mr *MockStateDBMockRecorder) GetNonce(arg0 any) *gomock.Call { } // GetPredicateStorageSlots mocks base method. -func (m *MockStateDB) GetPredicateStorageSlots(arg0 common.Address, arg1 int) ([]byte, bool) { +func (m *MockStateDB) GetPredicateStorageSlots(address common.Address, index int) ([]byte, bool) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPredicateStorageSlots", arg0, arg1) + ret := m.ctrl.Call(m, "GetPredicateStorageSlots", address, index) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(bool) return ret0, ret1 } // GetPredicateStorageSlots indicates an expected call of GetPredicateStorageSlots. -func (mr *MockStateDBMockRecorder) GetPredicateStorageSlots(arg0, arg1 any) *gomock.Call { +func (mr *MockStateDBMockRecorder) GetPredicateStorageSlots(address, index any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPredicateStorageSlots", reflect.TypeOf((*MockStateDB)(nil).GetPredicateStorageSlots), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPredicateStorageSlots", reflect.TypeOf((*MockStateDB)(nil).GetPredicateStorageSlots), address, index) } // GetState mocks base method. @@ -378,15 +381,15 @@ func (mr *MockStateDBMockRecorder) SetNonce(arg0, arg1 any) *gomock.Call { } // SetPredicateStorageSlots mocks base method. -func (m *MockStateDB) SetPredicateStorageSlots(arg0 common.Address, arg1 [][]byte) { +func (m *MockStateDB) SetPredicateStorageSlots(address common.Address, predicates [][]byte) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetPredicateStorageSlots", arg0, arg1) + m.ctrl.Call(m, "SetPredicateStorageSlots", address, predicates) } // SetPredicateStorageSlots indicates an expected call of SetPredicateStorageSlots. -func (mr *MockStateDBMockRecorder) SetPredicateStorageSlots(arg0, arg1 any) *gomock.Call { +func (mr *MockStateDBMockRecorder) SetPredicateStorageSlots(address, predicates any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPredicateStorageSlots", reflect.TypeOf((*MockStateDB)(nil).SetPredicateStorageSlots), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPredicateStorageSlots", reflect.TypeOf((*MockStateDB)(nil).SetPredicateStorageSlots), address, predicates) } // SetState mocks base method. diff --git a/precompile/contract/mocks_generate_test.go b/precompile/contract/mocks_generate_test.go new file mode 100644 index 0000000000..ab422832da --- /dev/null +++ b/precompile/contract/mocks_generate_test.go @@ -0,0 +1,6 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package contract + +//go:generate go run go.uber.org/mock/mockgen -package=$GOPACKAGE -destination=mocks.go . BlockContext,AccessibleState,StateDB diff --git a/precompile/precompileconfig/mocks.go b/precompile/precompileconfig/mocks.go index 4be7f046ec..cba1ca13a3 100644 --- a/precompile/precompileconfig/mocks.go +++ b/precompile/precompileconfig/mocks.go @@ -3,7 +3,7 @@ // // Generated by this command: // -// mockgen -package=precompileconfig -destination=precompile/precompileconfig/mocks.go github.com/ava-labs/coreth/precompile/precompileconfig Predicater,Config,ChainConfig,Accepter +// mockgen -package=precompileconfig -destination=mocks.go . Predicater,Config,ChainConfig,Accepter // // Package precompileconfig is a generated GoMock package. @@ -20,6 +20,7 @@ import ( type MockPredicater struct { ctrl *gomock.Controller recorder *MockPredicaterMockRecorder + isgomock struct{} } // MockPredicaterMockRecorder is the mock recorder for MockPredicater. @@ -40,38 +41,39 @@ func (m *MockPredicater) EXPECT() *MockPredicaterMockRecorder { } // PredicateGas mocks base method. -func (m *MockPredicater) PredicateGas(arg0 []byte) (uint64, error) { +func (m *MockPredicater) PredicateGas(predicateBytes []byte) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PredicateGas", arg0) + ret := m.ctrl.Call(m, "PredicateGas", predicateBytes) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // PredicateGas indicates an expected call of PredicateGas. -func (mr *MockPredicaterMockRecorder) PredicateGas(arg0 any) *gomock.Call { +func (mr *MockPredicaterMockRecorder) PredicateGas(predicateBytes any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PredicateGas", reflect.TypeOf((*MockPredicater)(nil).PredicateGas), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PredicateGas", reflect.TypeOf((*MockPredicater)(nil).PredicateGas), predicateBytes) } // VerifyPredicate mocks base method. -func (m *MockPredicater) VerifyPredicate(arg0 *PredicateContext, arg1 []byte) error { +func (m *MockPredicater) VerifyPredicate(predicateContext *PredicateContext, predicateBytes []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VerifyPredicate", arg0, arg1) + ret := m.ctrl.Call(m, "VerifyPredicate", predicateContext, predicateBytes) ret0, _ := ret[0].(error) return ret0 } // VerifyPredicate indicates an expected call of VerifyPredicate. -func (mr *MockPredicaterMockRecorder) VerifyPredicate(arg0, arg1 any) *gomock.Call { +func (mr *MockPredicaterMockRecorder) VerifyPredicate(predicateContext, predicateBytes any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifyPredicate", reflect.TypeOf((*MockPredicater)(nil).VerifyPredicate), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifyPredicate", reflect.TypeOf((*MockPredicater)(nil).VerifyPredicate), predicateContext, predicateBytes) } // MockConfig is a mock of Config interface. type MockConfig struct { ctrl *gomock.Controller recorder *MockConfigMockRecorder + isgomock struct{} } // MockConfigMockRecorder is the mock recorder for MockConfig. @@ -165,6 +167,7 @@ func (mr *MockConfigMockRecorder) Verify(arg0 any) *gomock.Call { type MockChainConfig struct { ctrl *gomock.Controller recorder *MockChainConfigMockRecorder + isgomock struct{} } // MockChainConfigMockRecorder is the mock recorder for MockChainConfig. @@ -185,23 +188,24 @@ func (m *MockChainConfig) EXPECT() *MockChainConfigMockRecorder { } // IsDurango mocks base method. -func (m *MockChainConfig) IsDurango(arg0 uint64) bool { +func (m *MockChainConfig) IsDurango(time uint64) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsDurango", arg0) + ret := m.ctrl.Call(m, "IsDurango", time) ret0, _ := ret[0].(bool) return ret0 } // IsDurango indicates an expected call of IsDurango. -func (mr *MockChainConfigMockRecorder) IsDurango(arg0 any) *gomock.Call { +func (mr *MockChainConfigMockRecorder) IsDurango(time any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsDurango", reflect.TypeOf((*MockChainConfig)(nil).IsDurango), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsDurango", reflect.TypeOf((*MockChainConfig)(nil).IsDurango), time) } // MockAccepter is a mock of Accepter interface. type MockAccepter struct { ctrl *gomock.Controller recorder *MockAccepterMockRecorder + isgomock struct{} } // MockAccepterMockRecorder is the mock recorder for MockAccepter. @@ -222,15 +226,15 @@ func (m *MockAccepter) EXPECT() *MockAccepterMockRecorder { } // Accept mocks base method. -func (m *MockAccepter) Accept(arg0 *AcceptContext, arg1 common.Hash, arg2 uint64, arg3 common.Hash, arg4 int, arg5 []common.Hash, arg6 []byte) error { +func (m *MockAccepter) Accept(acceptCtx *AcceptContext, blockHash common.Hash, blockNumber uint64, txHash common.Hash, logIndex int, topics []common.Hash, logData []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Accept", arg0, arg1, arg2, arg3, arg4, arg5, arg6) + ret := m.ctrl.Call(m, "Accept", acceptCtx, blockHash, blockNumber, txHash, logIndex, topics, logData) ret0, _ := ret[0].(error) return ret0 } // Accept indicates an expected call of Accept. -func (mr *MockAccepterMockRecorder) Accept(arg0, arg1, arg2, arg3, arg4, arg5, arg6 any) *gomock.Call { +func (mr *MockAccepterMockRecorder) Accept(acceptCtx, blockHash, blockNumber, txHash, logIndex, topics, logData any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockAccepter)(nil).Accept), arg0, arg1, arg2, arg3, arg4, arg5, arg6) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockAccepter)(nil).Accept), acceptCtx, blockHash, blockNumber, txHash, logIndex, topics, logData) } diff --git a/precompile/precompileconfig/mocks_generate_test.go b/precompile/precompileconfig/mocks_generate_test.go new file mode 100644 index 0000000000..9ca4ea38df --- /dev/null +++ b/precompile/precompileconfig/mocks_generate_test.go @@ -0,0 +1,6 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package precompileconfig + +//go:generate go run go.uber.org/mock/mockgen -package=$GOPACKAGE -destination=mocks.go . Predicater,Config,ChainConfig,Accepter diff --git a/scripts/mock.gen.sh b/scripts/mock.gen.sh deleted file mode 100755 index 87465d43a9..0000000000 --- a/scripts/mock.gen.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Root directory -CORETH_PATH=$( - cd "$(dirname "${BASH_SOURCE[0]}")" - cd .. && pwd -) - -if ! [[ "$0" =~ scripts/mock.gen.sh ]]; then - echo "must be run from repository root" - exit 255 -fi - -# https://github.com/uber-go/mock -go install -v go.uber.org/mock/mockgen@v0.4.0 - -if ! command -v go-license &>/dev/null; then - echo "go-license not found, installing..." - # https://github.com/palantir/go-license - go install -v github.com/palantir/go-license@v1.25.0 -fi - -# Load the versions -source "$CORETH_PATH"/scripts/versions.sh - -# Load the constants -source "$CORETH_PATH"/scripts/constants.sh - -# tuples of (source interface import path, comma-separated interface names, output file path) -input="scripts/mocks.mockgen.txt" -while IFS= read -r line; do - IFS='=' read -r src_import_path interface_name output_path <<<"${line}" - package_name=$(basename "$(dirname "$output_path")") - echo "Generating ${output_path}..." - mockgen -package="${package_name}" -destination="${output_path}" "${src_import_path}" "${interface_name}" - - go-license \ - --config=./header.yml \ - "${output_path}" -done <"$input" - -echo "SUCCESS" diff --git a/scripts/mocks.mockgen.txt b/scripts/mocks.mockgen.txt deleted file mode 100644 index 694343e40e..0000000000 --- a/scripts/mocks.mockgen.txt +++ /dev/null @@ -1,2 +0,0 @@ -github.com/ava-labs/coreth/precompile/precompileconfig=Predicater,Config,ChainConfig,Accepter=precompile/precompileconfig/mocks.go -github.com/ava-labs/coreth/precompile/contract=BlockContext,AccessibleState,StateDB=precompile/contract/mocks.go diff --git a/tools.go b/tools.go new file mode 100644 index 0000000000..d7c65266dd --- /dev/null +++ b/tools.go @@ -0,0 +1,8 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package coreth + +import ( + _ "golang.org/x/tools/imports" // golang.org/x/tools to satisfy requirement for go.uber.org/mock/mockgen@v0.5 +) diff --git a/warp/aggregator/mock_signature_getter.go b/warp/aggregator/mock_signature_getter.go index 144d8a2f98..70365da0ce 100644 --- a/warp/aggregator/mock_signature_getter.go +++ b/warp/aggregator/mock_signature_getter.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/coreth/warp/aggregator (interfaces: SignatureGetter) +// Source: signature_getter.go +// +// Generated by this command: +// +// mockgen -package=aggregator -source=signature_getter.go -destination=mock_signature_getter.go +// // Package aggregator is a generated GoMock package. package aggregator @@ -18,6 +23,7 @@ import ( type MockSignatureGetter struct { ctrl *gomock.Controller recorder *MockSignatureGetterMockRecorder + isgomock struct{} } // MockSignatureGetterMockRecorder is the mock recorder for MockSignatureGetter. @@ -38,16 +44,55 @@ func (m *MockSignatureGetter) EXPECT() *MockSignatureGetterMockRecorder { } // GetSignature mocks base method. -func (m *MockSignatureGetter) GetSignature(arg0 context.Context, arg1 ids.NodeID, arg2 *warp.UnsignedMessage) (*bls.Signature, error) { +func (m *MockSignatureGetter) GetSignature(ctx context.Context, nodeID ids.NodeID, unsignedWarpMessage *warp.UnsignedMessage) (*bls.Signature, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSignature", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetSignature", ctx, nodeID, unsignedWarpMessage) ret0, _ := ret[0].(*bls.Signature) ret1, _ := ret[1].(error) return ret0, ret1 } // GetSignature indicates an expected call of GetSignature. -func (mr *MockSignatureGetterMockRecorder) GetSignature(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockSignatureGetterMockRecorder) GetSignature(ctx, nodeID, unsignedWarpMessage any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSignature", reflect.TypeOf((*MockSignatureGetter)(nil).GetSignature), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSignature", reflect.TypeOf((*MockSignatureGetter)(nil).GetSignature), ctx, nodeID, unsignedWarpMessage) +} + +// MockNetworkClient is a mock of NetworkClient interface. +type MockNetworkClient struct { + ctrl *gomock.Controller + recorder *MockNetworkClientMockRecorder + isgomock struct{} +} + +// MockNetworkClientMockRecorder is the mock recorder for MockNetworkClient. +type MockNetworkClientMockRecorder struct { + mock *MockNetworkClient +} + +// NewMockNetworkClient creates a new mock instance. +func NewMockNetworkClient(ctrl *gomock.Controller) *MockNetworkClient { + mock := &MockNetworkClient{ctrl: ctrl} + mock.recorder = &MockNetworkClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockNetworkClient) EXPECT() *MockNetworkClientMockRecorder { + return m.recorder +} + +// SendAppRequest mocks base method. +func (m *MockNetworkClient) SendAppRequest(ctx context.Context, nodeID ids.NodeID, message []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendAppRequest", ctx, nodeID, message) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SendAppRequest indicates an expected call of SendAppRequest. +func (mr *MockNetworkClientMockRecorder) SendAppRequest(ctx, nodeID, message any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendAppRequest", reflect.TypeOf((*MockNetworkClient)(nil).SendAppRequest), ctx, nodeID, message) } diff --git a/warp/aggregator/mocks_generate_test.go b/warp/aggregator/mocks_generate_test.go new file mode 100644 index 0000000000..46388a6c7c --- /dev/null +++ b/warp/aggregator/mocks_generate_test.go @@ -0,0 +1,6 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package aggregator + +//go:generate go run go.uber.org/mock/mockgen -package=$GOPACKAGE -source=signature_getter.go -destination=mock_signature_getter.go From 7c069d88ee75c8104ed9839f050a2d5b291afada Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Tue, 7 Jan 2025 05:59:17 -0800 Subject: [PATCH 02/11] Sync subnet-evm changes up to 981830ed (#737) * small changes * relevant warp changes * use wrapped db package * nit * equivalent to subnet-evm 843e3f7 * add multiatch docker build to support arm (#1417) * remove build_docker_image.sh --------- Co-authored-by: Ceyhun Onur --- consensus/dummy/README.md | 2 +- core/state/pruner/pruner.go | 2 +- eth/tracers/js/tracer_test.go | 2 +- eth/tracers/logger/access_list_tracer.go | 2 +- plugin/evm/{service.go => api.go} | 0 plugin/evm/atomic_trie.go | 33 ++++---- plugin/evm/block.go | 4 +- .../wrapped_database.go} | 32 ++++---- plugin/evm/export_tx_test.go | 6 +- plugin/evm/syncervm_test.go | 9 +- plugin/evm/vm.go | 57 +++++-------- plugin/evm/vm_database.go | 82 +++++++++++++++++++ plugin/evm/vm_test.go | 2 +- precompile/contract/interfaces.go | 2 +- precompile/contracts/warp/README.md | 2 +- rpc/handler.go | 2 +- rpc/types.go | 2 +- scripts/build_docker_image.sh | 23 ------ scripts/known_flakes.txt | 1 + sync/statesync/trie_sync_stats.go | 2 +- warp/aggregator/aggregator_test.go | 2 +- warp/backend.go | 2 +- warp/backend_test.go | 7 ++ warp/verifier_backend.go | 8 +- warp/verifier_backend_test.go | 10 +-- warp/verifier_stats.go | 10 +-- 26 files changed, 184 insertions(+), 122 deletions(-) rename plugin/evm/{service.go => api.go} (100%) rename plugin/evm/{database.go => database/wrapped_database.go} (55%) create mode 100644 plugin/evm/vm_database.go delete mode 100755 scripts/build_docker_image.sh diff --git a/consensus/dummy/README.md b/consensus/dummy/README.md index 23ff20072a..cca69cf239 100644 --- a/consensus/dummy/README.md +++ b/consensus/dummy/README.md @@ -18,7 +18,7 @@ The dynamic fee algorithm aims to adjust the base fee to handle network congesti - EIP-1559 is intended for Ethereum where a block is produced roughly every 10s - C-Chain typically produces blocks every 2 seconds, but the dynamic fee algorithm needs to handle the case that the network quiesces and there are no blocks for a long period of time -- Since C-Chain produces blocks at a different cadence, it adapts EIP-1559 to sum the amount of gas consumed within a 10 second interval instead of using only the amount of gas consumed in the parent block +- Since C-Chain produces blocks at a different cadence, it adapts EIP-1559 to sum the amount of gas consumed within a 10-second interval instead of using only the amount of gas consumed in the parent block ## Consensus Engine Callbacks diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 29431a0ecd..090b7ac6af 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -52,7 +52,7 @@ const ( // stateBloomFilePrefix is the filename prefix of state bloom filter. stateBloomFilePrefix = "statebloom" - // stateBloomFilePrefix is the filename suffix of state bloom filter. + // stateBloomFileSuffix is the filename suffix of state bloom filter. stateBloomFileSuffix = "bf.gz" // stateBloomFileTempSuffix is the filename suffix of state bloom filter diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index 7e46c0aa20..746fc0eb0e 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -206,7 +206,7 @@ func TestHaltBetweenSteps(t *testing.T) { } } -// testNoStepExec tests a regular value transfer (no exec), and accessing the statedb +// TestNoStepExec tests a regular value transfer (no exec), and accessing the statedb // in 'result' func TestNoStepExec(t *testing.T) { execTracer := func(code string) []byte { diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index e2bb12f2d7..d43198a2ff 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -87,7 +87,7 @@ func (al accessList) equal(other accessList) bool { return true } -// accesslist converts the accesslist to a types.AccessList. +// accessList converts the accesslist to a types.AccessList. func (al accessList) accessList() types.AccessList { acl := make(types.AccessList, 0, len(al)) for addr, slots := range al { diff --git a/plugin/evm/service.go b/plugin/evm/api.go similarity index 100% rename from plugin/evm/service.go rename to plugin/evm/api.go diff --git a/plugin/evm/atomic_trie.go b/plugin/evm/atomic_trie.go index d734268e23..f6add46623 100644 --- a/plugin/evm/atomic_trie.go +++ b/plugin/evm/atomic_trie.go @@ -9,7 +9,7 @@ import ( avalancheatomic "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/codec" - "github.com/ava-labs/avalanchego/database" + avalanchedatabase "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" @@ -18,6 +18,7 @@ import ( "github.com/ava-labs/coreth/core/rawdb" "github.com/ava-labs/coreth/core/types" "github.com/ava-labs/coreth/plugin/evm/atomic" + "github.com/ava-labs/coreth/plugin/evm/database" "github.com/ava-labs/coreth/trie" "github.com/ava-labs/coreth/trie/trienode" "github.com/ava-labs/coreth/triedb" @@ -117,12 +118,12 @@ type AtomicTrieIterator interface { // atomicTrie implements the AtomicTrie interface type atomicTrie struct { - commitInterval uint64 // commit interval, same as commitHeightInterval by default - metadataDB database.Database // Underlying database containing the atomic trie metadata - trieDB *triedb.Database // Trie database - lastCommittedRoot common.Hash // trie root of the most recent commit - lastCommittedHeight uint64 // index height of the most recent commit - lastAcceptedRoot common.Hash // most recent trie root passed to accept trie or the root of the atomic trie on intialization. + commitInterval uint64 // commit interval, same as commitHeightInterval by default + metadataDB avalanchedatabase.Database // Underlying database containing the atomic trie metadata + trieDB *triedb.Database // Trie database + lastCommittedRoot common.Hash // trie root of the most recent commit + lastCommittedHeight uint64 // index height of the most recent commit + lastAcceptedRoot common.Hash // most recent trie root passed to accept trie or the root of the atomic trie on intialization. codec codec.Manager memoryCap common.StorageSize tipBuffer *core.BoundedBuffer[common.Hash] @@ -131,7 +132,7 @@ type atomicTrie struct { // newAtomicTrie returns a new instance of a atomicTrie with a configurable commitHeightInterval, used in testing. // Initializes the trie before returning it. func newAtomicTrie( - atomicTrieDB database.Database, metadataDB database.Database, + atomicTrieDB avalanchedatabase.Database, metadataDB avalanchedatabase.Database, codec codec.Manager, lastAcceptedHeight uint64, commitHeightInterval uint64, ) (*atomicTrie, error) { root, height, err := lastCommittedRootIfExists(metadataDB) @@ -153,7 +154,7 @@ func newAtomicTrie( } trieDB := triedb.NewDatabase( - rawdb.NewDatabase(Database{atomicTrieDB}), + rawdb.NewDatabase(database.WrapDatabase(atomicTrieDB)), &triedb.Config{ HashDB: &hashdb.Config{ CleanCacheSize: 64 * units.MiB, // Allocate 64MB of memory for clean cache @@ -182,17 +183,17 @@ func newAtomicTrie( // else returns empty common.Hash{} and 0 // returns error only if there are issues with the underlying data store // or if values present in the database are not as expected -func lastCommittedRootIfExists(db database.Database) (common.Hash, uint64, error) { +func lastCommittedRootIfExists(db avalanchedatabase.Database) (common.Hash, uint64, error) { // read the last committed entry if it exists and set the root hash lastCommittedHeightBytes, err := db.Get(lastCommittedKey) switch { - case err == database.ErrNotFound: + case err == avalanchedatabase.ErrNotFound: return common.Hash{}, 0, nil case err != nil: return common.Hash{}, 0, err } - height, err := database.ParseUInt64(lastCommittedHeightBytes) + height, err := avalanchedatabase.ParseUInt64(lastCommittedHeightBytes) if err != nil { return common.Hash{}, 0, fmt.Errorf("expected value at lastCommittedKey to be a valid uint64: %w", err) } @@ -251,7 +252,7 @@ func (a *atomicTrie) LastCommitted() (common.Hash, uint64) { // updateLastCommitted adds [height] -> [root] to the index and marks it as the last committed // root/height pair. func (a *atomicTrie) updateLastCommitted(root common.Hash, height uint64) error { - heightBytes := database.PackUInt64(height) + heightBytes := avalanchedatabase.PackUInt64(height) // now save the trie hash against the height it was committed at if err := a.metadataDB.Put(heightBytes, root[:]); err != nil { @@ -297,7 +298,7 @@ func (a *atomicTrie) Root(height uint64) (common.Hash, error) { // getRoot is a helper function to return the committed atomic trie root hash at [height] // from [metadataDB]. -func getRoot(metadataDB database.Database, height uint64) (common.Hash, error) { +func getRoot(metadataDB avalanchedatabase.Database, height uint64) (common.Hash, error) { if height == 0 { // if root is queried at height == 0, return the empty root hash // this may occur if peers ask for the most recent state summary @@ -305,10 +306,10 @@ func getRoot(metadataDB database.Database, height uint64) (common.Hash, error) { return types.EmptyRootHash, nil } - heightBytes := database.PackUInt64(height) + heightBytes := avalanchedatabase.PackUInt64(height) hash, err := metadataDB.Get(heightBytes) switch { - case err == database.ErrNotFound: + case err == avalanchedatabase.ErrNotFound: return common.Hash{}, nil case err != nil: return common.Hash{}, err diff --git a/plugin/evm/block.go b/plugin/evm/block.go index 9a2de32601..f94f3ebd81 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -143,7 +143,7 @@ func (b *Block) Accept(context.Context) error { // Although returning an error from Accept is considered fatal, it is good // practice to cleanup the batch we were modifying in the case of an error. - defer vm.db.Abort() + defer vm.versiondb.Abort() log.Debug(fmt.Sprintf("Accepting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) @@ -176,7 +176,7 @@ func (b *Block) Accept(context.Context) error { } // Get pending operations on the vm's versionDB so we can apply them atomically // with the shared memory changes. - vdbBatch, err := b.vm.db.CommitBatch() + vdbBatch, err := b.vm.versiondb.CommitBatch() if err != nil { return fmt.Errorf("could not create commit batch processing block[%s]: %w", b.ID(), err) } diff --git a/plugin/evm/database.go b/plugin/evm/database/wrapped_database.go similarity index 55% rename from plugin/evm/database.go rename to plugin/evm/database/wrapped_database.go index 479c995ba3..f8a36913bb 100644 --- a/plugin/evm/database.go +++ b/plugin/evm/database/wrapped_database.go @@ -1,7 +1,7 @@ // (c) 2019-2020, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package evm +package database import ( "errors" @@ -11,25 +11,29 @@ import ( ) var ( - _ ethdb.KeyValueStore = &Database{} + _ ethdb.KeyValueStore = ðDbWrapper{} ErrSnapshotNotSupported = errors.New("snapshot is not supported") ) -// Database implements ethdb.Database -type Database struct{ database.Database } +// ethDbWrapper implements ethdb.Database +type ethDbWrapper struct{ database.Database } + +func WrapDatabase(db database.Database) ethdb.KeyValueStore { return ethDbWrapper{db} } // Stat implements ethdb.Database -func (db Database) Stat(string) (string, error) { return "", database.ErrNotFound } +func (db ethDbWrapper) Stat(string) (string, error) { return "", database.ErrNotFound } // NewBatch implements ethdb.Database -func (db Database) NewBatch() ethdb.Batch { return Batch{db.Database.NewBatch()} } +func (db ethDbWrapper) NewBatch() ethdb.Batch { return wrappedBatch{db.Database.NewBatch()} } // NewBatchWithSize implements ethdb.Database // TODO: propagate size through avalanchego Database interface -func (db Database) NewBatchWithSize(size int) ethdb.Batch { return Batch{db.Database.NewBatch()} } +func (db ethDbWrapper) NewBatchWithSize(size int) ethdb.Batch { + return wrappedBatch{db.Database.NewBatch()} +} -func (db Database) NewSnapshot() (ethdb.Snapshot, error) { +func (db ethDbWrapper) NewSnapshot() (ethdb.Snapshot, error) { return nil, ErrSnapshotNotSupported } @@ -37,7 +41,7 @@ func (db Database) NewSnapshot() (ethdb.Snapshot, error) { // // Note: This method assumes that the prefix is NOT part of the start, so there's // no need for the caller to prepend the prefix to the start. -func (db Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { +func (db ethDbWrapper) NewIterator(prefix []byte, start []byte) ethdb.Iterator { // avalanchego's database implementation assumes that the prefix is part of the // start, so it is added here (if it is provided). if len(prefix) > 0 { @@ -50,15 +54,15 @@ func (db Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { } // NewIteratorWithStart implements ethdb.Database -func (db Database) NewIteratorWithStart(start []byte) ethdb.Iterator { +func (db ethDbWrapper) NewIteratorWithStart(start []byte) ethdb.Iterator { return db.Database.NewIteratorWithStart(start) } -// Batch implements ethdb.Batch -type Batch struct{ database.Batch } +// wrappedBatch implements ethdb.wrappedBatch +type wrappedBatch struct{ database.Batch } // ValueSize implements ethdb.Batch -func (batch Batch) ValueSize() int { return batch.Batch.Size() } +func (batch wrappedBatch) ValueSize() int { return batch.Batch.Size() } // Replay implements ethdb.Batch -func (batch Batch) Replay(w ethdb.KeyValueWriter) error { return batch.Batch.Replay(w) } +func (batch wrappedBatch) Replay(w ethdb.KeyValueWriter) error { return batch.Batch.Replay(w) } diff --git a/plugin/evm/export_tx_test.go b/plugin/evm/export_tx_test.go index 36b74ab45a..8e6c5d689b 100644 --- a/plugin/evm/export_tx_test.go +++ b/plugin/evm/export_tx_test.go @@ -1011,7 +1011,7 @@ func TestExportTxAccept(t *testing.T) { t.Fatal(err) } - commitBatch, err := vm.db.CommitBatch() + commitBatch, err := vm.versiondb.CommitBatch() if err != nil { t.Fatalf("Failed to create commit batch for VM due to %s", err) } @@ -1800,7 +1800,7 @@ func TestNewExportTx(t *testing.T) { t.Fatalf("burned wrong amount of AVAX - expected %d burned %d", test.expectedBurnedAVAX, burnedAVAX) } - commitBatch, err := vm.db.CommitBatch() + commitBatch, err := vm.versiondb.CommitBatch() if err != nil { t.Fatalf("Failed to create commit batch for VM due to %s", err) } @@ -2000,7 +2000,7 @@ func TestNewExportTxMulticoin(t *testing.T) { t.Fatal("newExportTx created an invalid transaction", err) } - commitBatch, err := vm.db.CommitBatch() + commitBatch, err := vm.versiondb.CommitBatch() if err != nil { t.Fatalf("Failed to create commit batch for VM due to %s", err) } diff --git a/plugin/evm/syncervm_test.go b/plugin/evm/syncervm_test.go index bd7f993cb5..7c8e76fa0a 100644 --- a/plugin/evm/syncervm_test.go +++ b/plugin/evm/syncervm_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/require" avalancheatomic "github.com/ava-labs/avalanchego/chains/atomic" - "github.com/ava-labs/avalanchego/database" + avalanchedatabase "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" @@ -36,6 +36,7 @@ import ( "github.com/ava-labs/coreth/metrics" "github.com/ava-labs/coreth/params" "github.com/ava-labs/coreth/plugin/evm/atomic" + "github.com/ava-labs/coreth/plugin/evm/database" "github.com/ava-labs/coreth/predicate" statesyncclient "github.com/ava-labs/coreth/sync/client" "github.com/ava-labs/coreth/sync/statesync" @@ -334,7 +335,7 @@ func createSyncServerAndClientVMs(t *testing.T, test syncTest, numBlocks int) *s serverAtomicTrie := serverVM.atomicTrie.(*atomicTrie) serverAtomicTrie.commitInterval = test.syncableInterval require.NoError(serverAtomicTrie.commit(test.syncableInterval, serverAtomicTrie.LastAcceptedRoot())) - require.NoError(serverVM.db.Commit()) + require.NoError(serverVM.versiondb.Commit()) serverSharedMemories := newSharedMemories(serverAtomicMemory, serverVM.ctx.ChainID, serverVM.ctx.XChainID) serverSharedMemories.assertOpsApplied(t, mustAtomicOps(importTx)) @@ -430,7 +431,7 @@ type syncVMSetup struct { fundedAccounts map[*keystore.Key]*types.StateAccount syncerVM *VM - syncerDB database.Database + syncerDB avalanchedatabase.Database syncerEngineChan <-chan commonEng.Message syncerAtomicMemory *avalancheatomic.Memory shutdownOnceSyncerVM *shutdownOnceVM @@ -491,7 +492,7 @@ func testSyncerVM(t *testing.T, vmSetup *syncVMSetup, test syncTest) { if test.expectedErr != nil { require.ErrorIs(err, test.expectedErr) // Note we re-open the database here to avoid a closed error when the test is for a shutdown VM. - chaindb := Database{prefixdb.NewNested(ethDBPrefix, syncerVM.db)} + chaindb := database.WrapDatabase(prefixdb.NewNested(ethDBPrefix, syncerVM.db)) assertSyncPerformedHeights(t, chaindb, map[uint64]struct{}{}) return } diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 6900c26ea0..89c8ea4629 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -76,7 +76,6 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/linearcodec" "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/database/versiondb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" @@ -225,8 +224,11 @@ type VM struct { blockChain *core.BlockChain miner *miner.Miner - // [db] is the VM's current database managed by ChainState - db *versiondb.Database + // [versiondb] is the VM's current versioned database + versiondb *versiondb.Database + + // [db] is the VM's current database + db database.Database // metadataDB is used to store one off keys. metadataDB database.Database @@ -274,7 +276,7 @@ type VM struct { client peer.NetworkClient networkCodec codec.Manager - validators *p2p.Validators + p2pValidators *p2p.Validators // Metrics sdkMetrics *prometheus.Registry @@ -396,14 +398,10 @@ func (vm *VM) Initialize( if err := vm.initializeDBs(db); err != nil { return fmt.Errorf("failed to initialize databases: %w", err) } - if vm.config.InspectDatabase { - start := time.Now() - log.Info("Starting database inspection") - if err := rawdb.InspectDatabase(vm.chaindb, nil, nil); err != nil { + if err := vm.inspectDatabases(); err != nil { return err } - log.Info("Completed database inspection", "elapsed", time.Since(start)) } g := new(core.Genesis) @@ -542,7 +540,7 @@ func (vm *VM) Initialize( if err != nil { return fmt.Errorf("failed to initialize p2p network: %w", err) } - vm.validators = p2p.NewValidators(p2pNetwork.Peers, vm.ctx.Log, vm.ctx.SubnetID, vm.ctx.ValidatorState, maxValidatorSetStaleness) + vm.p2pValidators = p2p.NewValidators(p2pNetwork.Peers, vm.ctx.Log, vm.ctx.SubnetID, vm.ctx.ValidatorState, maxValidatorSetStaleness) vm.networkCodec = message.Codec vm.Network = peer.NewNetwork(p2pNetwork, appSender, vm.networkCodec, chainCtx.NodeID, vm.config.MaxOutboundActiveRequests) vm.client = peer.NewNetworkClient(vm.Network) @@ -592,12 +590,12 @@ func (vm *VM) Initialize( } // initialize atomic repository - vm.atomicTxRepository, err = NewAtomicTxRepository(vm.db, atomic.Codec, lastAcceptedHeight) + vm.atomicTxRepository, err = NewAtomicTxRepository(vm.versiondb, atomic.Codec, lastAcceptedHeight) if err != nil { return fmt.Errorf("failed to create atomic repository: %w", err) } vm.atomicBackend, err = NewAtomicBackend( - vm.db, vm.ctx.SharedMemory, bonusBlockHeights, + vm.versiondb, vm.ctx.SharedMemory, bonusBlockHeights, vm.atomicTxRepository, lastAcceptedHeight, lastAcceptedHash, vm.config.CommitInterval, ) @@ -723,7 +721,7 @@ func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error { chaindb: vm.chaindb, metadataDB: vm.metadataDB, acceptedBlockDB: vm.acceptedBlockDB, - db: vm.db, + db: vm.versiondb, atomicBackend: vm.atomicBackend, toEngine: vm.toEngine, }) @@ -1047,7 +1045,7 @@ func (vm *VM) initBlockBuilding() error { vm.cancel = cancel ethTxGossipMarshaller := GossipEthTxMarshaller{} - ethTxGossipClient := vm.Network.NewClient(p2p.TxGossipHandlerID, p2p.WithValidatorSampling(vm.validators)) + ethTxGossipClient := vm.Network.NewClient(p2p.TxGossipHandlerID, p2p.WithValidatorSampling(vm.p2pValidators)) ethTxGossipMetrics, err := gossip.NewMetrics(vm.sdkMetrics, ethTxGossipNamespace) if err != nil { return fmt.Errorf("failed to initialize eth tx gossip metrics: %w", err) @@ -1063,7 +1061,7 @@ func (vm *VM) initBlockBuilding() error { }() atomicTxGossipMarshaller := atomic.GossipAtomicTxMarshaller{} - atomicTxGossipClient := vm.Network.NewClient(p2p.AtomicTxGossipHandlerID, p2p.WithValidatorSampling(vm.validators)) + atomicTxGossipClient := vm.Network.NewClient(p2p.AtomicTxGossipHandlerID, p2p.WithValidatorSampling(vm.p2pValidators)) atomicTxGossipMetrics, err := gossip.NewMetrics(vm.sdkMetrics, atomicTxGossipNamespace) if err != nil { return fmt.Errorf("failed to initialize atomic tx gossip metrics: %w", err) @@ -1084,7 +1082,7 @@ func (vm *VM) initBlockBuilding() error { ethTxPushGossiper, err = gossip.NewPushGossiper[*GossipEthTx]( ethTxGossipMarshaller, ethTxPool, - vm.validators, + vm.p2pValidators, ethTxGossipClient, ethTxGossipMetrics, pushGossipParams, @@ -1103,7 +1101,7 @@ func (vm *VM) initBlockBuilding() error { vm.atomicTxPushGossiper, err = gossip.NewPushGossiper[*atomic.GossipAtomicTx]( atomicTxGossipMarshaller, vm.mempool, - vm.validators, + vm.p2pValidators, atomicTxGossipClient, atomicTxGossipMetrics, pushGossipParams, @@ -1130,7 +1128,7 @@ func (vm *VM) initBlockBuilding() error { txGossipTargetMessageSize, txGossipThrottlingPeriod, txGossipThrottlingLimit, - vm.validators, + vm.p2pValidators, ) } @@ -1147,7 +1145,7 @@ func (vm *VM) initBlockBuilding() error { txGossipTargetMessageSize, txGossipThrottlingPeriod, txGossipThrottlingLimit, - vm.validators, + vm.p2pValidators, ) } @@ -1168,7 +1166,7 @@ func (vm *VM) initBlockBuilding() error { vm.ethTxPullGossiper = gossip.ValidatorGossiper{ Gossiper: ethTxPullGossiper, NodeID: vm.ctx.NodeID, - Validators: vm.validators, + Validators: vm.p2pValidators, } } @@ -1195,7 +1193,7 @@ func (vm *VM) initBlockBuilding() error { vm.atomicTxPullGossiper = &gossip.ValidatorGossiper{ Gossiper: atomicTxPullGossiper, NodeID: vm.ctx.NodeID, - Validators: vm.validators, + Validators: vm.p2pValidators, } } @@ -1457,6 +1455,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { enabledAPIs = append(enabledAPIs, "coreth-admin") } + // RPC APIs if vm.config.SnowmanAPIEnabled { if err := handler.RegisterName("snowman", &SnowmanAPI{vm}); err != nil { return nil, err @@ -1484,22 +1483,6 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { return apis, nil } -// initializeDBs initializes the databases used by the VM. -// coreth always uses the avalanchego provided database. -func (vm *VM) initializeDBs(db database.Database) error { - // Use NewNested rather than New so that the structure of the database - // remains the same regardless of the provided baseDB type. - vm.chaindb = rawdb.NewDatabase(Database{prefixdb.NewNested(ethDBPrefix, db)}) - vm.db = versiondb.New(db) - vm.acceptedBlockDB = prefixdb.New(acceptedPrefix, vm.db) - vm.metadataDB = prefixdb.New(metadataPrefix, vm.db) - // Note warpDB is not part of versiondb because it is not necessary - // that warp signatures are committed to the database atomically with - // the last accepted block. - vm.warpDB = prefixdb.New(warpPrefix, db) - return nil -} - // CreateStaticHandlers makes new http handlers that can handle API calls func (vm *VM) CreateStaticHandlers(context.Context) (map[string]http.Handler, error) { handler := rpc.NewServer(0) diff --git a/plugin/evm/vm_database.go b/plugin/evm/vm_database.go new file mode 100644 index 0000000000..f2a5b4c344 --- /dev/null +++ b/plugin/evm/vm_database.go @@ -0,0 +1,82 @@ +// (c) 2019-2021, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package evm + +import ( + "time" + + avalanchedatabase "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/prefixdb" + "github.com/ava-labs/avalanchego/database/versiondb" + "github.com/ava-labs/coreth/core/rawdb" + "github.com/ava-labs/coreth/plugin/evm/database" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +// initializeDBs initializes the databases used by the VM. +// coreth always uses the avalanchego provided database. +func (vm *VM) initializeDBs(db avalanchedatabase.Database) error { + // Use NewNested rather than New so that the structure of the database + // remains the same regardless of the provided baseDB type. + vm.chaindb = rawdb.NewDatabase(database.WrapDatabase(prefixdb.NewNested(ethDBPrefix, db))) + vm.versiondb = versiondb.New(db) + vm.acceptedBlockDB = prefixdb.New(acceptedPrefix, vm.versiondb) + vm.metadataDB = prefixdb.New(metadataPrefix, vm.versiondb) + vm.db = db + // Note warpDB is not part of versiondb because it is not necessary + // that warp signatures are committed to the database atomically with + // the last accepted block. + vm.warpDB = prefixdb.New(warpPrefix, db) + return nil +} + +func (vm *VM) inspectDatabases() error { + start := time.Now() + log.Info("Starting database inspection") + if err := rawdb.InspectDatabase(vm.chaindb, nil, nil); err != nil { + return err + } + if err := inspectDB(vm.acceptedBlockDB, "acceptedBlockDB"); err != nil { + return err + } + if err := inspectDB(vm.metadataDB, "metadataDB"); err != nil { + return err + } + if err := inspectDB(vm.warpDB, "warpDB"); err != nil { + return err + } + log.Info("Completed database inspection", "elapsed", time.Since(start)) + return nil +} + +func inspectDB(db avalanchedatabase.Database, label string) error { + it := db.NewIterator() + defer it.Release() + + var ( + count int64 + start = time.Now() + logged = time.Now() + + // Totals + total common.StorageSize + ) + // Inspect key-value database first. + for it.Next() { + var ( + key = it.Key() + size = common.StorageSize(len(key) + len(it.Value())) + ) + total += size + count++ + if count%1000 == 0 && time.Since(logged) > 8*time.Second { + log.Info("Inspecting database", "label", label, "count", count, "elapsed", common.PrettyDuration(time.Since(start))) + logged = time.Now() + } + } + // Display the database statistic. + log.Info("Database statistics", "label", label, "total", total.String(), "count", count) + return nil +} diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 56b56cf93c..2a79f3fb6f 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -3170,7 +3170,7 @@ func TestConfigureLogLevel(t *testing.T) { } } - // If the VM was not initialized, do not attept to shut it down + // If the VM was not initialized, do not attempt to shut it down if err == nil { shutdownChan := make(chan error, 1) shutdownFunc := func() { diff --git a/precompile/contract/interfaces.go b/precompile/contract/interfaces.go index b3ffb02fe2..44c3cfa633 100644 --- a/precompile/contract/interfaces.go +++ b/precompile/contract/interfaces.go @@ -62,7 +62,7 @@ type ConfigurationBlockContext interface { type BlockContext interface { ConfigurationBlockContext - // GetResults returns an arbitrary byte array result of verifying the predicates + // GetPredicateResults returns an arbitrary byte array result of verifying the predicates // of the given transaction, precompile address pair. GetPredicateResults(txHash common.Hash, precompileAddress common.Address) []byte } diff --git a/precompile/contracts/warp/README.md b/precompile/contracts/warp/README.md index 10e1daaa38..73ca165224 100644 --- a/precompile/contracts/warp/README.md +++ b/precompile/contracts/warp/README.md @@ -57,7 +57,7 @@ To use this function, the transaction must include the signed Avalanche Warp Mes This leads to the following advantages: 1. The EVM execution does not need to verify the Warp Message at runtime (no signature verification or external calls to the P-Chain) -2. The EVM can deterministically re-execute and re-verify blocks assuming the predicate was verified by the network (eg., in bootstrapping) +2. The EVM can deterministically re-execute and re-verify blocks assuming the predicate was verified by the network (e.g., in bootstrapping) This pre-verification is performed using the ProposerVM Block header during [block verification](../../../plugin/evm/block.go#L220) and [block building](../../../miner/worker.go#L200). diff --git a/rpc/handler.go b/rpc/handler.go index a15f6b20be..ef35a61ca8 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -479,7 +479,7 @@ func (h *handler) startCallProc(fn func(*callProc)) { } } -// handleResponse processes method call responses. +// handleResponses processes method call responses. func (h *handler) handleResponses(batch []*jsonrpcMessage, handleCall func(*jsonrpcMessage)) { var resolvedops []*requestOp handleResp := func(msg *jsonrpcMessage) { diff --git a/rpc/types.go b/rpc/types.go index b2f5b98528..c96e7bc74f 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -62,7 +62,7 @@ type ServerCodec interface { type jsonWriter interface { // writeJSON writes a message to the connection. writeJSON(ctx context.Context, msg interface{}, isError bool) error - // writeJSON writes a message to the connection with the option of skipping the deadline. + // writeJSONSkipDeadline writes a message to the connection with the option of skipping the deadline. writeJSONSkipDeadline(ctx context.Context, msg interface{}, isError bool, skip bool) error // Closed returns a channel which is closed when the connection is closed. closed() <-chan interface{} diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh deleted file mode 100755 index 9126a47a8d..0000000000 --- a/scripts/build_docker_image.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Avalanche root directory -CORETH_PATH=$( - cd "$(dirname "${BASH_SOURCE[0]}")" - cd .. && pwd -) - -# Load the constants -source "$CORETH_PATH"/scripts/constants.sh - -# Load the versions -source "$CORETH_PATH"/scripts/versions.sh - -# WARNING: this will use the most recent commit even if there are un-committed changes present -BUILD_IMAGE_ID=${BUILD_IMAGE_ID:-"${CURRENT_BRANCH}"} -echo "Building Docker Image: $DOCKERHUB_REPO:$BUILD_IMAGE_ID based of AvalancheGo@$AVALANCHE_VERSION" -docker build -t "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" "$CORETH_PATH" -f "$CORETH_PATH/Dockerfile" \ - --build-arg AVALANCHE_VERSION="$AVALANCHE_VERSION" \ - --build-arg CORETH_COMMIT="$CORETH_COMMIT" \ - --build-arg CURRENT_BRANCH="$CURRENT_BRANCH" diff --git a/scripts/known_flakes.txt b/scripts/known_flakes.txt index b28b4e710c..0f324a6714 100644 --- a/scripts/known_flakes.txt +++ b/scripts/known_flakes.txt @@ -5,6 +5,7 @@ TestMempoolAtmTxsAppGossipHandlingDiscardedTx TestMempoolEthTxsAppGossipHandling TestResumeSyncAccountsTrieInterrupted TestResyncNewRootAfterDeletes +TestTimedUnlock TestTransactionSkipIndexing TestVMShutdownWhileSyncing TestWaitDeployedCornerCases diff --git a/sync/statesync/trie_sync_stats.go b/sync/statesync/trie_sync_stats.go index bb4770e28c..c55fc8da35 100644 --- a/sync/statesync/trie_sync_stats.go +++ b/sync/statesync/trie_sync_stats.go @@ -79,7 +79,7 @@ func (t *trieSyncStats) incLeafs(segment *trieSegment, count uint64, remaining u } } -// estimateSegmentsInProgressTime retrns the ETA for all trie segments +// estimateSegmentsInProgressTime returns the ETA for all trie segments // in progress to finish (uses the one with most remaining leafs to estimate). func (t *trieSyncStats) estimateSegmentsInProgressTime() time.Duration { if len(t.remainingLeafs) == 0 { diff --git a/warp/aggregator/aggregator_test.go b/warp/aggregator/aggregator_test.go index 98e90607db..055d3edfa8 100644 --- a/warp/aggregator/aggregator_test.go +++ b/warp/aggregator/aggregator_test.go @@ -230,7 +230,7 @@ func TestAggregateSignatures(t *testing.T) { expectedErr: nil, }, { - name: "early termination of signature fetching on parent context cancelation", + name: "early termination of signature fetching on parent context cancellation", contextWithCancelFunc: func() (context.Context, context.CancelFunc) { ctx, cancel := context.WithCancel(context.Background()) cancel() diff --git a/warp/backend.go b/warp/backend.go index 6e1f6a9553..d35c96b8fb 100644 --- a/warp/backend.go +++ b/warp/backend.go @@ -180,7 +180,7 @@ func (b *backend) GetMessage(messageID ids.ID) (*avalancheWarp.UnsignedMessage, unsignedMessageBytes, err := b.db.Get(messageID[:]) if err != nil { - return nil, fmt.Errorf("failed to get warp message %s from db: %w", messageID.String(), err) + return nil, err } unsignedMessage, err := avalancheWarp.ParseUnsignedMessage(unsignedMessageBytes) diff --git a/warp/backend_test.go b/warp/backend_test.go index 4935875ece..cd7aa1ea76 100644 --- a/warp/backend_test.go +++ b/warp/backend_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/ava-labs/avalanchego/cache" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils" @@ -157,6 +158,12 @@ func TestOffChainMessages(t *testing.T) { require.Equal(expectedSignatureBytes, signature[:]) }, }, + "unknown message": { + check: func(require *require.Assertions, b Backend) { + _, err := b.GetMessage(testUnsignedMessage.ID()) + require.ErrorIs(err, database.ErrNotFound) + }, + }, "invalid message": { offchainMessages: [][]byte{{1, 2, 3}}, err: errParsingOffChainMessage, diff --git a/warp/verifier_backend.go b/warp/verifier_backend.go index c70563c585..3c8427b8ff 100644 --- a/warp/verifier_backend.go +++ b/warp/verifier_backend.go @@ -7,6 +7,7 @@ import ( "context" "fmt" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/snow/engine/common" avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" @@ -24,6 +25,11 @@ func (b *backend) Verify(ctx context.Context, unsignedMessage *avalancheWarp.Uns // Known on-chain messages should be signed if _, err := b.GetMessage(messageID); err == nil { return nil + } else if err != database.ErrNotFound { + return &common.AppError{ + Code: ParseErrCode, + Message: fmt.Sprintf("failed to get message %s: %s", messageID, err.Error()), + } } parsed, err := payload.Parse(unsignedMessage.Payload) @@ -53,7 +59,7 @@ func (b *backend) verifyBlockMessage(ctx context.Context, blockHashPayload *payl blockID := blockHashPayload.Hash _, err := b.blockClient.GetAcceptedBlock(ctx, blockID) if err != nil { - b.stats.IncBlockSignatureValidationFail() + b.stats.IncBlockValidationFail() return &common.AppError{ Code: VerifyErrCode, Message: fmt.Sprintf("failed to get block %s: %s", blockID, err.Error()), diff --git a/warp/verifier_backend_test.go b/warp/verifier_backend_test.go index 4bf11541b0..a58726aa0f 100644 --- a/warp/verifier_backend_test.go +++ b/warp/verifier_backend_test.go @@ -56,7 +56,7 @@ func TestAddressedCallSignatures(t *testing.T) { }, verifyStats: func(t *testing.T, stats *verifierStats) { require.EqualValues(t, 0, stats.messageParseFail.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureValidationFail.Snapshot().Count()) + require.EqualValues(t, 0, stats.blockValidationFail.Snapshot().Count()) }, }, "offchain message": { @@ -65,7 +65,7 @@ func TestAddressedCallSignatures(t *testing.T) { }, verifyStats: func(t *testing.T, stats *verifierStats) { require.EqualValues(t, 0, stats.messageParseFail.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureValidationFail.Snapshot().Count()) + require.EqualValues(t, 0, stats.blockValidationFail.Snapshot().Count()) }, }, "unknown message": { @@ -78,7 +78,7 @@ func TestAddressedCallSignatures(t *testing.T) { }, verifyStats: func(t *testing.T, stats *verifierStats) { require.EqualValues(t, 1, stats.messageParseFail.Snapshot().Count()) - require.EqualValues(t, 0, stats.blockSignatureValidationFail.Snapshot().Count()) + require.EqualValues(t, 0, stats.blockValidationFail.Snapshot().Count()) }, err: &common.AppError{Code: ParseErrCode}, }, @@ -177,7 +177,7 @@ func TestBlockSignatures(t *testing.T) { return toMessageBytes(knownBlkID), signature[:] }, verifyStats: func(t *testing.T, stats *verifierStats) { - require.EqualValues(t, 0, stats.blockSignatureValidationFail.Snapshot().Count()) + require.EqualValues(t, 0, stats.blockValidationFail.Snapshot().Count()) require.EqualValues(t, 0, stats.messageParseFail.Snapshot().Count()) }, }, @@ -187,7 +187,7 @@ func TestBlockSignatures(t *testing.T) { return toMessageBytes(unknownBlockID), nil }, verifyStats: func(t *testing.T, stats *verifierStats) { - require.EqualValues(t, 1, stats.blockSignatureValidationFail.Snapshot().Count()) + require.EqualValues(t, 1, stats.blockValidationFail.Snapshot().Count()) require.EqualValues(t, 0, stats.messageParseFail.Snapshot().Count()) }, err: &common.AppError{Code: VerifyErrCode}, diff --git a/warp/verifier_stats.go b/warp/verifier_stats.go index 3ee90312d9..980d464429 100644 --- a/warp/verifier_stats.go +++ b/warp/verifier_stats.go @@ -10,18 +10,18 @@ import ( type verifierStats struct { messageParseFail metrics.Counter // BlockRequest metrics - blockSignatureValidationFail metrics.Counter + blockValidationFail metrics.Counter } func newVerifierStats() *verifierStats { return &verifierStats{ - messageParseFail: metrics.NewRegisteredCounter("message_parse_fail", nil), - blockSignatureValidationFail: metrics.NewRegisteredCounter("block_signature_validation_fail", nil), + messageParseFail: metrics.NewRegisteredCounter("warp_backend_message_parse_fail", nil), + blockValidationFail: metrics.NewRegisteredCounter("warp_backend_block_validation_fail", nil), } } -func (h *verifierStats) IncBlockSignatureValidationFail() { - h.blockSignatureValidationFail.Inc(1) +func (h *verifierStats) IncBlockValidationFail() { + h.blockValidationFail.Inc(1) } func (h *verifierStats) IncMessageParseFail() { From e19a2f7efca244fa91c36f5185ebbc68f9ec100e Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Tue, 7 Jan 2025 08:26:50 -0800 Subject: [PATCH 03/11] ci verification for go mod tidy (#736) Co-authored-by: Quentin McGaw --- .github/workflows/ci.yml | 4 ++++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48056c04f2..9b180a501d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,10 @@ jobs: run: echo "TIMEOUT=1200s" >> "$GITHUB_ENV" - run: go mod download shell: bash + - name: go mod tidy + run: | + go mod tidy + git diff --exit-code - name: Mocks are up to date shell: bash run: | diff --git a/go.mod b/go.mod index 63146cd8d2..0b095d2f54 100644 --- a/go.mod +++ b/go.mod @@ -121,7 +121,7 @@ require ( go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/mod v0.22.0 // indirect + golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/term v0.27.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect diff --git a/go.sum b/go.sum index 9391e7bb79..9c19c061be 100644 --- a/go.sum +++ b/go.sum @@ -641,8 +641,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 14e9d30374e4fc4586bbe8f4a0e5a8d01b69250f Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Tue, 7 Jan 2025 12:38:21 -0800 Subject: [PATCH 04/11] refactor: Split config package so it doesn't import core, core/vm (#734) Co-authored-by: Quentin McGaw --- plugin/evm/config.go | 21 +++++++++++ plugin/evm/config/config.go | 35 ++++++++++-------- plugin/evm/imports_test.go | 72 +++++++++++++++++++++++++++++++++++++ plugin/evm/vm.go | 4 +-- plugin/evm/vm_test.go | 4 +-- 5 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 plugin/evm/config.go create mode 100644 plugin/evm/imports_test.go diff --git a/plugin/evm/config.go b/plugin/evm/config.go new file mode 100644 index 0000000000..5ad18aa2f2 --- /dev/null +++ b/plugin/evm/config.go @@ -0,0 +1,21 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package evm + +import ( + "github.com/ava-labs/coreth/core/txpool/legacypool" + "github.com/ava-labs/coreth/plugin/evm/config" +) + +// defaultTxPoolConfig uses [legacypool.DefaultConfig] to make a [config.TxPoolConfig] +// that can be passed to [config.Config.SetDefaults]. +var defaultTxPoolConfig = config.TxPoolConfig{ + PriceLimit: legacypool.DefaultConfig.PriceLimit, + PriceBump: legacypool.DefaultConfig.PriceBump, + AccountSlots: legacypool.DefaultConfig.AccountSlots, + GlobalSlots: legacypool.DefaultConfig.GlobalSlots, + AccountQueue: legacypool.DefaultConfig.AccountQueue, + GlobalQueue: legacypool.DefaultConfig.GlobalQueue, + Lifetime: legacypool.DefaultConfig.Lifetime, +} diff --git a/plugin/evm/config/config.go b/plugin/evm/config/config.go index a92405bcb5..f5bf644657 100644 --- a/plugin/evm/config/config.go +++ b/plugin/evm/config/config.go @@ -9,8 +9,6 @@ import ( "time" "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/coreth/core/txpool/legacypool" - "github.com/ava-labs/coreth/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/spf13/cast" @@ -224,28 +222,37 @@ type Config struct { HttpBodyLimit uint64 `json:"http-body-limit"` } +// TxPoolConfig contains the transaction pool config to be passed +// to [Config.SetDefaults]. +type TxPoolConfig struct { + PriceLimit uint64 + PriceBump uint64 + AccountSlots uint64 + GlobalSlots uint64 + AccountQueue uint64 + GlobalQueue uint64 + Lifetime time.Duration +} + // EthAPIs returns an array of strings representing the Eth APIs that should be enabled func (c Config) EthAPIs() []string { return c.EnabledEthAPIs } -func (c Config) EthBackendSettings() eth.Settings { - return eth.Settings{MaxBlocksPerRequest: c.MaxBlocksPerRequest} -} - -func (c *Config) SetDefaults() { +func (c *Config) SetDefaults(txPoolConfig TxPoolConfig) { c.EnabledEthAPIs = defaultEnabledAPIs c.RPCGasCap = defaultRpcGasCap c.RPCTxFeeCap = defaultRpcTxFeeCap c.MetricsExpensiveEnabled = defaultMetricsExpensiveEnabled - c.TxPoolPriceLimit = legacypool.DefaultConfig.PriceLimit - c.TxPoolPriceBump = legacypool.DefaultConfig.PriceBump - c.TxPoolAccountSlots = legacypool.DefaultConfig.AccountSlots - c.TxPoolGlobalSlots = legacypool.DefaultConfig.GlobalSlots - c.TxPoolAccountQueue = legacypool.DefaultConfig.AccountQueue - c.TxPoolGlobalQueue = legacypool.DefaultConfig.GlobalQueue - c.TxPoolLifetime.Duration = legacypool.DefaultConfig.Lifetime + // TxPool settings + c.TxPoolPriceLimit = txPoolConfig.PriceLimit + c.TxPoolPriceBump = txPoolConfig.PriceBump + c.TxPoolAccountSlots = txPoolConfig.AccountSlots + c.TxPoolGlobalSlots = txPoolConfig.GlobalSlots + c.TxPoolAccountQueue = txPoolConfig.AccountQueue + c.TxPoolGlobalQueue = txPoolConfig.GlobalQueue + c.TxPoolLifetime.Duration = txPoolConfig.Lifetime c.APIMaxDuration.Duration = defaultApiMaxDuration c.WSCPURefillRate.Duration = defaultWsCpuRefillRate diff --git a/plugin/evm/imports_test.go b/plugin/evm/imports_test.go new file mode 100644 index 0000000000..8b7ac4c4a9 --- /dev/null +++ b/plugin/evm/imports_test.go @@ -0,0 +1,72 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package evm + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "golang.org/x/tools/go/packages" +) + +// getDependencies takes a fully qualified package name and returns a map of all +// its recursive package imports (including itself) in the same format. +func getDependencies(packageName string) (map[string]struct{}, error) { + // Configure the load mode to include dependencies + cfg := &packages.Config{Mode: packages.NeedDeps | packages.NeedImports | packages.NeedName | packages.NeedModule} + pkgs, err := packages.Load(cfg, packageName) + if err != nil { + return nil, fmt.Errorf("failed to load package: %v", err) + } + + if len(pkgs) == 0 || pkgs[0].Errors != nil { + return nil, fmt.Errorf("failed to load package %s", packageName) + } + + deps := make(map[string]struct{}) + var collectDeps func(pkg *packages.Package) + collectDeps = func(pkg *packages.Package) { + if _, ok := deps[pkg.PkgPath]; ok { + return // Avoid re-processing the same dependency + } + deps[pkg.PkgPath] = struct{}{} + for _, dep := range pkg.Imports { + collectDeps(dep) + } + } + + // Start collecting dependencies + collectDeps(pkgs[0]) + return deps, nil +} + +func TestMustNotImport(t *testing.T) { + withRepo := func(pkg string) string { + const repo = "github.com/ava-labs/coreth" + return fmt.Sprintf("%s/%s", repo, pkg) + } + mustNotImport := map[string][]string{ + // The following sub-packages of plugin/evm must not import core, core/vm + // so clients (e.g., wallets, e2e tests) can import them without pulling in + // the entire VM logic. + // Importing these packages configures libevm globally and it is not + // possible to do so for both coreth and subnet-evm, where the client may + // wish to connect to multiple chains. + "plugin/evm/atomic": {"core", "core/vm"}, + "plugin/evm/client": {"core", "core/vm"}, + "plugin/evm/config": {"core", "core/vm"}, + } + + for packageName, forbiddenImports := range mustNotImport { + imports, err := getDependencies(withRepo(packageName)) + require.NoError(t, err) + + for _, forbiddenImport := range forbiddenImports { + fullForbiddenImport := withRepo(forbiddenImport) + _, found := imports[fullForbiddenImport] + require.False(t, found, "package %s must not import %s, check output of go list -f '{{ .Deps }}' \"%s\" ", packageName, fullForbiddenImport, withRepo(packageName)) + } + } +} diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 89c8ea4629..eebbd4a7ce 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -339,7 +339,7 @@ func (vm *VM) Initialize( fxs []*commonEng.Fx, appSender commonEng.AppSender, ) error { - vm.config.SetDefaults() + vm.config.SetDefaults(defaultTxPoolConfig) if len(configBytes) > 0 { if err := json.Unmarshal(configBytes, &vm.config); err != nil { return fmt.Errorf("failed to unmarshal config %s: %w", string(configBytes), err) @@ -660,7 +660,7 @@ func (vm *VM) initializeChain(lastAcceptedHash common.Hash) error { &vm.ethConfig, &EthPushGossiper{vm: vm}, vm.chaindb, - vm.config.EthBackendSettings(), + eth.Settings{MaxBlocksPerRequest: vm.config.MaxBlocksPerRequest}, lastAcceptedHash, dummy.NewFakerWithClock(callbacks, &vm.clock), &vm.clock, diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 2a79f3fb6f..507c8d3a94 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -402,7 +402,7 @@ func TestVMConfigDefaults(t *testing.T) { _, vm, _, _, _ := GenesisVM(t, false, "", configJSON, "") var vmConfig config.Config - vmConfig.SetDefaults() + vmConfig.SetDefaults(defaultTxPoolConfig) vmConfig.RPCTxFeeCap = txFeeCap vmConfig.EnabledEthAPIs = enabledEthAPIs require.Equal(t, vmConfig, vm.config, "VM Config should match default with overrides") @@ -414,7 +414,7 @@ func TestVMNilConfig(t *testing.T) { // VM Config should match defaults if no config is passed in var vmConfig config.Config - vmConfig.SetDefaults() + vmConfig.SetDefaults(defaultTxPoolConfig) require.Equal(t, vmConfig, vm.config, "VM Config should match default config") require.NoError(t, vm.Shutdown(context.Background())) } From 24e1459f44700530c0ea9ea5f30b5839843be433 Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 9 Jan 2025 10:13:25 -0800 Subject: [PATCH 05/11] remove currentStateLock (#741) --- core/txpool/legacypool/legacypool.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index f34701da78..51825da9e9 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -227,9 +227,6 @@ type LegacyPool struct { signer types.Signer mu sync.RWMutex - // [currentStateLock] is required to allow concurrent access to address nonces - // and balances during reorgs and gossip handling. - currentStateLock sync.Mutex // closed when the transaction pool is stopped. Any goroutine can listen // to this to be notified if it should shut down. generalShutdownChan chan struct{} @@ -685,9 +682,6 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro // validateTx checks whether a transaction is valid according to the consensus // rules and adheres to some heuristic limits of the local node (price and size). func (pool *LegacyPool) validateTx(tx *types.Transaction, local bool) error { - pool.currentStateLock.Lock() - defer pool.currentStateLock.Unlock() - opts := &txpool.ValidationOptionsWithState{ State: pool.currentState, Rules: pool.chainconfig.Rules( @@ -1500,9 +1494,7 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { return } pool.currentHead.Store(newHead) - pool.currentStateLock.Lock() pool.currentState = statedb - pool.currentStateLock.Unlock() pool.pendingNonces = newNoncer(statedb) // Inject any transactions discarded due to reorgs @@ -1515,9 +1507,6 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { // future queue to the set of pending transactions. During this process, all // invalidated transactions (low nonce, low balance) are deleted. func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.Transaction { - pool.currentStateLock.Lock() - defer pool.currentStateLock.Unlock() - // Track the promoted transactions to broadcast them at once var promoted []*types.Transaction @@ -1724,9 +1713,6 @@ func (pool *LegacyPool) truncateQueue() { // is always explicitly triggered by SetBaseFee and it would be unnecessary and wasteful // to trigger a re-heap is this function func (pool *LegacyPool) demoteUnexecutables() { - pool.currentStateLock.Lock() - defer pool.currentStateLock.Unlock() - // Iterate over all accounts and demote any non-executable transactions gasLimit := pool.currentHead.Load().GasLimit for addr, list := range pool.pending { From b6b4dfbc4bfc7f17e4cfe5f3c0fb44944176c884 Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 9 Jan 2025 10:28:46 -0800 Subject: [PATCH 06/11] atomic syncer: simplify interface (#735) Co-authored-by: Ceyhun Onur --- plugin/evm/atomic_backend.go | 11 ----------- plugin/evm/atomic_syncer.go | 5 ++--- plugin/evm/atomic_syncer_test.go | 4 ++-- plugin/evm/syncervm_client.go | 9 ++++++++- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/plugin/evm/atomic_backend.go b/plugin/evm/atomic_backend.go index 2420021d6f..45afa707f2 100644 --- a/plugin/evm/atomic_backend.go +++ b/plugin/evm/atomic_backend.go @@ -17,7 +17,6 @@ import ( "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/coreth/plugin/evm/atomic" - syncclient "github.com/ava-labs/coreth/sync/client" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -57,10 +56,6 @@ type AtomicBackend interface { // will not have been executed on shared memory. MarkApplyToSharedMemoryCursor(previousLastAcceptedHeight uint64) error - // Syncer creates and returns a new Syncer object that can be used to sync the - // state of the atomic trie from peers - Syncer(client syncclient.LeafClient, targetRoot common.Hash, targetHeight uint64, requestSize uint16) (Syncer, error) - // SetLastAccepted is used after state-sync to reset the last accepted block. SetLastAccepted(lastAcceptedHash common.Hash) @@ -356,12 +351,6 @@ func (a *atomicBackend) MarkApplyToSharedMemoryCursor(previousLastAcceptedHeight return database.PutUInt64(a.metadataDB, appliedSharedMemoryCursorKey, previousLastAcceptedHeight+1) } -// Syncer creates and returns a new Syncer object that can be used to sync the -// state of the atomic trie from peers -func (a *atomicBackend) Syncer(client syncclient.LeafClient, targetRoot common.Hash, targetHeight uint64, requestSize uint16) (Syncer, error) { - return newAtomicSyncer(client, a, targetRoot, targetHeight, requestSize) -} - func (a *atomicBackend) GetVerifiedAtomicState(blockHash common.Hash) (AtomicState, error) { if state, ok := a.verifiedRoots[blockHash]; ok { return state, nil diff --git a/plugin/evm/atomic_syncer.go b/plugin/evm/atomic_syncer.go index d68d61d597..8c435690c0 100644 --- a/plugin/evm/atomic_syncer.go +++ b/plugin/evm/atomic_syncer.go @@ -50,8 +50,7 @@ func addZeroes(height uint64) []byte { return packer.Bytes } -func newAtomicSyncer(client syncclient.LeafClient, atomicBackend *atomicBackend, targetRoot common.Hash, targetHeight uint64, requestSize uint16) (*atomicSyncer, error) { - atomicTrie := atomicBackend.AtomicTrie() +func newAtomicSyncer(client syncclient.LeafClient, vdb *versiondb.Database, atomicTrie AtomicTrie, targetRoot common.Hash, targetHeight uint64, requestSize uint16) (*atomicSyncer, error) { lastCommittedRoot, lastCommit := atomicTrie.LastCommitted() trie, err := atomicTrie.OpenTrie(lastCommittedRoot) if err != nil { @@ -59,7 +58,7 @@ func newAtomicSyncer(client syncclient.LeafClient, atomicBackend *atomicBackend, } atomicSyncer := &atomicSyncer{ - db: atomicBackend.db, + db: vdb, atomicTrie: atomicTrie, trie: trie, targetRoot: targetRoot, diff --git a/plugin/evm/atomic_syncer_test.go b/plugin/evm/atomic_syncer_test.go index 86589cc4d8..3feffe444c 100644 --- a/plugin/evm/atomic_syncer_test.go +++ b/plugin/evm/atomic_syncer_test.go @@ -65,7 +65,7 @@ func testAtomicSyncer(t *testing.T, serverTrieDB *triedb.Database, targetHeight // next trie. for i, checkpoint := range checkpoints { // Create syncer targeting the current [syncTrie]. - syncer, err := atomicBackend.Syncer(mockClient, targetRoot, targetHeight, config.DefaultStateSyncRequestSize) + syncer, err := newAtomicSyncer(mockClient, clientDB, atomicBackend.AtomicTrie(), targetRoot, targetHeight, config.DefaultStateSyncRequestSize) if err != nil { t.Fatal(err) } @@ -92,7 +92,7 @@ func testAtomicSyncer(t *testing.T, serverTrieDB *triedb.Database, targetHeight } // Create syncer targeting the current [targetRoot]. - syncer, err := atomicBackend.Syncer(mockClient, targetRoot, targetHeight, config.DefaultStateSyncRequestSize) + syncer, err := newAtomicSyncer(mockClient, clientDB, atomicBackend.AtomicTrie(), targetRoot, targetHeight, config.DefaultStateSyncRequestSize) if err != nil { t.Fatal(err) } diff --git a/plugin/evm/syncervm_client.go b/plugin/evm/syncervm_client.go index 0b704d6233..c25f68c46b 100644 --- a/plugin/evm/syncervm_client.go +++ b/plugin/evm/syncervm_client.go @@ -276,7 +276,14 @@ func (client *stateSyncerClient) syncBlocks(ctx context.Context, fromHash common func (client *stateSyncerClient) syncAtomicTrie(ctx context.Context) error { log.Info("atomic tx: sync starting", "root", client.syncSummary.AtomicRoot) - atomicSyncer, err := client.atomicBackend.Syncer(client.client, client.syncSummary.AtomicRoot, client.syncSummary.BlockNumber, client.stateSyncRequestSize) + atomicSyncer, err := newAtomicSyncer( + client.client, + client.db, + client.atomicBackend.AtomicTrie(), + client.syncSummary.AtomicRoot, + client.syncSummary.BlockNumber, + client.stateSyncRequestSize, + ) if err != nil { return err } From 50138514f84f4b2f2968c84bd498852f6b65a0b0 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Wed, 15 Jan 2025 16:28:22 +0100 Subject: [PATCH 07/11] feat(internal/ethapi)!: reject `eth_getProof` queries for historical blocks (#719) - default behavior for pruning mode to reject blocks before the 32 blocks preceding the last accepted block - default behavior for archive mode to reject blocks before ~24h worth of blocks preceding the last accepted block - archive mode new option `historical-proof-query-window` to customize the blocks window, or set it to 0 to accept any block number --- RELEASES.md | 4 + core/state_manager.go | 6 +- core/state_manager_test.go | 6 +- eth/api_backend.go | 15 + eth/backend.go | 11 +- eth/ethconfig/config.go | 5 + internal/ethapi/api.go | 7 + internal/ethapi/api_extra.go | 39 ++ internal/ethapi/api_extra_test.go | 132 +++++ internal/ethapi/api_test.go | 6 + internal/ethapi/backend.go | 2 + internal/ethapi/mocks_generate_test.go | 3 + internal/ethapi/mocks_test.go | 757 +++++++++++++++++++++++++ plugin/evm/config/config.go | 8 + plugin/evm/vm.go | 1 + 15 files changed, 991 insertions(+), 11 deletions(-) create mode 100644 internal/ethapi/api_extra_test.go create mode 100644 internal/ethapi/mocks_generate_test.go create mode 100644 internal/ethapi/mocks_test.go diff --git a/RELEASES.md b/RELEASES.md index bce253816e..4dd80d2d21 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,6 +1,10 @@ # Release Notes ## [v0.14.1](https://github.com/ava-labs/coreth/releases/tag/v0.14.1) + +- 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/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/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/vm.go b/plugin/evm/vm.go index eebbd4a7ce..879cb8988e 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -495,6 +495,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 From be859c90f068f8fddb34005ef59822212bbe71de Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Thu, 16 Jan 2025 11:20:29 +0300 Subject: [PATCH 08/11] remove keystore and related APIs (#748) --- RELEASES.md | 4 + plugin/evm/api.go | 211 +-------------------- plugin/evm/client/client.go | 141 -------------- plugin/evm/client/client_interface_test.go | 17 -- plugin/evm/user.go | 137 ------------- plugin/evm/vm.go | 17 -- plugin/evm/vm_test.go | 10 - 7 files changed, 7 insertions(+), 530 deletions(-) delete mode 100644 plugin/evm/client/client_interface_test.go delete mode 100644 plugin/evm/user.go diff --git a/RELEASES.md b/RELEASES.md index 4dd80d2d21..d2072b75b8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,9 @@ # Release Notes +## Pending Release + +- Removed deprecated `ExportKey`, `ExportAVAX`, `Export`, `ImportKey`, `ImportAVAX`, `Import` APIs + ## [v0.14.1](https://github.com/ava-labs/coreth/releases/tag/v0.14.1) - IMPORTANT: `eth_getProof` calls for historical state will be rejected by default. 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/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 879cb8988e..e85dad52d4 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -1731,23 +1731,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 507c8d3a94..340b946896 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -32,7 +32,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" @@ -46,7 +45,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" @@ -78,8 +76,6 @@ var ( testEthAddrs []common.Address // testEthAddrs[i] corresponds to testKeys[i] testShortIDAddrs []ids.ShortID testAvaxAssetID = ids.ID{1, 2, 3} - username = "Johns" - password = "CjasdjhiPeirbSenfeI13" // #nosec G101 genesisJSON = func(cfg *params.ChainConfig) string { g := new(core.Genesis) @@ -260,12 +256,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 From 4765329f1050930af5b22c8f4701280256c89ecf Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 16 Jan 2025 11:32:26 -0800 Subject: [PATCH 09/11] bump avalanchego in preparation for tagging rc (#751) --- RELEASES.md | 3 +-- go.mod | 2 +- go.sum | 4 ++-- scripts/versions.sh | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index d2072b75b8..628e454843 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2,10 +2,9 @@ ## Pending Release -- Removed deprecated `ExportKey`, `ExportAVAX`, `Export`, `ImportKey`, `ImportAVAX`, `Import` APIs - ## [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. 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/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'} From d00d1db11a6f051cc54a2a23d552dd7fe3134e28 Mon Sep 17 00:00:00 2001 From: Radovenchyk Date: Fri, 17 Jan 2025 18:58:39 +0200 Subject: [PATCH 10/11] chore: changed the link to the documentation (#755) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 6bf036c2f3422b6326a6afad9687a96272f6a331 Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Mon, 20 Jan 2025 14:57:20 +0300 Subject: [PATCH 11/11] remove unused var --- plugin/evm/vm_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 2afa2d9cc8..ef0f557904 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -70,7 +70,6 @@ var ( testKeys []*secp256k1.PrivateKey testEthAddrs []common.Address // testEthAddrs[i] corresponds to testKeys[i] testShortIDAddrs []ids.ShortID - testAvaxAssetID = ids.ID{1, 2, 3} genesisJSON = func(cfg *params.ChainConfig) string { g := new(core.Genesis)