diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34c64fe4d3..92f3f6a62f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -57,6 +57,12 @@ jobs: run: echo "TIMEOUT=1200s" >> "$GITHUB_ENV" - run: go mod download shell: bash + - name: fjl/gencodec generated files are up to date + run: | + grep -lr -E '^// Code generated by github\.com\/fjl\/gencodec\. DO NOT EDIT\.$' . | xargs -r rm + go generate -run "github.com/fjl/gencodec" ./... + git add --intent-to-add --all + git diff --exit-code - name: Mocks are up to date shell: bash run: | diff --git a/accounts/abi/bind/auth.go b/accounts/abi/bind/auth.go index 919b74685a..a724adb174 100644 --- a/accounts/abi/bind/auth.go +++ b/accounts/abi/bind/auth.go @@ -37,9 +37,9 @@ import ( "github.com/ava-labs/libevm/accounts/external" "github.com/ava-labs/libevm/accounts/keystore" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" ) // ErrNoChainID is returned whenever the user failed to specify a chain id. diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go index 73e9877534..f9ce3be9ab 100644 --- a/accounts/abi/bind/backend.go +++ b/accounts/abi/bind/backend.go @@ -31,9 +31,9 @@ import ( "errors" "math/big" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ava-labs/libevm/core/types" ) var ( @@ -64,7 +64,7 @@ type ContractCaller interface { // CallContract executes an Ethereum contract call with the specified data as the // input. - CallContract(ctx context.Context, call interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) + CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) } // AcceptedContractCaller defines methods to perform contract calls on the pending state. @@ -75,7 +75,7 @@ type AcceptedContractCaller interface { AcceptedCodeAt(ctx context.Context, contract common.Address) ([]byte, error) // AcceptedCallContract executes an Ethereum contract call against the accepted state. - AcceptedCallContract(ctx context.Context, call interfaces.CallMsg) ([]byte, error) + AcceptedCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) } // BlockHashContractCaller defines methods to perform contract calls on a specific block hash. @@ -86,7 +86,7 @@ type BlockHashContractCaller interface { CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) // CallContractAtHash executes an Ethereum contract call against the state at the specified block hash. - CallContractAtHash(ctx context.Context, call interfaces.CallMsg, blockHash common.Hash) ([]byte, error) + CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error) } // ContractTransactor defines the methods needed to allow operating with a contract @@ -94,10 +94,10 @@ type BlockHashContractCaller interface { // used when the user does not provide some needed values, but rather leaves it up // to the transactor to decide. type ContractTransactor interface { - interfaces.GasEstimator - interfaces.GasPricer - interfaces.GasPricer1559 - interfaces.TransactionSender + ethereum.GasEstimator + ethereum.GasPricer + ethereum.GasPricer1559 + ethereum.TransactionSender // HeaderByNumber returns a block header from the current canonical chain. If // number is nil, the latest known header is returned. @@ -119,7 +119,7 @@ type DeployBackend interface { // ContractFilterer defines the methods needed to access log events using one-off // queries or continuous event subscriptions. type ContractFilterer interface { - interfaces.LogFilterer + ethereum.LogFilterer } // ContractBackend defines the methods needed to work with contracts on a read-write basis. diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 7254a3539e..20f14aee3e 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -29,9 +29,10 @@ package backends import ( "context" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient/simulated" "github.com/ava-labs/subnet-evm/interfaces" ) @@ -42,14 +43,14 @@ var ( _ bind.ContractBackend = (*SimulatedBackend)(nil) _ bind.DeployBackend = (*SimulatedBackend)(nil) - _ interfaces.ChainReader = (*SimulatedBackend)(nil) - _ interfaces.ChainStateReader = (*SimulatedBackend)(nil) - _ interfaces.TransactionReader = (*SimulatedBackend)(nil) - _ interfaces.TransactionSender = (*SimulatedBackend)(nil) - _ interfaces.ContractCaller = (*SimulatedBackend)(nil) - _ interfaces.GasEstimator = (*SimulatedBackend)(nil) - _ interfaces.GasPricer = (*SimulatedBackend)(nil) - _ interfaces.LogFilterer = (*SimulatedBackend)(nil) + _ ethereum.ChainReader = (*SimulatedBackend)(nil) + _ ethereum.ChainStateReader = (*SimulatedBackend)(nil) + _ ethereum.TransactionReader = (*SimulatedBackend)(nil) + _ ethereum.TransactionSender = (*SimulatedBackend)(nil) + _ ethereum.ContractCaller = (*SimulatedBackend)(nil) + _ ethereum.GasEstimator = (*SimulatedBackend)(nil) + _ ethereum.GasPricer = (*SimulatedBackend)(nil) + _ ethereum.LogFilterer = (*SimulatedBackend)(nil) _ interfaces.AcceptedStateReader = (*SimulatedBackend)(nil) _ interfaces.AcceptedContractCaller = (*SimulatedBackend)(nil) ) diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index 4c4f21f0b8..23da49583d 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -34,12 +34,12 @@ import ( "strings" "sync" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/event" "github.com/ava-labs/subnet-evm/accounts/abi" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/rpc" ) @@ -179,7 +179,7 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri return err } var ( - msg = interfaces.CallMsg{From: opts.From, To: &c.address, Data: input} + msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input} ctx = ensureContext(opts.Context) code []byte output []byte @@ -374,7 +374,7 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad return 0, ErrNoCode } } - msg := interfaces.CallMsg{ + msg := ethereum.CallMsg{ From: opts.From, To: contract, GasPrice: gasPrice, @@ -458,7 +458,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int // Start the background filtering logs := make(chan types.Log, 128) - config := interfaces.FilterQuery{ + config := ethereum.FilterQuery{ Addresses: []common.Address{c.address}, Topics: topics, FromBlock: new(big.Int).SetUint64(opts.Start), @@ -507,7 +507,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter // Start the background filtering logs := make(chan types.Log, 128) - config := interfaces.FilterQuery{ + config := ethereum.FilterQuery{ Addresses: []common.Address{c.address}, Topics: topics, } diff --git a/accounts/abi/bind/base_test.go b/accounts/abi/bind/base_test.go index 35d1d5804a..23dce74594 100644 --- a/accounts/abi/bind/base_test.go +++ b/accounts/abi/bind/base_test.go @@ -34,14 +34,14 @@ import ( "strings" "testing" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/stretchr/testify/assert" ) @@ -77,7 +77,7 @@ func (mt *mockTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error return mt.gasTipCap, nil } -func (mt *mockTransactor) EstimateGas(ctx context.Context, call interfaces.CallMsg) (gas uint64, err error) { +func (mt *mockTransactor) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { return 0, nil } @@ -99,7 +99,7 @@ func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, block return mc.codeAtBytes, mc.codeAtErr } -func (mc *mockCaller) CallContract(ctx context.Context, call interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) { +func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { mc.callContractBlockNumber = blockNumber return mc.callContractBytes, mc.callContractErr } @@ -119,7 +119,7 @@ func (mc *mockAcceptedCaller) AcceptedCodeAt(ctx context.Context, contract commo return mc.acceptedCodeAtBytes, mc.acceptedCodeAtErr } -func (mc *mockAcceptedCaller) AcceptedCallContract(ctx context.Context, call interfaces.CallMsg) ([]byte, error) { +func (mc *mockAcceptedCaller) AcceptedCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) { mc.acceptedCallContractCalled = true return mc.acceptedCallContractBytes, mc.acceptedCallContractErr } @@ -139,7 +139,7 @@ func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.A return mc.codeAtHashBytes, mc.codeAtHashErr } -func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call interfaces.CallMsg, hash common.Hash) ([]byte, error) { +func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) { mc.callContractAtHashCalled = true return mc.callContractAtHashBytes, mc.callContractAtHashErr } diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go index 09c724a63c..a92245558e 100644 --- a/accounts/abi/bind/bind_test.go +++ b/accounts/abi/bind/bind_test.go @@ -299,7 +299,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -355,7 +355,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -401,7 +401,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -459,7 +459,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -507,7 +507,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -574,7 +574,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -620,7 +620,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" `, ` // Create a simulator and wrap a non-deployed contract @@ -659,7 +659,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" `, ` // Create a simulator and wrap a non-deployed contract @@ -706,7 +706,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -756,7 +756,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -831,7 +831,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -925,7 +925,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1115,7 +1115,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1250,7 +1250,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, @@ -1392,7 +1392,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1458,7 +1458,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1568,7 +1568,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" `, ` // Initialize test accounts @@ -1631,7 +1631,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" `, ` key, _ := crypto.GenerateKey() @@ -1692,7 +1692,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1753,7 +1753,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1841,7 +1841,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1911,7 +1911,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, ` @@ -1963,7 +1963,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, tester: ` @@ -2011,7 +2011,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, tester: ` @@ -2052,7 +2052,7 @@ var bindTests = []struct { "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/accounts/abi/bind/backends" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" `, tester: ` diff --git a/accounts/abi/bind/precompilebind/precompile_contract_template.go b/accounts/abi/bind/precompilebind/precompile_contract_template.go index 5421bd9a9e..79937927d4 100644 --- a/accounts/abi/bind/precompilebind/precompile_contract_template.go +++ b/accounts/abi/bind/precompilebind/precompile_contract_template.go @@ -37,11 +37,11 @@ import ( "github.com/ava-labs/subnet-evm/precompile/allowlist" {{- end}} "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" _ "embed" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" ) {{$contract := .Contract}} const ( @@ -67,7 +67,7 @@ var ( _ = abi.JSON _ = errors.New _ = big.NewInt - _ = vmerrs.ErrOutOfGas + _ = vm.ErrOutOfGas _ = common.Big0 ) @@ -230,7 +230,7 @@ func {{decapitalise .Normalized.Name}}(accessibleState contract.AccessibleState, {{- if not .Original.IsConstant}} if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } {{- end}} @@ -294,7 +294,7 @@ func {{decapitalise $contract.Type}}Fallback (accessibleState contract.Accessibl } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } {{- if $contract.AllowList}} diff --git a/accounts/abi/bind/precompilebind/precompile_contract_test_template.go b/accounts/abi/bind/precompilebind/precompile_contract_test_template.go index 9af40cb1c9..3b1f384d19 100644 --- a/accounts/abi/bind/precompilebind/precompile_contract_test_template.go +++ b/accounts/abi/bind/precompilebind/precompile_contract_test_template.go @@ -19,13 +19,13 @@ import ( "github.com/ava-labs/subnet-evm/precompile/allowlist" {{- end}} "github.com/ava-labs/subnet-evm/precompile/testutils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" "github.com/stretchr/testify/require" ) var ( - _ = vmerrs.ErrOutOfGas + _ = vm.ErrOutOfGas _ = big.NewInt _ = common.Big0 _ = require.New @@ -121,7 +121,7 @@ var( }, SuppliedGas: {{$func.Normalized.Name}}GasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, {{- end}} "insufficient gas for {{decapitalise $func.Normalized.Name}} should fail": { @@ -147,7 +147,7 @@ var( }, SuppliedGas: {{$func.Normalized.Name}}GasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, {{- end}} {{- if .Contract.Fallback}} @@ -156,14 +156,14 @@ var( Input: []byte{}, SuppliedGas: {{.Contract.Type}}FallbackGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "readOnly fallback should fail": { Caller: common.Address{1}, Input: []byte{}, SuppliedGas: {{.Contract.Type}}FallbackGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "fallback should succeed": { Caller: common.Address{1}, diff --git a/accounts/abi/bind/template.go b/accounts/abi/bind/template.go index 96b0d06ef5..a588e24f8c 100644 --- a/accounts/abi/bind/template.go +++ b/accounts/abi/bind/template.go @@ -103,8 +103,8 @@ import ( "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" + "github.com/ava-labs/libevm/core/types" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/event" ) @@ -114,7 +114,7 @@ var ( _ = errors.New _ = big.NewInt _ = strings.NewReader - _ = interfaces.NotFound + _ = ethereum.NotFound _ = bind.Bind _ = common.Big1 _ = types.BloomLookup @@ -443,7 +443,7 @@ var ( event string // Event name to use for unpacking event data logs chan types.Log // Log channel receiving the found contract events - sub interfaces.Subscription // Subscription for errors, completion and termination + sub ethereum.Subscription // Subscription for errors, completion and termination done bool // Whether the subscription completed delivering logs fail error // Occurred error to stop iteration } diff --git a/accounts/abi/bind/util.go b/accounts/abi/bind/util.go index 960bbd1d64..cf2fc2691f 100644 --- a/accounts/abi/bind/util.go +++ b/accounts/abi/bind/util.go @@ -31,10 +31,10 @@ import ( "errors" "time" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" ) // WaitMined waits for tx to be mined on the blockchain. @@ -50,7 +50,7 @@ func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*ty return receipt, nil } - if errors.Is(err, interfaces.NotFound) { + if errors.Is(err, ethereum.NotFound) { logger.Trace("Transaction not yet mined") } else { logger.Trace("Receipt retrieval failed", "err", err) diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go index 5c7eb1fd76..3d5badeddd 100644 --- a/accounts/abi/bind/util_test.go +++ b/accounts/abi/bind/util_test.go @@ -34,9 +34,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient/simulated" "github.com/ava-labs/subnet-evm/params" ) diff --git a/cmd/evm/internal/t8ntool/block.go b/cmd/evm/internal/t8ntool/block.go index 0543014753..b28799f878 100644 --- a/cmd/evm/internal/t8ntool/block.go +++ b/cmd/evm/internal/t8ntool/block.go @@ -37,9 +37,9 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/urfave/cli/v2" ) @@ -166,7 +166,10 @@ func (i *bbInput) ToBlock() *types.Block { if i.Header.Difficulty != nil { header.Difficulty = i.Header.Difficulty } - return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers) + return types.NewBlockWithHeader(header).WithBody(types.Body{ + Transactions: i.Txs, + Uncles: i.Ommers, + }) } // SealBlock seals the given block using the configured engine. diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 488065fad0..7b81bc1795 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -32,6 +32,8 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" @@ -41,9 +43,7 @@ import ( "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" diff --git a/cmd/evm/internal/t8ntool/gen_header.go b/cmd/evm/internal/t8ntool/gen_header.go index 867ee56241..374cee2a22 100644 --- a/cmd/evm/internal/t8ntool/gen_header.go +++ b/cmd/evm/internal/t8ntool/gen_header.go @@ -7,10 +7,10 @@ import ( "errors" "math/big" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" ) var _ = (*headerMarshaling)(nil) diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index e409a8e9aa..5336ee26d8 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -36,9 +36,9 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/tests" "github.com/urfave/cli/v2" diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index baa54a4eca..645776def2 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -36,11 +36,11 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/tracers" "github.com/ava-labs/subnet-evm/params" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" diff --git a/cmd/evm/internal/t8ntool/tx_iterator.go b/cmd/evm/internal/t8ntool/tx_iterator.go index 81021c662a..d9127f073f 100644 --- a/cmd/evm/internal/t8ntool/tx_iterator.go +++ b/cmd/evm/internal/t8ntool/tx_iterator.go @@ -27,9 +27,9 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 6e7317bb85..b37a68a30e 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -38,13 +38,13 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/cmd/evm/internal/compiler" "github.com/ava-labs/subnet-evm/cmd/utils" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/vm/runtime" "github.com/ava-labs/subnet-evm/internal/flags" diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index ab77c5e767..d831c3f158 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -33,9 +33,9 @@ import ( "os" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/eth/tracers/logger" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/tests" "github.com/urfave/cli/v2" diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 209580031b..d576330ca3 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -10,11 +10,11 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/cmd/simulator/key" "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/params" ) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 57fa6fce70..f0ada1f52f 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -15,13 +15,13 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" ethcrypto "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/cmd/simulator/config" "github.com/ava-labs/subnet-evm/cmd/simulator/key" "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/params" "golang.org/x/sync/errgroup" diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 367281c810..41d6e388ed 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -8,11 +8,11 @@ import ( "fmt" "time" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" - "github.com/ava-labs/subnet-evm/interfaces" ) type ethereumTxWorker struct { @@ -21,7 +21,7 @@ type ethereumTxWorker struct { acceptedNonce uint64 address common.Address - sub interfaces.Subscription + sub ethereum.Subscription newHeads chan *types.Header } diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index cf71363d0e..57983a33ff 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -8,8 +8,8 @@ import ( "crypto/ecdsa" "fmt" + "github.com/ava-labs/libevm/core/types" ethcrypto "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" ) diff --git a/consensus/consensus.go b/consensus/consensus.go index d95ebfae18..9f565d3fa0 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -31,9 +31,9 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go index c544f30026..1f1422b02a 100644 --- a/consensus/dummy/consensus.go +++ b/consensus/dummy/consensus.go @@ -11,15 +11,16 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" + "github.com/ava-labs/subnet-evm/plugin/evm/vmerrors" "github.com/ava-labs/subnet-evm/utils" - "github.com/ava-labs/subnet-evm/vmerrs" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" ) @@ -121,7 +122,7 @@ func (eng *DummyEngine) verifyCoinbase(header *types.Header, parent *types.Heade // we fetch the configured coinbase at the parent's state // to check against the coinbase in [header]. if configuredAddressAtParent != header.Coinbase { - return fmt.Errorf("%w: %v does not match required coinbase address %v", vmerrs.ErrInvalidCoinbase, header.Coinbase, configuredAddressAtParent) + return fmt.Errorf("%w: %v does not match required coinbase address %v", vmerrors.ErrInvalidCoinbase, header.Coinbase, configuredAddressAtParent) } return nil } @@ -162,8 +163,9 @@ func verifyHeaderGasFields(config *extras.ChainConfig, header *types.Header, par parent, header.Time, ) - if !utils.BigEqual(header.BlockGasCost, expectedBlockGasCost) { - return fmt.Errorf("invalid block gas cost: have %d, want %d", header.BlockGasCost, expectedBlockGasCost) + headerExtra := customtypes.GetHeaderExtra(header) + if !utils.BigEqual(headerExtra.BlockGasCost, expectedBlockGasCost) { + return fmt.Errorf("invalid block gas cost: have %d, want %d", headerExtra.BlockGasCost, expectedBlockGasCost) } return nil } @@ -336,7 +338,7 @@ func (eng *DummyEngine) Finalize(chain consensus.ChainHeaderReader, block *types return err } // Verify the BlockGasCost set in the header matches the expected value. - blockGasCost := block.BlockGasCost() + blockGasCost := customtypes.BlockGasCost(block) expectedBlockGasCost := customheader.BlockGasCost( config, feeConfig, @@ -373,7 +375,8 @@ func (eng *DummyEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, h config := params.GetExtra(chain.Config()) // Calculate the required block gas cost for this block. - header.BlockGasCost = customheader.BlockGasCost( + headerExtra := customtypes.GetHeaderExtra(header) + headerExtra.BlockGasCost = customheader.BlockGasCost( config, feeConfig, parent, @@ -383,7 +386,7 @@ func (eng *DummyEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, h // Verify that this block covers the block fee. if err := eng.verifyBlockFee( header.BaseFee, - header.BlockGasCost, + headerExtra.BlockGasCost, txs, receipts, ); err != nil { diff --git a/consensus/dummy/consensus_test.go b/consensus/dummy/consensus_test.go index 0aa0245fa5..c4cb25a1d2 100644 --- a/consensus/dummy/consensus_test.go +++ b/consensus/dummy/consensus_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/plugin/evm/header" ) diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go index 9e3444ec38..bc6821847a 100644 --- a/consensus/misc/eip4844/eip4844.go +++ b/consensus/misc/eip4844/eip4844.go @@ -31,7 +31,7 @@ import ( "fmt" "math/big" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/core/bench_test.go b/core/bench_test.go index 7a5dc50676..c64a8b0679 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -33,13 +33,14 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) func BenchmarkInsertChain_empty_memdb(b *testing.B) { @@ -250,7 +251,7 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin rawdb.WriteCanonicalHash(db, hash, n) if n == 0 { - rawdb.WriteChainConfig(db, hash, genesis.Config) + customrawdb.WriteChainConfig(db, hash, genesis.Config) } rawdb.WriteHeadHeaderHash(db, hash) diff --git a/core/block_validator.go b/core/block_validator.go index 73956e231b..6a18502afe 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -30,10 +30,10 @@ import ( "errors" "fmt" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" ) diff --git a/core/blockchain.go b/core/blockchain.go index 46fd3c261f..3e9cc11f1a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -41,6 +41,8 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/lru" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" @@ -51,12 +53,12 @@ import ( "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/version" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/triedb/hashdb" "github.com/ava-labs/subnet-evm/triedb/pathdb" @@ -214,7 +216,7 @@ func (c *CacheConfig) triedbConfig() *triedb.Config { config.DBOverride = hashdb.Config{ CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, StatsPrefix: trieCleanCacheStatsNamespace, - ReferenceRootAtomicallyOnUpdate: true, // Automatically reference root nodes when an update is made + ReferenceRootAtomicallyOnUpdate: true, }.BackendConstructor } if c.StateScheme == rawdb.PathScheme { @@ -473,7 +475,7 @@ func NewBlockChain( // if txlookup limit is 0 (uindexing disabled), we don't need to repair the tx index tail. if bc.cacheConfig.TransactionHistory != 0 { - latestStateSynced := rawdb.GetLatestSyncPerformed(bc.db) + latestStateSynced := customrawdb.GetLatestSyncPerformed(bc.db) bc.repairTxIndexTail(latestStateSynced) } @@ -506,7 +508,7 @@ func (bc *BlockChain) batchBlockAcceptedIndices(batch ethdb.Batch, b *types.Bloc if !bc.cacheConfig.SkipTxIndexing { rawdb.WriteTxLookupEntriesByBlock(batch, b) } - if err := rawdb.WriteAcceptorTip(batch, b.Hash()); err != nil { + if err := customrawdb.WriteAcceptorTip(batch, b.Hash()); err != nil { return fmt.Errorf("%w: failed to write acceptor tip key", err) } return nil @@ -609,7 +611,7 @@ func (bc *BlockChain) startAcceptor() { bc.acceptorTipLock.Unlock() // Update accepted feeds - flattenedLogs := types.FlattenLogs(logs) + flattenedLogs := customtypes.FlattenLogs(logs) bc.chainAcceptedFeed.Send(ChainEvent{Block: next, Hash: next.Hash(), Logs: flattenedLogs}) if len(flattenedLogs) > 0 { bc.logsAcceptedFeed.Send(flattenedLogs) @@ -1233,8 +1235,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, parentRoot common. } // Commit all cached state changes into underlying memory database. - var err error - _, err = bc.commitWithSnap(block, parentRoot, state) + _, err := bc.commitWithSnap(block, parentRoot, state) if err != nil { return err } @@ -1442,7 +1443,7 @@ func (bc *BlockChain) insertBlock(block *types.Block, writes bool) error { "parentHash", block.ParentHash(), "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(), "elapsed", common.PrettyDuration(time.Since(start)), - "root", block.Root(), "baseFeePerGas", block.BaseFee(), "blockGasCost", block.BlockGasCost(), + "root", block.Root(), "baseFeePerGas", block.BaseFee(), "blockGasCost", customtypes.BlockGasCost(block), ) processedBlockGasUsedCounter.Inc(int64(block.GasUsed())) @@ -1485,7 +1486,7 @@ func (bc *BlockChain) collectUnflattenedLogs(b *types.Block, removed bool) [][]* // the processing of a block. These logs are later announced as deleted or reborn. func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { unflattenedLogs := bc.collectUnflattenedLogs(b, removed) - return types.FlattenLogs(unflattenedLogs) + return customtypes.FlattenLogs(unflattenedLogs) } // reorg takes two blocks, an old chain and a new chain and will reconstruct the @@ -1756,8 +1757,8 @@ func (bc *BlockChain) reprocessBlock(parent *types.Block, current *types.Block) func (bc *BlockChain) commitWithSnap( current *types.Block, parentRoot common.Hash, statedb *state.StateDB, ) (common.Hash, error) { - // blockHashes must be passed through Commit since snapshots are based on the - // block hash. + // blockHashes must be passed through [state.StateDB]'s Commit since snapshots + // are based on the block hash. blockHashes := snapshot.WithBlockHashes(current.Hash(), current.ParentHash()) root, err := statedb.Commit(current.NumberU64(), bc.chainConfig.IsEIP158(current.Number()), blockHashes) if err != nil { @@ -1808,7 +1809,7 @@ func (bc *BlockChain) initSnapshot(b *types.Header) { // state that reprocessing will start from. func (bc *BlockChain) reprocessState(current *types.Block, reexec uint64) error { origin := current.NumberU64() - acceptorTip, err := rawdb.ReadAcceptorTip(bc.db) + acceptorTip, err := customrawdb.ReadAcceptorTip(bc.db) if err != nil { return fmt.Errorf("%w: unable to get Acceptor tip", err) } @@ -1939,9 +1940,9 @@ func (bc *BlockChain) reprocessState(current *types.Block, reexec uint64) error func (bc *BlockChain) protectTrieIndex() error { if !bc.cacheConfig.Pruning { - return rawdb.WritePruningDisabled(bc.db) + return customrawdb.WritePruningDisabled(bc.db) } - pruningDisabled, err := rawdb.HasPruningDisabled(bc.db) + pruningDisabled, err := customrawdb.HasPruningDisabled(bc.db) if err != nil { return fmt.Errorf("failed to check if the chain has been run with pruning disabled: %w", err) } @@ -2026,7 +2027,7 @@ func (bc *BlockChain) populateMissingTries() error { // Write marker to DB to indicate populate missing tries finished successfully. // Note: writing the marker here means that we do allow consecutive runs of re-populating // missing tries if it does not finish during the prior run. - if err := rawdb.WritePopulateMissingTries(bc.db); err != nil { + if err := customrawdb.WritePopulateMissingTries(bc.db); err != nil { return fmt.Errorf("failed to write offline pruning success marker: %w", err) } @@ -2124,9 +2125,9 @@ func (bc *BlockChain) ResetToStateSyncedBlock(block *types.Block) error { } rawdb.WriteHeadBlockHash(batch, block.Hash()) rawdb.WriteHeadHeaderHash(batch, block.Hash()) - rawdb.WriteSnapshotBlockHash(batch, block.Hash()) + customrawdb.WriteSnapshotBlockHash(batch, block.Hash()) rawdb.WriteSnapshotRoot(batch, block.Root()) - if err := rawdb.WriteSyncPerformed(batch, block.NumberU64()); err != nil { + if err := customrawdb.WriteSyncPerformed(batch, block.NumberU64()); err != nil { return err } diff --git a/core/blockchain_iterator.go b/core/blockchain_iterator.go index 70e3e27605..e453720c7b 100644 --- a/core/blockchain_iterator.go +++ b/core/blockchain_iterator.go @@ -33,7 +33,7 @@ import ( "fmt" "sync" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) type blockAndState struct { diff --git a/core/blockchain_log_test.go b/core/blockchain_log_test.go index 054812eb10..ca02f542e5 100644 --- a/core/blockchain_log_test.go +++ b/core/blockchain_log_test.go @@ -9,12 +9,12 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" "github.com/stretchr/testify/require" diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index b26d37087d..50f29f57bb 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -30,16 +30,16 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/constants" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" "github.com/ava-labs/subnet-evm/precompile/contracts/rewardmanager" diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 3696c19f76..256abca3c5 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -35,12 +35,12 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/stretchr/testify/require" ) diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 6d210aac45..9bf245b092 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -32,7 +32,7 @@ package core import ( "testing" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) // verifyNoGaps checks that there are no gaps after the initial set of blocks in diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index aa7da5df0b..dea9a6a956 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -39,12 +39,12 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" ) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 0eceeebeca..3ea2abbab7 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -11,17 +11,18 @@ import ( "github.com/ava-labs/avalanchego/upgrade" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/state/pruner" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" "github.com/holiman/uint256" ) @@ -239,7 +240,7 @@ func TestCorruptSnapshots(t *testing.T) { create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) { // Delete the snapshot block hash and state root to ensure that if we die in between writing a snapshot // diff layer to disk at any point, we can still recover on restart. - rawdb.DeleteSnapshotBlockHash(db) + customrawdb.DeleteSnapshotBlockHash(db) rawdb.DeleteSnapshotRoot(db) return createBlockChain(db, pruningConfig, gspec, lastAcceptedHash) diff --git a/core/bloom_indexer.go b/core/bloom_indexer.go index b2100d6355..29960c0ced 100644 --- a/core/bloom_indexer.go +++ b/core/bloom_indexer.go @@ -22,10 +22,10 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/bitutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) const ( diff --git a/core/bloombits/generator.go b/core/bloombits/generator.go index deb0ab3eea..9acabe35b8 100644 --- a/core/bloombits/generator.go +++ b/core/bloombits/generator.go @@ -29,7 +29,7 @@ package bloombits import ( "errors" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) var ( diff --git a/core/bloombits/generator_test.go b/core/bloombits/generator_test.go index 6dfacc763d..c07a5d2b9c 100644 --- a/core/bloombits/generator_test.go +++ b/core/bloombits/generator_test.go @@ -32,7 +32,7 @@ import ( "math/rand" "testing" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) // Tests that batched bloom bits are correctly rotated from the input bloom diff --git a/core/chain_indexer.go b/core/chain_indexer.go index ce0d7e20cd..1dd532f885 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -36,11 +36,11 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) // ChainIndexerBackend defines the methods needed to process chain segments in diff --git a/core/chain_indexer_test.go b/core/chain_indexer_test.go index b47c4af282..97d7f479ec 100644 --- a/core/chain_indexer_test.go +++ b/core/chain_indexer_test.go @@ -36,8 +36,8 @@ import ( "time" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" ) // Runs multiple tests with randomized parameters. diff --git a/core/chain_makers.go b/core/chain_makers.go index ec6e015e38..5a3b412abb 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -31,6 +31,8 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/triedb" @@ -38,9 +40,7 @@ import ( "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/constants" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/holiman/uint256" diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index ad819b7bee..a200272c16 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -31,12 +31,12 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/core/error.go b/core/error.go index 2a23e691d0..e321e07d69 100644 --- a/core/error.go +++ b/core/error.go @@ -29,7 +29,7 @@ package core import ( "errors" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) var ( diff --git a/core/events.go b/core/events.go index dc85101f72..90345c67de 100644 --- a/core/events.go +++ b/core/events.go @@ -28,7 +28,7 @@ package core import ( "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) // NewTxsEvent is posted when a batch of transactions enter the transaction pool. diff --git a/core/evm.go b/core/evm.go index c64ebf8233..6329f0a3b7 100644 --- a/core/evm.go +++ b/core/evm.go @@ -31,13 +31,12 @@ import ( "math/big" "github.com/ava-labs/libevm/common" - ethtypes "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core/extstate" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/predicate" @@ -50,14 +49,14 @@ func init() { type hooks struct{} -// OverrideNewEVMArgs is a hook that is called back when a new EVM is created. +// OverrideNewEVMArgs is a hook that is called in [vm.NewEVM]. // It allows for the modification of the EVM arguments before the EVM is created. // Specifically, we set Random to be the same as Difficulty since Shanghai. // This allows using the same jump table as upstream. -// Then we set Difficulty to nil as it is post Merge in upstream. +// Then we set Difficulty to 0 as it is post Merge in upstream. // Additionally we wrap the StateDB with the appropriate StateDB wrapper, -// which is used in coreth to process historical pre-AP1 blocks with the -// GetCommittedState method as it was historically. +// which is used in subnet-evm to process historical pre-AP1 blocks with the +// [StateDbAP1.GetCommittedState] method as it was historically. func (hooks) OverrideNewEVMArgs(args *vm.NewEVMArgs) *vm.NewEVMArgs { rules := args.ChainConfig.Rules(args.BlockContext.BlockNumber, params.IsMergeTODO, args.BlockContext.Time) args.StateDB = wrapStateDB(rules, args.StateDB) @@ -65,7 +64,7 @@ func (hooks) OverrideNewEVMArgs(args *vm.NewEVMArgs) *vm.NewEVMArgs { if rules.IsShanghai { args.BlockContext.Random = new(common.Hash) args.BlockContext.Random.SetBytes(args.BlockContext.Difficulty.Bytes()) - args.BlockContext.Difficulty = nil + args.BlockContext.Difficulty = new(big.Int) } return args @@ -77,7 +76,7 @@ func (hooks) OverrideEVMResetArgs(rules params.Rules, args *vm.EVMResetArgs) *vm } func wrapStateDB(rules params.Rules, db vm.StateDB) vm.StateDB { - return &extstate.StateDB{VmStateDB: db.(extstate.VmStateDB)} + return extstate.New(db.(extstate.VmStateDB)) } // ChainContext supports retrieving headers and consensus parameters from the @@ -155,7 +154,7 @@ func newEVMBlockContext(header *types.Header, chain ChainContext, author *common BaseFee: baseFee, BlobBaseFee: blobBaseFee, GasLimit: header.GasLimit, - Header: ðtypes.Header{ + Header: &types.Header{ Number: new(big.Int).Set(header.Number), Time: header.Time, Extra: extra, diff --git a/core/extstate/statedb.go b/core/extstate/statedb.go index def7860c2d..04fb7cb36c 100644 --- a/core/extstate/statedb.go +++ b/core/extstate/statedb.go @@ -5,8 +5,8 @@ package extstate import ( "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/predicate" ) @@ -14,25 +14,35 @@ import ( type VmStateDB interface { vm.StateDB Logs() []*types.Log - GetTxHash() common.Hash } +type vmStateDB = VmStateDB + type StateDB struct { - VmStateDB + vmStateDB // Ordered storage slots to be used in predicate verification as set in the tx access list. - // Only set in PrepareAccessList, and un-modified through execution. + // Only set in [StateDB.Prepare], and un-modified through execution. predicateStorageSlots map[common.Address][][]byte } +// New creates a new [*StateDB] with the given [VmStateDB], effectively wrapping it +// with additional functionality. +func New(vm VmStateDB) *StateDB { + return &StateDB{ + vmStateDB: vm, + predicateStorageSlots: make(map[common.Address][][]byte), + } +} + func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { rulesExtra := params.GetRulesExtra(rules) s.predicateStorageSlots = predicate.PreparePredicateStorageSlots(rulesExtra, list) - s.VmStateDB.Prepare(rules, sender, coinbase, dst, precompiles, list) + s.vmStateDB.Prepare(rules, sender, coinbase, dst, precompiles, list) } -// GetLogData returns the underlying topics and data from each log included in the StateDB +// GetLogData returns the underlying topics and data from each log included in the [StateDB]. // Test helper function. func (s *StateDB) GetLogData() (topics [][]common.Hash, data [][]byte) { for _, log := range s.Logs() { @@ -54,10 +64,7 @@ func (s *StateDB) GetLogData() (topics [][]common.Hash, data [][]byte) { // GetPredicateStorageSlots(AddrA, 1) -> Predicate3 func (s *StateDB) GetPredicateStorageSlots(address common.Address, index int) ([]byte, bool) { predicates, exists := s.predicateStorageSlots[address] - if !exists { - return nil, false - } - if index >= len(predicates) { + if !exists || index >= len(predicates) { return nil, false } return predicates[index], true @@ -65,8 +72,5 @@ func (s *StateDB) GetPredicateStorageSlots(address common.Address, index int) ([ // SetPredicateStorageSlots sets the predicate storage slots for the given address func (s *StateDB) SetPredicateStorageSlots(address common.Address, predicates [][]byte) { - if s.predicateStorageSlots == nil { - s.predicateStorageSlots = make(map[common.Address][][]byte) - } s.predicateStorageSlots[address] = predicates } diff --git a/core/extstate/test_statedb.go b/core/extstate/test_statedb.go index 62cd5d8bda..1f86baed4b 100644 --- a/core/extstate/test_statedb.go +++ b/core/extstate/test_statedb.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/stretchr/testify/require" @@ -16,5 +16,5 @@ func NewTestStateDB(t testing.TB) contract.StateDB { db := rawdb.NewMemoryDatabase() statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) require.NoError(t, err) - return &StateDB{VmStateDB: statedb} + return New(statedb) } diff --git a/core/gen_genesis.go b/core/gen_genesis.go index e4f9c23fd4..15da6718a6 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -7,11 +7,11 @@ import ( "errors" "math/big" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" - "github.com/ava-labs/libevm/params" + "github.com/ava-labs/libevm/core/types" + params0 "github.com/ava-labs/subnet-evm/params" ) var _ = (*genesisSpecMarshaling)(nil) @@ -19,7 +19,7 @@ var _ = (*genesisSpecMarshaling)(nil) // MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { - Config *params.ChainConfig `json:"config"` + Config *params0.ChainConfig `json:"config"` Nonce math.HexOrDecimal64 `json:"nonce"` Timestamp math.HexOrDecimal64 `json:"timestamp"` ExtraData hexutil.Bytes `json:"extraData"` @@ -68,7 +68,7 @@ func (g Genesis) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { - Config *params.ChainConfig `json:"config"` + Config *params0.ChainConfig `json:"config"` Nonce *math.HexOrDecimal64 `json:"nonce"` Timestamp *math.HexOrDecimal64 `json:"timestamp"` ExtraData *hexutil.Bytes `json:"extraData"` diff --git a/core/genesis.go b/core/genesis.go index 4cd87a769b..ac332bb052 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -36,15 +36,16 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" "github.com/ava-labs/subnet-evm/triedb/pathdb" "github.com/holiman/uint256" @@ -54,7 +55,7 @@ import ( var errGenesisNoConfig = errors.New("genesis has no chain configuration") -// Deprecated: use types.GenesisAccount instead. +// Deprecated: use types.Account instead. type GenesisAccount = types.Account // Deprecated: use types.GenesisAlloc instead. @@ -175,12 +176,12 @@ func SetupGenesisBlock( if err := newcfg.CheckConfigForkOrder(); err != nil { return newcfg, common.Hash{}, err } - storedcfg := rawdb.ReadChainConfig(db, stored) + storedcfg := customrawdb.ReadChainConfig(db, stored) // If there is no previously stored chain config, write the chain config to disk. if storedcfg == nil { // Note: this can happen since we did not previously write the genesis block and chain config in the same batch. log.Warn("Found genesis block without chain config") - rawdb.WriteChainConfig(db, stored, newcfg) + customrawdb.WriteChainConfig(db, stored, newcfg) return newcfg, stored, nil } // Check config compatibility and write the config. Compatibility errors @@ -210,7 +211,7 @@ func SetupGenesisBlock( } // Required to write the chain config to disk to ensure both the chain config and upgrade bytes are persisted to disk. // Note: this intentionally removes an extra check from upstream. - rawdb.WriteChainConfig(db, stored, newcfg) + customrawdb.WriteChainConfig(db, stored, newcfg) return newcfg, stored, nil } @@ -359,7 +360,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) rawdb.WriteHeadBlockHash(batch, block.Hash()) rawdb.WriteHeadHeaderHash(batch, block.Hash()) - rawdb.WriteChainConfig(batch, block.Hash(), config) + customrawdb.WriteChainConfig(batch, block.Hash(), config) if err := batch.Write(); err != nil { return nil, fmt.Errorf("failed to write genesis block: %w", err) } diff --git a/core/genesis_test.go b/core/genesis_test.go index 1f20c21f33..b481966716 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -34,14 +34,15 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" + ethparams "github.com/ava-labs/libevm/params" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" @@ -164,7 +165,7 @@ func testSetupGenesis(t *testing.T, scheme string) { }, wantHash: customghash, wantConfig: customg.Config, - wantErr: ¶ms.ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "SubnetEVM fork block timestamp", StoredTime: u64(90), NewTime: u64(100), diff --git a/core/headerchain.go b/core/headerchain.go index 981d37f547..6b5914e3ae 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -35,10 +35,10 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/lru" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/consensus" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/core/headerchain_test.go b/core/headerchain_test.go index baa0309b1e..750f03e702 100644 --- a/core/headerchain_test.go +++ b/core/headerchain_test.go @@ -33,11 +33,11 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" ) diff --git a/core/predicate_check.go b/core/predicate_check.go index 1656531475..cd4bc92c21 100644 --- a/core/predicate_check.go +++ b/core/predicate_check.go @@ -9,8 +9,8 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/predicate" diff --git a/core/predicate_check_test.go b/core/predicate_check_test.go index 2a19fac4cf..5a7f14c4d2 100644 --- a/core/predicate_check_test.go +++ b/core/predicate_check_test.go @@ -10,7 +10,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/stretchr/testify/require" diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go deleted file mode 100644 index ff4a98ae92..0000000000 --- a/core/rawdb/accessors_chain.go +++ /dev/null @@ -1,606 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "encoding/binary" - "errors" - "math/big" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/params" -) - -// ReadCanonicalHash retrieves the hash assigned to a canonical block number. -func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { - data, _ := db.Get(headerHashKey(number)) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteCanonicalHash stores the hash assigned to a canonical block number. -func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { - log.Crit("Failed to store number to hash mapping", "err", err) - } -} - -// DeleteCanonicalHash removes the number to hash canonical mapping. -func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) { - if err := db.Delete(headerHashKey(number)); err != nil { - log.Crit("Failed to delete number to hash mapping", "err", err) - } -} - -// ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights, -// both canonical and reorged forks included. -func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash { - prefix := headerKeyPrefix(number) - - hashes := make([]common.Hash, 0, 1) - it := db.NewIterator(prefix, nil) - defer it.Release() - - for it.Next() { - if key := it.Key(); len(key) == len(prefix)+32 { - hashes = append(hashes, common.BytesToHash(key[len(key)-32:])) - } - } - return hashes -} - -type NumberHash struct { - Number uint64 - Hash common.Hash -} - -// ReadAllHashesInRange retrieves all the hashes assigned to blocks at certain -// heights, both canonical and reorged forks included. -// This method considers both limits to be _inclusive_. -func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash { - var ( - start = encodeBlockNumber(first) - keyLength = len(headerPrefix) + 8 + 32 - hashes = make([]*NumberHash, 0, 1+last-first) - it = db.NewIterator(headerPrefix, start) - ) - defer it.Release() - for it.Next() { - key := it.Key() - if len(key) != keyLength { - continue - } - num := binary.BigEndian.Uint64(key[len(headerPrefix) : len(headerPrefix)+8]) - if num > last { - break - } - hash := common.BytesToHash(key[len(key)-32:]) - hashes = append(hashes, &NumberHash{num, hash}) - } - return hashes -} - -// ReadAllCanonicalHashes retrieves all canonical number and hash mappings at the -// certain chain range. If the accumulated entries reaches the given threshold, -// abort the iteration and return the semi-finish result. -func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int) ([]uint64, []common.Hash) { - // Short circuit if the limit is 0. - if limit == 0 { - return nil, nil - } - var ( - numbers []uint64 - hashes []common.Hash - ) - // Construct the key prefix of start point. - start, end := headerHashKey(from), headerHashKey(to) - it := db.NewIterator(nil, start) - defer it.Release() - - for it.Next() { - if bytes.Compare(it.Key(), end) >= 0 { - break - } - if key := it.Key(); len(key) == len(headerPrefix)+8+1 && bytes.Equal(key[len(key)-1:], headerHashSuffix) { - numbers = append(numbers, binary.BigEndian.Uint64(key[len(headerPrefix):len(headerPrefix)+8])) - hashes = append(hashes, common.BytesToHash(it.Value())) - // If the accumulated entries reaches the limit threshold, return. - if len(numbers) >= limit { - break - } - } - } - return numbers, hashes -} - -// ReadHeaderNumber returns the header number assigned to a hash. -func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { - data, _ := db.Get(headerNumberKey(hash)) - if len(data) != 8 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteHeaderNumber stores the hash->number mapping. -func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - key := headerNumberKey(hash) - enc := encodeBlockNumber(number) - if err := db.Put(key, enc); err != nil { - log.Crit("Failed to store hash to number mapping", "err", err) - } -} - -// DeleteHeaderNumber removes hash->number mapping. -func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(headerNumberKey(hash)); err != nil { - log.Crit("Failed to delete hash to number mapping", "err", err) - } -} - -// ReadHeadHeaderHash retrieves the hash of the current canonical head header. -func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headHeaderKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteHeadHeaderHash stores the hash of the current canonical head header. -func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last header's hash", "err", err) - } -} - -// ReadHeadBlockHash retrieves the hash of the current canonical head block. -func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headBlockKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteHeadBlockHash stores the head block's hash. -func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headBlockKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last block's hash", "err", err) - } -} - -// ReadHeaderRLP retrieves a block header in its raw RLP database encoding. -func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - data, _ := db.Get(headerKey(number, hash)) - if len(data) > 0 { - return data - } - return nil -} - -// HasHeader verifies the existence of a block header corresponding to the hash. -func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { - if has, err := db.Has(headerKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadHeader retrieves the block header corresponding to the hash. -func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { - data := ReadHeaderRLP(db, hash, number) - if len(data) == 0 { - return nil - } - header := new(types.Header) - if err := rlp.DecodeBytes(data, header); err != nil { - log.Error("Invalid block header RLP", "hash", hash, "err", err) - return nil - } - return header -} - -// WriteHeader stores a block header into the database and also stores the hash- -// to-number mapping. -func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { - var ( - hash = header.Hash() - number = header.Number.Uint64() - ) - // Write the hash -> number mapping - WriteHeaderNumber(db, hash, number) - - // Write the encoded header - data, err := rlp.EncodeToBytes(header) - if err != nil { - log.Crit("Failed to RLP encode header", "err", err) - } - key := headerKey(number, hash) - if err := db.Put(key, data); err != nil { - log.Crit("Failed to store header", "err", err) - } -} - -// DeleteHeader removes all block header data associated with a hash. -func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - deleteHeaderWithoutNumber(db, hash, number) - if err := db.Delete(headerNumberKey(hash)); err != nil { - log.Crit("Failed to delete hash to number mapping", "err", err) - } -} - -// deleteHeaderWithoutNumber removes only the block header but does not remove -// the hash to number mapping. -func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(headerKey(number, hash)); err != nil { - log.Crit("Failed to delete header", "err", err) - } -} - -// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. -func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - data, _ := db.Get(blockBodyKey(number, hash)) - if len(data) > 0 { - return data - } - return nil -} - -// ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical -// block at number, in RLP encoding. -func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { - // Need to get the hash - data, _ := db.Get(blockBodyKey(number, ReadCanonicalHash(db, number))) - if len(data) > 0 { - return data - } - return nil -} - -// WriteBodyRLP stores an RLP encoded block body into the database. -func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { - if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { - log.Crit("Failed to store block body", "err", err) - } -} - -// HasBody verifies the existence of a block body corresponding to the hash. -func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { - if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadBody retrieves the block body corresponding to the hash. -func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { - data := ReadBodyRLP(db, hash, number) - if len(data) == 0 { - return nil - } - body := new(types.Body) - if err := rlp.DecodeBytes(data, body); err != nil { - log.Error("Invalid block body RLP", "hash", hash, "err", err) - return nil - } - return body -} - -// WriteBody stores a block body into the database. -func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { - data, err := rlp.EncodeToBytes(body) - if err != nil { - log.Crit("Failed to RLP encode body", "err", err) - } - WriteBodyRLP(db, hash, number, data) -} - -// DeleteBody removes all block body data associated with a hash. -func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockBodyKey(number, hash)); err != nil { - log.Crit("Failed to delete block body", "err", err) - } -} - -// HasReceipts verifies the existence of all the transaction receipts belonging -// to a block. -func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { - if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. -func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - data, _ := db.Get(blockReceiptsKey(number, hash)) - if len(data) > 0 { - return data - } - return nil -} - -// ReadRawReceipts retrieves all the transaction receipts belonging to a block. -// The receipt metadata fields are not guaranteed to be populated, so they -// should not be used. Use ReadReceipts instead if the metadata is needed. -func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { - // Retrieve the flattened receipt slice - data := ReadReceiptsRLP(db, hash, number) - if len(data) == 0 { - return nil - } - // Convert the receipts from their storage form to their internal representation - storageReceipts := []*types.ReceiptForStorage{} - if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { - log.Error("Invalid receipt array RLP", "hash", hash, "err", err) - return nil - } - receipts := make(types.Receipts, len(storageReceipts)) - for i, storageReceipt := range storageReceipts { - receipts[i] = (*types.Receipt)(storageReceipt) - } - return receipts -} - -// ReadReceipts retrieves all the transaction receipts belonging to a block, including -// its corresponding metadata fields. If it is unable to populate these metadata -// fields then nil is returned. -// -// The current implementation populates these metadata fields by reading the receipts' -// corresponding block body, so if the block body is not found it will return nil even -// if the receipt itself is stored. -func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64, config *params.ChainConfig) types.Receipts { - // We're deriving many fields from the block body, retrieve beside the receipt - receipts := ReadRawReceipts(db, hash, number) - if receipts == nil { - return nil - } - body := ReadBody(db, hash, number) - if body == nil { - log.Error("Missing body but have receipt", "hash", hash, "number", number) - return nil - } - header := ReadHeader(db, hash, number) - - var baseFee *big.Int - if header == nil { - baseFee = big.NewInt(0) - } else { - baseFee = header.BaseFee - } - // Compute effective blob gas price. - var blobGasPrice *big.Int - if header != nil && header.ExcessBlobGas != nil { - blobGasPrice = eip4844.CalcBlobFee(*header.ExcessBlobGas) - } - if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil { - log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) - return nil - } - return receipts -} - -// WriteReceipts stores all the transaction receipts belonging to a block. -func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { - // Convert the receipts into their storage form and serialize them - storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) - for i, receipt := range receipts { - storageReceipts[i] = (*types.ReceiptForStorage)(receipt) - } - bytes, err := rlp.EncodeToBytes(storageReceipts) - if err != nil { - log.Crit("Failed to encode block receipts", "err", err) - } - // Store the flattened receipt slice - if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { - log.Crit("Failed to store block receipts", "err", err) - } -} - -// DeleteReceipts removes all receipt data associated with a block hash. -func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { - log.Crit("Failed to delete block receipts", "err", err) - } -} - -// storedReceiptRLP is the storage encoding of a receipt. -// Re-definition in core/types/receipt.go. -// TODO: Re-use the existing definition. -type storedReceiptRLP struct { - PostStateOrStatus []byte - CumulativeGasUsed uint64 - Logs []*types.Log -} - -// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps -// the list of logs. When decoding a stored receipt into this object we -// avoid creating the bloom filter. -type receiptLogs struct { - Logs []*types.Log -} - -// DecodeRLP implements rlp.Decoder. -func (r *receiptLogs) DecodeRLP(s *rlp.Stream) error { - var stored storedReceiptRLP - if err := s.Decode(&stored); err != nil { - return err - } - r.Logs = stored.Logs - return nil -} - -// DeriveLogFields fills the logs in receiptLogs with information such as block number, txhash, etc. -func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, txs types.Transactions) error { - logIndex := uint(0) - if len(txs) != len(receipts) { - return errors.New("transaction and receipt count mismatch") - } - for i := 0; i < len(receipts); i++ { - txHash := txs[i].Hash() - // The derived log fields can simply be set from the block and transaction - for j := 0; j < len(receipts[i].Logs); j++ { - receipts[i].Logs[j].BlockNumber = number - receipts[i].Logs[j].BlockHash = hash - receipts[i].Logs[j].TxHash = txHash - receipts[i].Logs[j].TxIndex = uint(i) - receipts[i].Logs[j].Index = logIndex - logIndex++ - } - } - return nil -} - -// ReadLogs retrieves the logs for all transactions in a block. In case -// receipts is not found, a nil is returned. -// Note: ReadLogs does not derive unstored log fields. -func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { - // Retrieve the flattened receipt slice - data := ReadReceiptsRLP(db, hash, number) - if len(data) == 0 { - return nil - } - receipts := []*receiptLogs{} - if err := rlp.DecodeBytes(data, &receipts); err != nil { - log.Error("Invalid receipt array RLP", "hash", hash, "err", err) - return nil - } - - logs := make([][]*types.Log, len(receipts)) - for i, receipt := range receipts { - logs[i] = receipt.Logs - } - return logs -} - -// ReadBlock retrieves an entire block corresponding to the hash, assembling it -// back from the stored header and body. If either the header or body could not -// be retrieved nil is returned. -// -// Note, due to concurrent download of header and block body the header and thus -// canonical hash can be stored in the database but the body data not (yet). -func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { - header := ReadHeader(db, hash, number) - if header == nil { - return nil - } - body := ReadBody(db, hash, number) - if body == nil { - return nil - } - return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) -} - -// WriteBlock serializes a block into the database, header and body separately. -func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - WriteHeader(db, block.Header()) -} - -// DeleteBlock removes all block data associated with a hash. -func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - DeleteReceipts(db, hash, number) - DeleteHeader(db, hash, number) - DeleteBody(db, hash, number) -} - -// DeleteBlockWithoutNumber removes all block data associated with a hash, except -// the hash to number mapping. -func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - DeleteReceipts(db, hash, number) - deleteHeaderWithoutNumber(db, hash, number) - DeleteBody(db, hash, number) -} - -// FindCommonAncestor returns the last common ancestor of two block headers -func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { - for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { - a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) - if a == nil { - return nil - } - } - for an := a.Number.Uint64(); an < b.Number.Uint64(); { - b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) - if b == nil { - return nil - } - } - for a.Hash() != b.Hash() { - a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) - if a == nil { - return nil - } - b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) - if b == nil { - return nil - } - } - return a -} - -// ReadHeadBlock returns the current canonical head block. -func ReadHeadBlock(db ethdb.Reader) *types.Block { - headBlockHash := ReadHeadBlockHash(db) - if headBlockHash == (common.Hash{}) { - return nil - } - headBlockNumber := ReadHeaderNumber(db, headBlockHash) - if headBlockNumber == nil { - return nil - } - return ReadBlock(db, headBlockHash, *headBlockNumber) -} - -// ReadTxIndexTail retrieves the number of oldest indexed block -// whose transaction indices has been indexed. -func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 { - data, _ := db.Get(txIndexTailKey) - if len(data) != 8 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteTxIndexTail stores the number of oldest indexed block -// into database. -func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { - log.Crit("Failed to store the transaction index tail", "err", err) - } -} diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go deleted file mode 100644 index 0e151a091e..0000000000 --- a/core/rawdb/accessors_chain_test.go +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "encoding/hex" - "fmt" - "math/big" - "os" - "reflect" - "testing" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/params" - "golang.org/x/crypto/sha3" -) - -// Tests block header storage and retrieval operations. -func TestHeaderStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test header to move around the database and make sure it's really new - header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")} - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { - t.Fatalf("Non existent header returned: %v", entry) - } - // Write and verify the header in the database - WriteHeader(db, header) - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil { - t.Fatalf("Stored header not found") - } else if entry.Hash() != header.Hash() { - t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header) - } - if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil { - t.Fatalf("Stored header RLP not found") - } else { - hasher := sha3.NewLegacyKeccak256() - hasher.Write(entry) - - if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() { - t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header) - } - } - // Delete the header and verify the execution - DeleteHeader(db, header.Hash(), header.Number.Uint64()) - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { - t.Fatalf("Deleted header returned: %v", entry) - } -} - -// Tests block body storage and retrieval operations. -func TestBodyStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test body to move around the database and make sure it's really new - body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}} - - hasher := sha3.NewLegacyKeccak256() - rlp.Encode(hasher, body) - hash := common.BytesToHash(hasher.Sum(nil)) - - if entry := ReadBody(db, hash, 0); entry != nil { - t.Fatalf("Non existent body returned: %v", entry) - } - // Write and verify the body in the database - WriteBody(db, hash, 0, body) - if entry := ReadBody(db, hash, 0); entry == nil { - t.Fatalf("Stored body not found") - } else if types.DeriveSha(types.Transactions(entry.Transactions), newTestHasher()) != types.DeriveSha(types.Transactions(body.Transactions), newTestHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) { - t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body) - } - if entry := ReadBodyRLP(db, hash, 0); entry == nil { - t.Fatalf("Stored body RLP not found") - } else { - hasher := sha3.NewLegacyKeccak256() - hasher.Write(entry) - - if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash { - t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body) - } - } - // Delete the body and verify the execution - DeleteBody(db, hash, 0) - if entry := ReadBody(db, hash, 0); entry != nil { - t.Fatalf("Deleted body returned: %v", entry) - } -} - -// Tests block storage and retrieval operations. -func TestBlockStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test block to move around the database and make sure it's really new - block := types.NewBlockWithHeader(&types.Header{ - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent header returned: %v", entry) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent body returned: %v", entry) - } - // Write and verify the block in the database - WriteBlock(db, block) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored block not found") - } else if entry.Hash() != block.Hash() { - t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored header not found") - } else if entry.Hash() != block.Header().Hash() { - t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header()) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored body not found") - } else if types.DeriveSha(types.Transactions(entry.Transactions), newTestHasher()) != types.DeriveSha(block.Transactions(), newTestHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) { - t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body()) - } - // Delete the block and verify the execution - DeleteBlock(db, block.Hash(), block.NumberU64()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted block returned: %v", entry) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted header returned: %v", entry) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted body returned: %v", entry) - } -} - -// Tests that partial block contents don't get reassembled into full blocks. -func TestPartialBlockStorage(t *testing.T) { - db := NewMemoryDatabase() - block := types.NewBlockWithHeader(&types.Header{ - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - // Store a header and check that it's not recognized as a block - WriteHeader(db, block.Header()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - DeleteHeader(db, block.Hash(), block.NumberU64()) - - // Store a body and check that it's not recognized as a block - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - DeleteBody(db, block.Hash(), block.NumberU64()) - - // Store a header and a body separately and check reassembly - WriteHeader(db, block.Header()) - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored block not found") - } else if entry.Hash() != block.Hash() { - t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) - } -} - -// Tests that canonical numbers can be mapped to hashes and retrieved. -func TestCanonicalMappingStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test canonical number and assigned hash to move around - hash, number := common.Hash{0: 0xff}, uint64(314) - if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { - t.Fatalf("Non existent canonical mapping returned: %v", entry) - } - // Write and verify the TD in the database - WriteCanonicalHash(db, hash, number) - if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) { - t.Fatalf("Stored canonical mapping not found") - } else if entry != hash { - t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash) - } - // Delete the TD and verify the execution - DeleteCanonicalHash(db, number) - if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { - t.Fatalf("Deleted canonical mapping returned: %v", entry) - } -} - -// Tests that head headers and head blocks can be assigned, individually. -func TestHeadStorage(t *testing.T) { - db := NewMemoryDatabase() - - blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")}) - blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")}) - - // Check that no head entries are in a pristine database - if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) { - t.Fatalf("Non head header entry returned: %v", entry) - } - if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) { - t.Fatalf("Non head block entry returned: %v", entry) - } - // Assign separate entries for the head header and block - WriteHeadHeaderHash(db, blockHead.Hash()) - WriteHeadBlockHash(db, blockFull.Hash()) - - // Check that both heads are present, and different (i.e. two heads maintained) - if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() { - t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash()) - } - if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() { - t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash()) - } -} - -// Tests that receipts associated with a single block can be stored and retrieved. -func TestBlockReceiptStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a live block since we need metadata to reconstruct the receipt - tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) - tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil) - - body := &types.Body{Transactions: types.Transactions{tx1, tx2}} - - // Create the two receipts to manage afterwards - receipt1 := &types.Receipt{ - Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, - } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) - - receipt2 := &types.Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 2, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, - } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) - receipts := []*types.Receipt{receipt1, receipt2} - - // Check that no receipt entries are in a pristine database - header := &types.Header{Number: big.NewInt(0), Extra: []byte("test header")} - hash := header.Hash() - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("non existent receipts returned: %v", rs) - } - // Insert the body that corresponds to the receipts - WriteHeader(db, header) - WriteBody(db, hash, 0, body) - if header := ReadHeader(db, hash, 0); header == nil { - t.Fatal("header is nil") - } - - // Insert the receipt slice into the database and check presence - WriteReceipts(db, hash, 0, receipts) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 { - t.Fatal("no receipts returned") - } else { - if err := checkReceiptsRLP(rs, receipts); err != nil { - t.Fatal(err) - } - } - // Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed) - DeleteHeader(db, hash, 0) - DeleteBody(db, hash, 0) - if header := ReadHeader(db, hash, 0); header != nil { - t.Fatal("header is not nil") - } - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); rs != nil { - t.Fatalf("receipts returned when body was deleted: %v", rs) - } - // Ensure that receipts without metadata can be returned without the block body too - if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil { - t.Fatal(err) - } - // Sanity check that body and header alone without the receipt is a full purge - WriteHeader(db, header) - WriteBody(db, hash, 0, body) - - DeleteReceipts(db, hash, 0) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("deleted receipts returned: %v", rs) - } -} - -func checkReceiptsRLP(have, want types.Receipts) error { - if len(have) != len(want) { - return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want)) - } - for i := 0; i < len(want); i++ { - rlpHave, err := rlp.EncodeToBytes(have[i]) - if err != nil { - return err - } - rlpWant, err := rlp.EncodeToBytes(want[i]) - if err != nil { - return err - } - if !bytes.Equal(rlpHave, rlpWant) { - return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant)) - } - } - return nil -} - -func TestCanonicalHashIteration(t *testing.T) { - var cases = []struct { - from, to uint64 - limit int - expect []uint64 - }{ - {1, 8, 0, nil}, - {1, 8, 1, []uint64{1}}, - {1, 8, 10, []uint64{1, 2, 3, 4, 5, 6, 7}}, - {1, 9, 10, []uint64{1, 2, 3, 4, 5, 6, 7, 8}}, - {2, 9, 10, []uint64{2, 3, 4, 5, 6, 7, 8}}, - {9, 10, 10, nil}, - } - // Test empty db iteration - db := NewMemoryDatabase() - numbers, _ := ReadAllCanonicalHashes(db, 0, 10, 10) - if len(numbers) != 0 { - t.Fatalf("No entry should be returned to iterate an empty db") - } - // Fill database with testing data. - for i := uint64(1); i <= 8; i++ { - WriteCanonicalHash(db, common.Hash{}, i) - } - for i, c := range cases { - numbers, _ := ReadAllCanonicalHashes(db, c.from, c.to, c.limit) - if !reflect.DeepEqual(numbers, c.expect) { - t.Fatalf("Case %d failed, want %v, got %v", i, c.expect, numbers) - } - } -} - -func TestHashesInRange(t *testing.T) { - mkHeader := func(number, seq int) *types.Header { - h := types.Header{ - Difficulty: new(big.Int), - Number: big.NewInt(int64(number)), - GasLimit: uint64(seq), - } - return &h - } - db := NewMemoryDatabase() - // For each number, write N versions of that particular number - total := 0 - for i := 0; i < 15; i++ { - for ii := 0; ii < i; ii++ { - WriteHeader(db, mkHeader(i, ii)) - total++ - } - } - if have, want := len(ReadAllHashesInRange(db, 10, 10)), 10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 10, 9)), 0; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 0, 100)), total; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 9, 10)), 9+10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 10)), 10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 16)), 0; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 1)), 1; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } -} - -type fullLogRLP struct { - Address common.Address - Topics []common.Hash - Data []byte - BlockNumber uint64 - TxHash common.Hash - TxIndex uint - BlockHash common.Hash - Index uint -} - -func newFullLogRLP(l *types.Log) *fullLogRLP { - return &fullLogRLP{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: l.BlockNumber, - TxHash: l.TxHash, - TxIndex: l.TxIndex, - BlockHash: l.BlockHash, - Index: l.Index, - } -} - -// Tests that logs associated with a single block can be retrieved. -func TestReadLogs(t *testing.T) { - db := NewMemoryDatabase() - - // Create a live block since we need metadata to reconstruct the receipt - tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) - tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil) - - body := &types.Body{Transactions: types.Transactions{tx1, tx2}} - - // Create the two receipts to manage afterwards - receipt1 := &types.Receipt{ - Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, - } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) - - receipt2 := &types.Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 2, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, - } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) - receipts := []*types.Receipt{receipt1, receipt2} - - hash := common.BytesToHash([]byte{0x03, 0x14}) - // Check that no receipt entries are in a pristine database - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("non existent receipts returned: %v", rs) - } - // Insert the body that corresponds to the receipts - WriteBody(db, hash, 0, body) - - // Insert the receipt slice into the database and check presence - WriteReceipts(db, hash, 0, receipts) - - logs := ReadLogs(db, hash, 0) - if len(logs) == 0 { - t.Fatalf("no logs returned") - } - if have, want := len(logs), 2; have != want { - t.Fatalf("unexpected number of logs returned, have %d want %d", have, want) - } - if have, want := len(logs[0]), 2; have != want { - t.Fatalf("unexpected number of logs[0] returned, have %d want %d", have, want) - } - if have, want := len(logs[1]), 2; have != want { - t.Fatalf("unexpected number of logs[1] returned, have %d want %d", have, want) - } - - for i, pr := range receipts { - for j, pl := range pr.Logs { - rlpHave, err := rlp.EncodeToBytes(newFullLogRLP(logs[i][j])) - if err != nil { - t.Fatal(err) - } - rlpWant, err := rlp.EncodeToBytes(newFullLogRLP(pl)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(rlpHave, rlpWant) { - t.Fatalf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant)) - } - } - } -} - -func TestDeriveLogFields(t *testing.T) { - // Create a few transactions to have receipts for - to2 := common.HexToAddress("0x2") - to3 := common.HexToAddress("0x3") - txs := types.Transactions{ - types.NewTx(&types.LegacyTx{ - Nonce: 1, - Value: big.NewInt(1), - Gas: 1, - GasPrice: big.NewInt(1), - }), - types.NewTx(&types.LegacyTx{ - To: &to2, - Nonce: 2, - Value: big.NewInt(2), - Gas: 2, - GasPrice: big.NewInt(2), - }), - types.NewTx(&types.AccessListTx{ - To: &to3, - Nonce: 3, - Value: big.NewInt(3), - Gas: 3, - GasPrice: big.NewInt(3), - }), - } - // Create the corresponding receipts - receipts := []*receiptLogs{ - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - }, - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - }, - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x33})}, - {Address: common.BytesToAddress([]byte{0x03, 0x33})}, - }, - }, - } - - // Derive log metadata fields - number := big.NewInt(1) - hash := common.BytesToHash([]byte{0x03, 0x14}) - if err := deriveLogFields(receipts, hash, number.Uint64(), txs); err != nil { - t.Fatal(err) - } - - // Iterate over all the computed fields and check that they're correct - logIndex := uint(0) - for i := range receipts { - for j := range receipts[i].Logs { - if receipts[i].Logs[j].BlockNumber != number.Uint64() { - t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64()) - } - if receipts[i].Logs[j].BlockHash != hash { - t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String()) - } - if receipts[i].Logs[j].TxHash != txs[i].Hash() { - t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) - } - if receipts[i].Logs[j].TxIndex != uint(i) { - t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i) - } - if receipts[i].Logs[j].Index != logIndex { - t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex) - } - logIndex++ - } - } -} - -func BenchmarkDecodeRLPLogs(b *testing.B) { - // Encoded receipts from block 0x14ee094309fbe8f70b65f45ebcc08fb33f126942d97464aad5eb91cfd1e2d269 - buf, err := os.ReadFile("testdata/stored_receipts.bin") - if err != nil { - b.Fatal(err) - } - b.Run("ReceiptForStorage", func(b *testing.B) { - b.ReportAllocs() - var r []*types.ReceiptForStorage - for i := 0; i < b.N; i++ { - if err := rlp.DecodeBytes(buf, &r); err != nil { - b.Fatal(err) - } - } - }) - b.Run("rlpLogs", func(b *testing.B) { - b.ReportAllocs() - var r []*receiptLogs - for i := 0; i < b.N; i++ { - if err := rlp.DecodeBytes(buf, &r); err != nil { - b.Fatal(err) - } - } - }) -} diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go deleted file mode 100644 index 3a883f6667..0000000000 --- a/core/rawdb/accessors_indexes.go +++ /dev/null @@ -1,191 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "math/big" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/params" -) - -// ReadTxLookupEntry retrieves the positional metadata associated with a transaction -// hash to allow retrieving the transaction or receipt by hash. -func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 { - data, _ := db.Get(txLookupKey(hash)) - if len(data) == 0 { - return nil - } - // Database v6 tx lookup just stores the block number - if len(data) < common.HashLength { - number := new(big.Int).SetBytes(data).Uint64() - return &number - } - // Database v4-v5 tx lookup format just stores the hash - if len(data) == common.HashLength { - return ReadHeaderNumber(db, common.BytesToHash(data)) - } - // Finally try database v3 tx lookup format - var entry LegacyTxLookupEntry - if err := rlp.DecodeBytes(data, &entry); err != nil { - log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) - return nil - } - return &entry.BlockIndex -} - -// writeTxLookupEntry stores a positional metadata for a transaction, -// enabling hash based transaction and receipt lookups. -func writeTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash, numberBytes []byte) { - if err := db.Put(txLookupKey(hash), numberBytes); err != nil { - log.Crit("Failed to store transaction lookup entry", "err", err) - } -} - -// WriteTxLookupEntries is identical to WriteTxLookupEntry, but it works on -// a list of hashes -func WriteTxLookupEntries(db ethdb.KeyValueWriter, number uint64, hashes []common.Hash) { - numberBytes := new(big.Int).SetUint64(number).Bytes() - for _, hash := range hashes { - writeTxLookupEntry(db, hash, numberBytes) - } -} - -// WriteTxLookupEntriesByBlock stores a positional metadata for every transaction from -// a block, enabling hash based transaction and receipt lookups. -func WriteTxLookupEntriesByBlock(db ethdb.KeyValueWriter, block *types.Block) { - numberBytes := block.Number().Bytes() - for _, tx := range block.Transactions() { - writeTxLookupEntry(db, tx.Hash(), numberBytes) - } -} - -// DeleteTxLookupEntry removes all transaction data associated with a hash. -func DeleteTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(txLookupKey(hash)); err != nil { - log.Crit("Failed to delete transaction lookup entry", "err", err) - } -} - -// DeleteTxLookupEntries removes all transaction lookups for a given block. -func DeleteTxLookupEntries(db ethdb.KeyValueWriter, hashes []common.Hash) { - for _, hash := range hashes { - DeleteTxLookupEntry(db, hash) - } -} - -// ReadTransaction retrieves a specific transaction from the database, along with -// its added positional metadata. -func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { - blockNumber := ReadTxLookupEntry(db, hash) - if blockNumber == nil { - return nil, common.Hash{}, 0, 0 - } - blockHash := ReadCanonicalHash(db, *blockNumber) - if blockHash == (common.Hash{}) { - return nil, common.Hash{}, 0, 0 - } - body := ReadBody(db, blockHash, *blockNumber) - if body == nil { - log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash) - return nil, common.Hash{}, 0, 0 - } - for txIndex, tx := range body.Transactions { - if tx.Hash() == hash { - return tx, blockHash, *blockNumber, uint64(txIndex) - } - } - log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) - return nil, common.Hash{}, 0, 0 -} - -// ReadReceipt retrieves a specific transaction receipt from the database, along with -// its added positional metadata. -func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { - // Retrieve the context of the receipt based on the transaction hash - blockNumber := ReadTxLookupEntry(db, hash) - if blockNumber == nil { - return nil, common.Hash{}, 0, 0 - } - blockHash := ReadCanonicalHash(db, *blockNumber) - if blockHash == (common.Hash{}) { - return nil, common.Hash{}, 0, 0 - } - blockHeader := ReadHeader(db, blockHash, *blockNumber) - if blockHeader == nil { - return nil, common.Hash{}, 0, 0 - } - // Read all the receipts from the block and return the one with the matching hash - receipts := ReadReceipts(db, blockHash, *blockNumber, blockHeader.Time, config) - for receiptIndex, receipt := range receipts { - if receipt.TxHash == hash { - return receipt, blockHash, *blockNumber, uint64(receiptIndex) - } - } - log.Error("Receipt not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) - return nil, common.Hash{}, 0, 0 -} - -// ReadBloomBits retrieves the compressed bloom bit vector belonging to the given -// section and bit index from the. -func ReadBloomBits(db ethdb.KeyValueReader, bit uint, section uint64, head common.Hash) ([]byte, error) { - return db.Get(bloomBitsKey(bit, section, head)) -} - -// WriteBloomBits stores the compressed bloom bits vector belonging to the given -// section and bit index. -func WriteBloomBits(db ethdb.KeyValueWriter, bit uint, section uint64, head common.Hash, bits []byte) { - if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { - log.Crit("Failed to store bloom bits", "err", err) - } -} - -// DeleteBloombits removes all compressed bloom bits vector belonging to the -// given section range and bit index. -func DeleteBloombits(db ethdb.Database, bit uint, from uint64, to uint64) { - start, end := bloomBitsKey(bit, from, common.Hash{}), bloomBitsKey(bit, to, common.Hash{}) - it := db.NewIterator(nil, start) - defer it.Release() - - for it.Next() { - if bytes.Compare(it.Key(), end) >= 0 { - break - } - if len(it.Key()) != len(bloomBitsPrefix)+2+8+32 { - continue - } - db.Delete(it.Key()) - } - if it.Error() != nil { - log.Crit("Failed to delete bloom bits", "err", it.Error()) - } -} diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go deleted file mode 100644 index 666c8e32b5..0000000000 --- a/core/rawdb/accessors_indexes_test.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "math/big" - "testing" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/internal/blocktest" -) - -var newTestHasher = blocktest.NewHasher - -// Tests that positional lookup metadata can be stored and retrieved. -func TestLookupStorage(t *testing.T) { - tests := []struct { - name string - writeTxLookupEntriesByBlock func(ethdb.Writer, *types.Block) - }{ - { - "DatabaseV6", - func(db ethdb.Writer, block *types.Block) { - WriteTxLookupEntriesByBlock(db, block) - }, - }, - { - "DatabaseV4-V5", - func(db ethdb.Writer, block *types.Block) { - for _, tx := range block.Transactions() { - db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()) - } - }, - }, - { - "DatabaseV3", - func(db ethdb.Writer, block *types.Block) { - for index, tx := range block.Transactions() { - entry := LegacyTxLookupEntry{ - BlockHash: block.Hash(), - BlockIndex: block.NumberU64(), - Index: uint64(index), - } - data, _ := rlp.EncodeToBytes(entry) - db.Put(txLookupKey(tx.Hash()), data) - } - }, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - db := NewMemoryDatabase() - - tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) - tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) - tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) - txs := []*types.Transaction{tx1, tx2, tx3} - - block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, newTestHasher()) - - // Check that no transactions entries are in a pristine database - for i, tx := range txs { - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { - t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) - } - } - // Insert all the transactions into the database, and verify contents - WriteCanonicalHash(db, block.Hash(), block.NumberU64()) - WriteBlock(db, block) - tc.writeTxLookupEntriesByBlock(db, block) - - for i, tx := range txs { - if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { - t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) - } else { - if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { - t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) - } - if tx.Hash() != txn.Hash() { - t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) - } - } - } - // Delete the transactions and check purge - for i, tx := range txs { - DeleteTxLookupEntry(db, tx.Hash()) - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { - t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) - } - } - }) - } -} - -func TestDeleteBloomBits(t *testing.T) { - // Prepare testing data - db := NewMemoryDatabase() - - genesisHash0 := common.BytesToHash([]byte{1, 2, 3, 4, 5}) - genesisHash1 := common.BytesToHash([]byte{5, 4, 3, 2, 1}) - for i := uint(0); i < 2; i++ { - for s := uint64(0); s < 2; s++ { - WriteBloomBits(db, i, s, genesisHash0, []byte{0x01, 0x02}) - WriteBloomBits(db, i, s, genesisHash1, []byte{0x01, 0x02}) - } - } - check := func(bit uint, section uint64, head common.Hash, exist bool) { - bits, _ := ReadBloomBits(db, bit, section, head) - if exist && !bytes.Equal(bits, []byte{0x01, 0x02}) { - t.Fatalf("Bloombits mismatch") - } - if !exist && len(bits) > 0 { - t.Fatalf("Bloombits should be removed") - } - } - // Check the existence of written data. - check(0, 0, genesisHash0, true) - check(0, 0, genesisHash1, true) - - // Check the existence of deleted data. - DeleteBloombits(db, 0, 0, 1) - check(0, 0, genesisHash0, false) - check(0, 0, genesisHash1, false) - check(0, 1, genesisHash0, true) - check(0, 1, genesisHash1, true) - - // Check the existence of deleted data. - DeleteBloombits(db, 0, 0, 2) - check(0, 0, genesisHash0, false) - check(0, 0, genesisHash1, false) - check(0, 1, genesisHash0, false) - check(0, 1, genesisHash1, false) - - // Bit1 shouldn't be affect. - check(1, 0, genesisHash0, true) - check(1, 0, genesisHash1, true) - check(1, 1, genesisHash0, true) - check(1, 1, genesisHash1, true) -} diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go deleted file mode 100644 index 23861cc1a6..0000000000 --- a/core/rawdb/accessors_metadata.go +++ /dev/null @@ -1,298 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "encoding/json" - "time" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/params" -) - -// ReadDatabaseVersion retrieves the version number of the database. -func ReadDatabaseVersion(db ethdb.KeyValueReader) *uint64 { - var version uint64 - - enc, _ := db.Get(databaseVersionKey) - if len(enc) == 0 { - return nil - } - if err := rlp.DecodeBytes(enc, &version); err != nil { - return nil - } - - return &version -} - -// WriteDatabaseVersion stores the version number of the database -func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) { - enc, err := rlp.EncodeToBytes(version) - if err != nil { - log.Crit("Failed to encode database version", "err", err) - } - if err = db.Put(databaseVersionKey, enc); err != nil { - log.Crit("Failed to store the database version", "err", err) - } -} - -// ReadChainConfig retrieves the consensus settings based on the given genesis hash. -func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) *params.ChainConfig { - data, _ := db.Get(configKey(hash)) - if len(data) == 0 { - return nil - } - var config params.ChainConfig - if err := json.Unmarshal(data, &config); err != nil { - log.Error("Invalid chain config JSON", "hash", hash, "err", err) - return nil - } - - // Read the upgrade config for this chain config - data, _ = db.Get(upgradeConfigKey(hash)) - if len(data) == 0 { - return &config // return early if no upgrade config is found - } - if err := json.Unmarshal(data, ¶ms.GetExtra(&config).UpgradeConfig); err != nil { - log.Error("Invalid upgrade config JSON", "err", err) - return nil - } - - return &config -} - -// WriteChainConfig writes the chain config settings to the database. -func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.ChainConfig) { - if cfg == nil { - return - } - data, err := json.Marshal(cfg) - if err != nil { - log.Crit("Failed to JSON encode chain config", "err", err) - } - if err := db.Put(configKey(hash), data); err != nil { - log.Crit("Failed to store chain config", "err", err) - } - - // Write the upgrade config for this chain config - data, err = json.Marshal(params.GetExtra(cfg).UpgradeConfig) - if err != nil { - log.Crit("Failed to JSON encode upgrade config", "err", err) - } - if err := db.Put(upgradeConfigKey(hash), data); err != nil { - log.Crit("Failed to store upgrade config", "err", err) - } -} - -// crashList is a list of unclean-shutdown-markers, for rlp-encoding to the -// database -type crashList struct { - Discarded uint64 // how many ucs have we deleted - Recent []uint64 // unix timestamps of 10 latest unclean shutdowns -} - -const crashesToKeep = 10 - -// PushUncleanShutdownMarker appends a new unclean shutdown marker and returns -// the previous data -// - a list of timestamps -// - a count of how many old unclean-shutdowns have been discarded -func PushUncleanShutdownMarker(db ethdb.KeyValueStore) ([]uint64, uint64, error) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err == nil { - if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - return nil, 0, err - } - } - var discarded = uncleanShutdowns.Discarded - var previous = make([]uint64, len(uncleanShutdowns.Recent)) - copy(previous, uncleanShutdowns.Recent) - // Add a new (but cap it) - uncleanShutdowns.Recent = append(uncleanShutdowns.Recent, uint64(time.Now().Unix())) - if count := len(uncleanShutdowns.Recent); count > crashesToKeep+1 { - numDel := count - (crashesToKeep + 1) - uncleanShutdowns.Recent = uncleanShutdowns.Recent[numDel:] - uncleanShutdowns.Discarded += uint64(numDel) - } - // And save it again - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to write unclean-shutdown marker", "err", err) - return nil, 0, err - } - return previous, discarded, nil -} - -// PopUncleanShutdownMarker removes the last unclean shutdown marker -func PopUncleanShutdownMarker(db ethdb.KeyValueStore) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err != nil { - log.Warn("Error reading unclean shutdown markers", "error", err) - } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - log.Error("Error decoding unclean shutdown markers", "error", err) // Should mos def _not_ happen - } - if l := len(uncleanShutdowns.Recent); l > 0 { - uncleanShutdowns.Recent = uncleanShutdowns.Recent[:l-1] - } - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to clear unclean-shutdown marker", "err", err) - } -} - -// UpdateUncleanShutdownMarker updates the last marker's timestamp to now. -func UpdateUncleanShutdownMarker(db ethdb.KeyValueStore) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err != nil { - log.Warn("Error reading unclean shutdown markers", "error", err) - } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - log.Warn("Error decoding unclean shutdown markers", "error", err) - } - // This shouldn't happen because we push a marker on Backend instantiation - count := len(uncleanShutdowns.Recent) - if count == 0 { - log.Warn("No unclean shutdown marker to update") - return - } - uncleanShutdowns.Recent[count-1] = uint64(time.Now().Unix()) - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to write unclean-shutdown marker", "err", err) - } -} - -// WriteTimeMarker writes a marker of the current time in the db at [key] -func WriteTimeMarker(db ethdb.KeyValueStore, key []byte) error { - data, err := rlp.EncodeToBytes(uint64(time.Now().Unix())) - if err != nil { - return err - } - return db.Put(key, data) -} - -// ReadTimeMarker reads the timestamp stored at [key] -func ReadTimeMarker(db ethdb.KeyValueStore, key []byte) (time.Time, error) { - data, err := db.Get(key) - if err != nil { - return time.Time{}, err - } - - var lastRun uint64 - if err := rlp.DecodeBytes(data, &lastRun); err != nil { - return time.Time{}, err - } - - return time.Unix(int64(lastRun), 0), nil -} - -// DeleteTimeMarker deletes any value stored at [key] -func DeleteTimeMarker(db ethdb.KeyValueStore, key []byte) error { - return db.Delete(key) -} - -// WriteOfflinePruning writes a marker of the last attempt to run offline pruning -// The marker is written when offline pruning completes and is deleted when the node -// is started successfully with offline pruning disabled. This ensures users must -// disable offline pruning and start their node successfully between runs of offline -// pruning. -func WriteOfflinePruning(db ethdb.KeyValueStore) error { - return WriteTimeMarker(db, offlinePruningKey) -} - -// ReadOfflinePruning reads the most recent timestamp of an attempt to run offline -// pruning if present. -func ReadOfflinePruning(db ethdb.KeyValueStore) (time.Time, error) { - return ReadTimeMarker(db, offlinePruningKey) -} - -// DeleteOfflinePruning deletes any marker of the last attempt to run offline pruning. -func DeleteOfflinePruning(db ethdb.KeyValueStore) error { - return DeleteTimeMarker(db, offlinePruningKey) -} - -// WritePopulateMissingTries writes a marker for the current attempt to populate -// missing tries. -func WritePopulateMissingTries(db ethdb.KeyValueStore) error { - return WriteTimeMarker(db, populateMissingTriesKey) -} - -// ReadPopulateMissingTries reads the most recent timestamp of an attempt to -// re-populate missing trie nodes. -func ReadPopulateMissingTries(db ethdb.KeyValueStore) (time.Time, error) { - return ReadTimeMarker(db, populateMissingTriesKey) -} - -// DeletePopulateMissingTries deletes any marker of the last attempt to -// re-populate missing trie nodes. -func DeletePopulateMissingTries(db ethdb.KeyValueStore) error { - return DeleteTimeMarker(db, populateMissingTriesKey) -} - -// WritePruningDisabled writes a marker to track whether the node has ever run -// with pruning disabled. -func WritePruningDisabled(db ethdb.KeyValueStore) error { - return db.Put(pruningDisabledKey, nil) -} - -// HasPruningDisabled returns true if there is a marker present indicating that -// the node has run with pruning disabled at some pooint. -func HasPruningDisabled(db ethdb.KeyValueStore) (bool, error) { - return db.Has(pruningDisabledKey) -} - -// DeletePruningDisabled deletes the marker indicating that the node has -// run with pruning disabled. -func DeletePruningDisabled(db ethdb.KeyValueStore) error { - return db.Delete(pruningDisabledKey) -} - -// WriteAcceptorTip writes [hash] as the last accepted block that has been fully processed. -func WriteAcceptorTip(db ethdb.KeyValueWriter, hash common.Hash) error { - return db.Put(acceptorTipKey, hash[:]) -} - -// ReadAcceptorTip reads the hash of the last accepted block that was fully processed. -// If there is no value present (the index is being initialized for the first time), then the -// empty hash is returned. -func ReadAcceptorTip(db ethdb.KeyValueReader) (common.Hash, error) { - has, err := db.Has(acceptorTipKey) - // If the index is not present on disk, the [acceptorTipKey] index has not been initialized yet. - if !has || err != nil { - return common.Hash{}, err - } - h, err := db.Get(acceptorTipKey) - if err != nil { - return common.Hash{}, err - } - return common.BytesToHash(h), nil -} diff --git a/core/rawdb/accessors_snapshot.go b/core/rawdb/accessors_snapshot.go deleted file mode 100644 index f091b63831..0000000000 --- a/core/rawdb/accessors_snapshot.go +++ /dev/null @@ -1,155 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2019 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" -) - -// ReadSnapshotRoot retrieves the root of the block whose state is contained in -// the persisted snapshot. -func ReadSnapshotRoot(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(snapshotRootKey) - if len(data) != common.HashLength { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteSnapshotRoot stores the root of the block whose state is contained in -// the persisted snapshot. -func WriteSnapshotRoot(db ethdb.KeyValueWriter, root common.Hash) { - if err := db.Put(snapshotRootKey, root[:]); err != nil { - log.Crit("Failed to store snapshot root", "err", err) - } -} - -// DeleteSnapshotRoot deletes the root of the block whose state is contained in -// the persisted snapshot. Since snapshots are not immutable, this method can -// be used during updates, so a crash or failure will mark the entire snapshot -// invalid. -func DeleteSnapshotRoot(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotRootKey); err != nil { - log.Crit("Failed to remove snapshot root", "err", err) - } -} - -// ReadSnapshotBlockHash retrieves the hash of the block whose state is contained in -// the persisted snapshot. -func ReadSnapshotBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(snapshotBlockHashKey) - if len(data) != common.HashLength { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteSnapshotBlockHash stores the root of the block whose state is contained in -// the persisted snapshot. -func WriteSnapshotBlockHash(db ethdb.KeyValueWriter, blockHash common.Hash) { - if err := db.Put(snapshotBlockHashKey, blockHash[:]); err != nil { - log.Crit("Failed to store snapshot block hash", "err", err) - } -} - -// DeleteSnapshotBlockHash deletes the hash of the block whose state is contained in -// the persisted snapshot. Since snapshots are not immutable, this method can -// be used during updates, so a crash or failure will mark the entire snapshot -// invalid. -func DeleteSnapshotBlockHash(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotBlockHashKey); err != nil { - log.Crit("Failed to remove snapshot block hash", "err", err) - } -} - -// ReadAccountSnapshot retrieves the snapshot entry of an account trie leaf. -func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(accountSnapshotKey(hash)) - return data -} - -// WriteAccountSnapshot stores the snapshot entry of an account trie leaf. -func WriteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash, entry []byte) { - if err := db.Put(accountSnapshotKey(hash), entry); err != nil { - log.Crit("Failed to store account snapshot", "err", err) - } -} - -// DeleteAccountSnapshot removes the snapshot entry of an account trie leaf. -func DeleteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(accountSnapshotKey(hash)); err != nil { - log.Crit("Failed to delete account snapshot", "err", err) - } -} - -// ReadStorageSnapshot retrieves the snapshot entry of an storage trie leaf. -func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) []byte { - data, _ := db.Get(storageSnapshotKey(accountHash, storageHash)) - return data -} - -// WriteStorageSnapshot stores the snapshot entry of an storage trie leaf. -func WriteStorageSnapshot(db ethdb.KeyValueWriter, accountHash, storageHash common.Hash, entry []byte) { - if err := db.Put(storageSnapshotKey(accountHash, storageHash), entry); err != nil { - log.Crit("Failed to store storage snapshot", "err", err) - } -} - -// DeleteStorageSnapshot removes the snapshot entry of an storage trie leaf. -func DeleteStorageSnapshot(db ethdb.KeyValueWriter, accountHash, storageHash common.Hash) { - if err := db.Delete(storageSnapshotKey(accountHash, storageHash)); err != nil { - log.Crit("Failed to delete storage snapshot", "err", err) - } -} - -// IterateStorageSnapshots returns an iterator for walking the entire storage -// space of a specific account. -func IterateStorageSnapshots(db ethdb.Iteratee, accountHash common.Hash) ethdb.Iterator { - return NewKeyLengthIterator(db.NewIterator(storageSnapshotsKey(accountHash), nil), len(SnapshotStoragePrefix)+2*common.HashLength) -} - -// IterateAccountSnapshots returns an iterator for walking all of the accounts in the snapshot -func IterateAccountSnapshots(db ethdb.Iteratee) ethdb.Iterator { - return NewKeyLengthIterator(db.NewIterator(SnapshotAccountPrefix, nil), len(SnapshotAccountPrefix)+common.HashLength) -} - -// ReadSnapshotGenerator retrieves the serialized snapshot generator saved at -// the last shutdown. -func ReadSnapshotGenerator(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(snapshotGeneratorKey) - return data -} - -// WriteSnapshotGenerator stores the serialized snapshot generator to save at -// shutdown. -func WriteSnapshotGenerator(db ethdb.KeyValueWriter, generator []byte) { - if err := db.Put(snapshotGeneratorKey, generator); err != nil { - log.Crit("Failed to store snapshot generator", "err", err) - } -} diff --git a/core/rawdb/accessors_state.go b/core/rawdb/accessors_state.go deleted file mode 100644 index e7f509bbb7..0000000000 --- a/core/rawdb/accessors_state.go +++ /dev/null @@ -1,146 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2020 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "encoding/binary" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" -) - -// ReadPreimage retrieves a single preimage of the provided hash. -func ReadPreimage(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(preimageKey(hash)) - return data -} - -// WritePreimages writes the provided set of preimages to the database. -func WritePreimages(db ethdb.KeyValueWriter, preimages map[common.Hash][]byte) { - for hash, preimage := range preimages { - if err := db.Put(preimageKey(hash), preimage); err != nil { - log.Crit("Failed to store trie preimage", "err", err) - } - } - preimageCounter.Inc(int64(len(preimages))) - preimageHitCounter.Inc(int64(len(preimages))) -} - -// ReadCode retrieves the contract code of the provided code hash. -func ReadCode(db ethdb.KeyValueReader, hash common.Hash) []byte { - // Try with the prefixed code scheme first and only. The legacy scheme was never used in subnet-evm. - data, _ := db.Get(codeKey(hash)) - return data -} - -// HasCode checks if the contract code corresponding to the -// provided code hash is present in the db. -func HasCode(db ethdb.KeyValueReader, hash common.Hash) bool { - // Try with the prefixed code scheme first and only. The legacy scheme was never used in subnet-evm. - ok, _ := db.Has(codeKey(hash)) - return ok -} - -// WriteCode writes the provided contract code database. -func WriteCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) { - if err := db.Put(codeKey(hash), code); err != nil { - log.Crit("Failed to store contract code", "err", err) - } -} - -// DeleteCode deletes the specified contract code from the database. -func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(codeKey(hash)); err != nil { - log.Crit("Failed to delete contract code", "err", err) - } -} - -// ReadStateID retrieves the state id with the provided state root. -func ReadStateID(db ethdb.KeyValueReader, root common.Hash) *uint64 { - data, err := db.Get(stateIDKey(root)) - if err != nil || len(data) == 0 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteStateID writes the provided state lookup to database. -func WriteStateID(db ethdb.KeyValueWriter, root common.Hash, id uint64) { - var buff [8]byte - binary.BigEndian.PutUint64(buff[:], id) - if err := db.Put(stateIDKey(root), buff[:]); err != nil { - log.Crit("Failed to store state ID", "err", err) - } -} - -// DeleteStateID deletes the specified state lookup from the database. -func DeleteStateID(db ethdb.KeyValueWriter, root common.Hash) { - if err := db.Delete(stateIDKey(root)); err != nil { - log.Crit("Failed to delete state ID", "err", err) - } -} - -// ReadPersistentStateID retrieves the id of the persistent state from the database. -func ReadPersistentStateID(db ethdb.KeyValueReader) uint64 { - data, _ := db.Get(persistentStateIDKey) - if len(data) != 8 { - return 0 - } - return binary.BigEndian.Uint64(data) -} - -// WritePersistentStateID stores the id of the persistent state into database. -func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(persistentStateIDKey, encodeBlockNumber(number)); err != nil { - log.Crit("Failed to store the persistent state ID", "err", err) - } -} - -// ReadTrieJournal retrieves the serialized in-memory trie nodes of layers saved at -// the last shutdown. -func ReadTrieJournal(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(trieJournalKey) - return data -} - -// WriteTrieJournal stores the serialized in-memory trie nodes of layers to save at -// shutdown. -func WriteTrieJournal(db ethdb.KeyValueWriter, journal []byte) { - if err := db.Put(trieJournalKey, journal); err != nil { - log.Crit("Failed to store tries journal", "err", err) - } -} - -// DeleteTrieJournal deletes the serialized in-memory trie nodes of layers saved at -// the last shutdown. -func DeleteTrieJournal(db ethdb.KeyValueWriter) { - if err := db.Delete(trieJournalKey); err != nil { - log.Crit("Failed to remove tries journal", "err", err) - } -} diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go deleted file mode 100644 index 742a462c7c..0000000000 --- a/core/rawdb/accessors_trie.go +++ /dev/null @@ -1,357 +0,0 @@ -// (c) 2023, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2022 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see - -package rawdb - -import ( - "fmt" - "sync" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" - "golang.org/x/crypto/sha3" -) - -// HashScheme is the legacy hash-based state scheme with which trie nodes are -// stored in the disk with node hash as the database key. The advantage of this -// scheme is that different versions of trie nodes can be stored in disk, which -// is very beneficial for constructing archive nodes. The drawback is it will -// store different trie nodes on the same path to different locations on the disk -// with no data locality, and it's unfriendly for designing state pruning. -// -// Now this scheme is still kept for backward compatibility, and it will be used -// for archive node and some other tries(e.g. light trie). -const HashScheme = "hash" - -// PathScheme is the new path-based state scheme with which trie nodes are stored -// in the disk with node path as the database key. This scheme will only store one -// version of state data in the disk, which means that the state pruning operation -// is native. At the same time, this scheme will put adjacent trie nodes in the same -// area of the disk with good data locality property. But this scheme needs to rely -// on extra state diffs to survive deep reorg. -const PathScheme = "path" - -// hasher is used to compute the sha256 hash of the provided data. -type hasher struct{ sha crypto.KeccakState } - -var hasherPool = sync.Pool{ - New: func() interface{} { return &hasher{sha: sha3.NewLegacyKeccak256().(crypto.KeccakState)} }, -} - -func newHasher() *hasher { - return hasherPool.Get().(*hasher) -} - -func (h *hasher) hash(data []byte) common.Hash { - return crypto.HashData(h.sha, data) -} - -func (h *hasher) release() { - hasherPool.Put(h) -} - -// ReadAccountTrieNode retrieves the account trie node and the associated node -// hash with the specified node path. -func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) ([]byte, common.Hash) { - data, err := db.Get(accountTrieNodeKey(path)) - if err != nil { - return nil, common.Hash{} - } - h := newHasher() - defer h.release() - return data, h.hash(data) -} - -// HasAccountTrieNode checks the account trie node presence with the specified -// node path and the associated node hash. -func HasAccountTrieNode(db ethdb.KeyValueReader, path []byte, hash common.Hash) bool { - data, err := db.Get(accountTrieNodeKey(path)) - if err != nil { - return false - } - h := newHasher() - defer h.release() - return h.hash(data) == hash -} - -// ExistsAccountTrieNode checks the presence of the account trie node with the -// specified node path, regardless of the node hash. -func ExistsAccountTrieNode(db ethdb.KeyValueReader, path []byte) bool { - has, err := db.Has(accountTrieNodeKey(path)) - if err != nil { - return false - } - return has -} - -// WriteAccountTrieNode writes the provided account trie node into database. -func WriteAccountTrieNode(db ethdb.KeyValueWriter, path []byte, node []byte) { - if err := db.Put(accountTrieNodeKey(path), node); err != nil { - log.Crit("Failed to store account trie node", "err", err) - } -} - -// DeleteAccountTrieNode deletes the specified account trie node from the database. -func DeleteAccountTrieNode(db ethdb.KeyValueWriter, path []byte) { - if err := db.Delete(accountTrieNodeKey(path)); err != nil { - log.Crit("Failed to delete account trie node", "err", err) - } -} - -// ReadStorageTrieNode retrieves the storage trie node and the associated node -// hash with the specified node path. -func ReadStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) ([]byte, common.Hash) { - data, err := db.Get(storageTrieNodeKey(accountHash, path)) - if err != nil { - return nil, common.Hash{} - } - h := newHasher() - defer h.release() - return data, h.hash(data) -} - -// HasStorageTrieNode checks the storage trie node presence with the provided -// node path and the associated node hash. -func HasStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte, hash common.Hash) bool { - data, err := db.Get(storageTrieNodeKey(accountHash, path)) - if err != nil { - return false - } - h := newHasher() - defer h.release() - return h.hash(data) == hash -} - -// ExistsStorageTrieNode checks the presence of the storage trie node with the -// specified account hash and node path, regardless of the node hash. -func ExistsStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) bool { - has, err := db.Has(storageTrieNodeKey(accountHash, path)) - if err != nil { - return false - } - return has -} - -// WriteStorageTrieNode writes the provided storage trie node into database. -func WriteStorageTrieNode(db ethdb.KeyValueWriter, accountHash common.Hash, path []byte, node []byte) { - if err := db.Put(storageTrieNodeKey(accountHash, path), node); err != nil { - log.Crit("Failed to store storage trie node", "err", err) - } -} - -// DeleteStorageTrieNode deletes the specified storage trie node from the database. -func DeleteStorageTrieNode(db ethdb.KeyValueWriter, accountHash common.Hash, path []byte) { - if err := db.Delete(storageTrieNodeKey(accountHash, path)); err != nil { - log.Crit("Failed to delete storage trie node", "err", err) - } -} - -// ReadLegacyTrieNode retrieves the legacy trie node with the given -// associated node hash. -func ReadLegacyTrieNode(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, err := db.Get(hash.Bytes()) - if err != nil { - return nil - } - return data -} - -// HasLegacyTrieNode checks if the trie node with the provided hash is present in db. -func HasLegacyTrieNode(db ethdb.KeyValueReader, hash common.Hash) bool { - ok, _ := db.Has(hash.Bytes()) - return ok -} - -// WriteLegacyTrieNode writes the provided legacy trie node to database. -func WriteLegacyTrieNode(db ethdb.KeyValueWriter, hash common.Hash, node []byte) { - if err := db.Put(hash.Bytes(), node); err != nil { - log.Crit("Failed to store legacy trie node", "err", err) - } -} - -// DeleteLegacyTrieNode deletes the specified legacy trie node from database. -func DeleteLegacyTrieNode(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(hash.Bytes()); err != nil { - log.Crit("Failed to delete legacy trie node", "err", err) - } -} - -// HasTrieNode checks the trie node presence with the provided node info and -// the associated node hash. -func HasTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash common.Hash, scheme string) bool { - switch scheme { - case HashScheme: - return HasLegacyTrieNode(db, hash) - case PathScheme: - if owner == (common.Hash{}) { - return HasAccountTrieNode(db, path, hash) - } - return HasStorageTrieNode(db, owner, path, hash) - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// ReadTrieNode retrieves the trie node from database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func ReadTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash common.Hash, scheme string) []byte { - switch scheme { - case HashScheme: - return ReadLegacyTrieNode(db, hash) - case PathScheme: - var ( - blob []byte - nHash common.Hash - ) - if owner == (common.Hash{}) { - blob, nHash = ReadAccountTrieNode(db, path) - } else { - blob, nHash = ReadStorageTrieNode(db, owner, path) - } - if nHash != hash { - return nil - } - return blob - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// WriteTrieNode writes the trie node into database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func WriteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, hash common.Hash, node []byte, scheme string) { - switch scheme { - case HashScheme: - WriteLegacyTrieNode(db, hash, node) - case PathScheme: - if owner == (common.Hash{}) { - WriteAccountTrieNode(db, path, node) - } else { - WriteStorageTrieNode(db, owner, path, node) - } - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// DeleteTrieNode deletes the trie node from database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, hash common.Hash, scheme string) { - switch scheme { - case HashScheme: - DeleteLegacyTrieNode(db, hash) - case PathScheme: - if owner == (common.Hash{}) { - DeleteAccountTrieNode(db, path) - } else { - DeleteStorageTrieNode(db, owner, path) - } - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// ReadStateScheme reads the state scheme of persistent state, or none -// if the state is not present in database. -func ReadStateScheme(db ethdb.Reader) string { - // Check if state in path-based scheme is present - blob, _ := ReadAccountTrieNode(db, nil) - if len(blob) != 0 { - return PathScheme - } - // The root node might be deleted during the initial snap sync, check - // the persistent state id then. - if id := ReadPersistentStateID(db); id != 0 { - return PathScheme - } - // In a hash-based scheme, the genesis state is consistently stored - // on the disk. To assess the scheme of the persistent state, it - // suffices to inspect the scheme of the genesis state. - header := ReadHeader(db, ReadCanonicalHash(db, 0), 0) - if header == nil { - return "" // empty datadir - } - blob = ReadLegacyTrieNode(db, header.Root) - if len(blob) == 0 { - return "" // no state in disk - } - return HashScheme -} - -// ParseStateScheme checks if the specified state scheme is compatible with -// the stored state. -// -// - If the provided scheme is none, use the scheme consistent with persistent -// state, or fallback to hash-based scheme if state is empty. -// -// - If the provided scheme is hash, use hash-based scheme or error out if not -// compatible with persistent state scheme. -// -// - If the provided scheme is path: use path-based scheme or error out if not -// compatible with persistent state scheme. -func ParseStateScheme(provided string, disk ethdb.Database) (string, error) { - // If state scheme is not specified, use the scheme consistent - // with persistent state, or fallback to hash mode if database - // is empty. - stored := ReadStateScheme(disk) - if provided == "" { - if stored == "" { - // use default scheme for empty database, flip it when - // path mode is chosen as default - log.Info("State schema set to default", "scheme", "hash") - return HashScheme, nil - } - log.Info("State scheme set to already existing", "scheme", stored) - return stored, nil // reuse scheme of persistent scheme - } - // If state scheme is specified, ensure it's compatible with - // persistent state. - if stored == "" || provided == stored { - log.Info("State scheme set by user", "scheme", provided) - return provided, nil - } - return "", fmt.Errorf("incompatible state scheme, stored: %s, provided: %s", stored, provided) -} diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go deleted file mode 100644 index ede3c71e38..0000000000 --- a/core/rawdb/chain_iterator.go +++ /dev/null @@ -1,320 +0,0 @@ -// (c) 2019-2022, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2020 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "runtime" - "sync/atomic" - "time" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/prque" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/log" - "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" -) - -type blockTxHashes struct { - number uint64 - hashes []common.Hash -} - -// iterateTransactions iterates over all transactions in the (canon) block -// number(s) given, and yields the hashes on a channel. If there is a signal -// received from interrupt channel, the iteration will be aborted and result -// channel will be closed. -// Iterates blocks in the range [from, to) -func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool, interrupt chan struct{}) chan *blockTxHashes { - // One thread sequentially reads data from db - type numberRlp struct { - number uint64 - rlp rlp.RawValue - } - if to == from { - return nil - } - threads := to - from - if cpus := runtime.NumCPU(); threads > uint64(cpus) { - threads = uint64(cpus) - } - var ( - rlpCh = make(chan *numberRlp, threads*2) // we send raw rlp over this channel - hashesCh = make(chan *blockTxHashes, threads*2) // send hashes over hashesCh - ) - // lookup runs in one instance - lookup := func() { - n, end := from, to - if reverse { - n, end = to-1, from-1 - } - defer close(rlpCh) - for n != end { - data := ReadCanonicalBodyRLP(db, n) - // Feed the block to the aggregator, or abort on interrupt - select { - case rlpCh <- &numberRlp{n, data}: - case <-interrupt: - return - } - if reverse { - n-- - } else { - n++ - } - } - } - // process runs in parallel - var nThreadsAlive atomic.Int32 - nThreadsAlive.Store(int32(threads)) - process := func() { - defer func() { - // Last processor closes the result channel - if nThreadsAlive.Add(-1) == 0 { - close(hashesCh) - } - }() - for data := range rlpCh { - var body types.Body - if err := rlp.DecodeBytes(data.rlp, &body); err != nil { - log.Warn("Failed to decode block body", "block", data.number, "error", err) - return - } - var hashes []common.Hash - for _, tx := range body.Transactions { - hashes = append(hashes, tx.Hash()) - } - result := &blockTxHashes{ - hashes: hashes, - number: data.number, - } - // Feed the block to the aggregator, or abort on interrupt - select { - case hashesCh <- result: - case <-interrupt: - return - } - } - } - go lookup() // start the sequential db accessor - for i := 0; i < int(threads); i++ { - go process() - } - return hashesCh -} - -// indexTransactions creates txlookup indices of the specified block range. -// -// This function iterates canonical chain in reverse order, it has one main advantage: -// We can write tx index tail flag periodically even without the whole indexing -// procedure is finished. So that we can resume indexing procedure next time quickly. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { - // short circuit for invalid range - if from >= to { - return - } - var ( - hashesCh = iterateTransactions(db, from, to, true, interrupt) - batch = db.NewBatch() - start = time.Now() - logged = start.Add(-7 * time.Second) - - // Since we iterate in reverse, we expect the first number to come - // in to be [to-1]. Therefore, setting lastNum to means that the - // queue gap-evaluation will work correctly - lastNum = to - queue = prque.New[int64, *blockTxHashes](nil) - blocks, txs = 0, 0 // for stats reporting - ) - for chanDelivery := range hashesCh { - // Push the delivery into the queue and process contiguous ranges. - // Since we iterate in reverse, so lower numbers have lower prio, and - // we can use the number directly as prio marker - queue.Push(chanDelivery, int64(chanDelivery.number)) - for !queue.Empty() { - // If the next available item is gapped, return - if _, priority := queue.Peek(); priority != int64(lastNum-1) { - break - } - // For testing - if hook != nil && !hook(lastNum-1) { - break - } - // Next block available, pop it off and index it - delivery := queue.PopItem() - lastNum = delivery.number - WriteTxLookupEntries(batch, delivery.number, delivery.hashes) - blocks++ - txs += len(delivery.hashes) - // If enough data was accumulated in memory or we're at the last block, dump to disk - if batch.ValueSize() > ethdb.IdealBatchSize { - WriteTxIndexTail(batch, lastNum) // Also write the tail here - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - batch.Reset() - } - // If we've spent too much time already, notify the user of what we're doing - if time.Since(logged) > 8*time.Second { - log.Info("Indexing transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "total", to-from, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - } - // Flush the new indexing tail and the last committed data. It can also happen - // that the last batch is empty because nothing to index, but the tail has to - // be flushed anyway. - WriteTxIndexTail(batch, lastNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - logger := log.Debug - if report { - logger = log.Info - } - select { - case <-interrupt: - logger("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start))) - default: - logger("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -// IndexTransactions creates txlookup indices of the specified block range. The from -// is included while to is excluded. -// -// This function iterates canonical chain in reverse order, it has one main advantage: -// We can write tx index tail flag periodically even without the whole indexing -// procedure is finished. So that we can resume indexing procedure next time quickly. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) { - indexTransactions(db, from, to, interrupt, nil, report) -} - -// indexTransactionsForTesting is the internal debug version with an additional hook. -func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) { - indexTransactions(db, from, to, interrupt, hook, false) -} - -// unindexTransactions removes txlookup indices of the specified block range. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { - // short circuit for invalid range - if from >= to { - return - } - var ( - hashesCh = iterateTransactions(db, from, to, false, interrupt) - batch = db.NewBatch() - start = time.Now() - logged = start.Add(-7 * time.Second) - - // we expect the first number to come in to be [from]. Therefore, setting - // nextNum to from means that the queue gap-evaluation will work correctly - nextNum = from - queue = prque.New[int64, *blockTxHashes](nil) - blocks, txs = 0, 0 // for stats reporting - ) - // Otherwise spin up the concurrent iterator and unindexer - for delivery := range hashesCh { - // Push the delivery into the queue and process contiguous ranges. - queue.Push(delivery, -int64(delivery.number)) - for !queue.Empty() { - // If the next available item is gapped, return - if _, priority := queue.Peek(); -priority != int64(nextNum) { - break - } - // For testing - if hook != nil && !hook(nextNum) { - break - } - delivery := queue.PopItem() - nextNum = delivery.number + 1 - DeleteTxLookupEntries(batch, delivery.hashes) - txs += len(delivery.hashes) - blocks++ - - // If enough data was accumulated in memory or we're at the last block, dump to disk - // A batch counts the size of deletion as '1', so we need to flush more - // often than that. - if blocks%1000 == 0 { - WriteTxIndexTail(batch, nextNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - batch.Reset() - } - // If we've spent too much time already, notify the user of what we're doing - if time.Since(logged) > 8*time.Second { - log.Info("Unindexing transactions", "blocks", blocks, "txs", txs, "total", to-from, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - } - // Flush the new indexing tail and the last committed data. It can also happen - // that the last batch is empty because nothing to unindex, but the tail has to - // be flushed anyway. - WriteTxIndexTail(batch, nextNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - logger := log.Debug - if report { - logger = log.Info - } - select { - case <-interrupt: - logger("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start))) - default: - logger("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -// UnindexTransactions removes txlookup indices of the specified block range. -// The from is included while to is excluded. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) { - unindexTransactions(db, from, to, interrupt, nil, report) -} - -// unindexTransactionsForTesting is the internal debug version with an additional hook. -func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) { - unindexTransactions(db, from, to, interrupt, hook, false) -} diff --git a/core/rawdb/chain_iterator_test.go b/core/rawdb/chain_iterator_test.go deleted file mode 100644 index daea1834b0..0000000000 --- a/core/rawdb/chain_iterator_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// (c) 2019-2022, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2020 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "math/big" - "reflect" - "sort" - "sync" - "testing" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" -) - -func TestChainIterator(t *testing.T) { - // Construct test chain db - chainDb := NewMemoryDatabase() - - var block *types.Block - var txs []*types.Transaction - to := common.BytesToAddress([]byte{0x11}) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher()) // Empty genesis block - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - for i := uint64(1); i <= 10; i++ { - var tx *types.Transaction - if i%2 == 0 { - tx = types.NewTx(&types.LegacyTx{ - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } else { - tx = types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1337), - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } - txs = append(txs, tx) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - } - - var cases = []struct { - from, to uint64 - reverse bool - expect []int - }{ - {0, 11, true, []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}, - {0, 0, true, nil}, - {0, 5, true, []int{4, 3, 2, 1, 0}}, - {10, 11, true, []int{10}}, - {0, 11, false, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, - {0, 0, false, nil}, - {10, 11, false, []int{10}}, - } - for i, c := range cases { - var numbers []int - hashCh := iterateTransactions(chainDb, c.from, c.to, c.reverse, nil) - if hashCh != nil { - for h := range hashCh { - numbers = append(numbers, int(h.number)) - if len(h.hashes) > 0 { - if got, exp := h.hashes[0], txs[h.number-1].Hash(); got != exp { - t.Fatalf("block %d: hash wrong, got %x exp %x", h.number, got, exp) - } - } - } - } - if !c.reverse { - sort.Ints(numbers) - } else { - sort.Sort(sort.Reverse(sort.IntSlice(numbers))) - } - if !reflect.DeepEqual(numbers, c.expect) { - t.Fatalf("Case %d failed, visit element mismatch, want %v, got %v", i, c.expect, numbers) - } - } -} - -func TestIndexTransactions(t *testing.T) { - // Construct test chain db - chainDb := NewMemoryDatabase() - - var block *types.Block - var txs []*types.Transaction - to := common.BytesToAddress([]byte{0x11}) - - // Write empty genesis block - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - - for i := uint64(1); i <= 10; i++ { - var tx *types.Transaction - if i%2 == 0 { - tx = types.NewTx(&types.LegacyTx{ - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } else { - tx = types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1337), - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } - txs = append(txs, tx) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - } - // verify checks whether the tx indices in the range [from, to) - // is expected. - verify := func(from, to int, exist bool, tail uint64) { - for i := from; i < to; i++ { - if i == 0 { - continue - } - number := ReadTxLookupEntry(chainDb, txs[i-1].Hash()) - if exist && number == nil { - t.Fatalf("Transaction index %d missing", i) - } - if !exist && number != nil { - t.Fatalf("Transaction index %d is not deleted", i) - } - } - number := ReadTxIndexTail(chainDb) - if number == nil || *number != tail { - t.Fatalf("Transaction tail mismatch") - } - } - IndexTransactions(chainDb, 5, 11, nil, false) - verify(5, 11, true, 5) - verify(0, 5, false, 5) - - IndexTransactions(chainDb, 0, 5, nil, false) - verify(0, 11, true, 0) - - UnindexTransactions(chainDb, 0, 5, nil, false) - verify(5, 11, true, 5) - verify(0, 5, false, 5) - - UnindexTransactions(chainDb, 5, 11, nil, false) - verify(0, 11, false, 11) - - // Testing corner cases - signal := make(chan struct{}) - var once sync.Once - indexTransactionsForTesting(chainDb, 5, 11, signal, func(n uint64) bool { - if n <= 8 { - once.Do(func() { - close(signal) - }) - return false - } - return true - }) - verify(9, 11, true, 9) - verify(0, 9, false, 9) - IndexTransactions(chainDb, 0, 9, nil, false) - - signal = make(chan struct{}) - var once2 sync.Once - unindexTransactionsForTesting(chainDb, 0, 11, signal, func(n uint64) bool { - if n >= 8 { - once2.Do(func() { - close(signal) - }) - return false - } - return true - }) - verify(8, 11, true, 8) - verify(0, 8, false, 8) -} diff --git a/core/rawdb/database.go b/core/rawdb/database.go deleted file mode 100644 index 2195ab31ac..0000000000 --- a/core/rawdb/database.go +++ /dev/null @@ -1,464 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "time" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/ethdb/leveldb" - "github.com/ava-labs/libevm/ethdb/memorydb" - "github.com/ava-labs/libevm/ethdb/pebble" - "github.com/ava-labs/libevm/log" - "github.com/olekukonko/tablewriter" -) - -// nofreezedb is a database wrapper that disables freezer data retrievals. -type nofreezedb struct { - ethdb.KeyValueStore -} - -// HasAncient returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) HasAncient(kind string, number uint64) (bool, error) { - return false, errNotSupported -} - -// Ancient returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) { - return nil, errNotSupported -} - -// AncientRange returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientRange(kind string, start, max, maxByteSize uint64) ([][]byte, error) { - return nil, errNotSupported -} - -// Ancients returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Ancients() (uint64, error) { - return 0, errNotSupported -} - -// Tail returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Tail() (uint64, error) { - return 0, errNotSupported -} - -// AncientSize returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientSize(kind string) (uint64, error) { - return 0, errNotSupported -} - -// ModifyAncients is not supported. -func (db *nofreezedb) ModifyAncients(func(ethdb.AncientWriteOp) error) (int64, error) { - return 0, errNotSupported -} - -// TruncateHead returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) TruncateHead(items uint64) (uint64, error) { - return 0, errNotSupported -} - -// TruncateTail returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) TruncateTail(items uint64) (uint64, error) { - return 0, errNotSupported -} - -// Sync returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Sync() error { - return errNotSupported -} - -func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { - // Unlike other ancient-related methods, this method does not return - // errNotSupported when invoked. - // The reason for this is that the caller might want to do several things: - // 1. Check if something is in the freezer, - // 2. If not, check leveldb. - // - // This will work, since the ancient-checks inside 'fn' will return errors, - // and the leveldb work will continue. - // - // If we instead were to return errNotSupported here, then the caller would - // have to explicitly check for that, having an extra clause to do the - // non-ancient operations. - return fn(db) -} - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (db *nofreezedb) MigrateTable(kind string, convert convertLegacyFn) error { - return errNotSupported -} - -// AncientDatadir returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientDatadir() (string, error) { - return "", errNotSupported -} - -// NewDatabase creates a high level database on top of a given key-value data -// store without a freezer moving immutable chain segments into cold storage. -func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { - return &nofreezedb{KeyValueStore: db} -} - -// NewMemoryDatabase creates an ephemeral in-memory key-value database without a -// freezer moving immutable chain segments into cold storage. -func NewMemoryDatabase() ethdb.Database { - return NewDatabase(memorydb.New()) -} - -// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database -// with an initial starting capacity, but without a freezer moving immutable -// chain segments into cold storage. -func NewMemoryDatabaseWithCap(size int) ethdb.Database { - return NewDatabase(memorydb.NewWithCap(size)) -} - -// NewLevelDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewLevelDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := leveldb.New(file, cache, handles, namespace, readonly) - if err != nil { - return nil, err - } - log.Info("Using LevelDB as the backing database") - return NewDatabase(db), nil -} - -// NewPebbleDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral) - if err != nil { - return nil, err - } - return NewDatabase(db), nil -} - -const ( - dbPebble = "pebble" - dbLeveldb = "leveldb" -) - -// PreexistingDatabase checks the given data directory whether a database is already -// instantiated at that location, and if so, returns the type of database (or the -// empty string). -func PreexistingDatabase(path string) string { - if _, err := os.Stat(filepath.Join(path, "CURRENT")); err != nil { - return "" // No pre-existing db - } - if matches, err := filepath.Glob(filepath.Join(path, "OPTIONS*")); len(matches) > 0 || err != nil { - if err != nil { - panic(err) // only possible if the pattern is malformed - } - return dbPebble - } - return dbLeveldb -} - -// OpenOptions contains the options to apply when opening a database. -// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used. -type OpenOptions struct { - Type string // "leveldb" | "pebble" - Directory string // the datadir - Namespace string // the namespace for database relevant metrics - Cache int // the capacity(in megabytes) of the data caching - Handles int // number of files to be open simultaneously - ReadOnly bool - // Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of - // a crash is not important. This option should typically be used in tests. - Ephemeral bool -} - -// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. -// -// type == null type != null -// +---------------------------------------- -// db is non-existent | pebble default | specified type -// db is existent | from db | specified type (if compatible) -func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) { - // Reject any unsupported database type - if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble { - return nil, fmt.Errorf("unknown db.engine %v", o.Type) - } - // Retrieve any pre-existing database's type and use that or the requested one - // as long as there's no conflict between the two types - existingDb := PreexistingDatabase(o.Directory) - if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { - return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) - } - if o.Type == dbPebble || existingDb == dbPebble { - log.Info("Using pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) - } - if o.Type == dbLeveldb || existingDb == dbLeveldb { - log.Info("Using leveldb as the backing database") - return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } - // No pre-existing database, no user-requested one either. Default to Pebble. - log.Info("Defaulting to pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) -} - -// Open opens both a disk-based key-value database such as leveldb or pebble, but also -// integrates it with a freezer database -- if the AncientDir option has been -// set on the provided OpenOptions. -// The passed o.AncientDir indicates the path of root ancient directory where -// the chain freezer can be opened. -func Open(o OpenOptions) (ethdb.Database, error) { - kvdb, err := openKeyValueDatabase(o) - if err != nil { - return nil, err - } - return kvdb, nil -} - -type counter uint64 - -func (c counter) String() string { - return fmt.Sprintf("%d", c) -} - -func (c counter) Percentage(current uint64) string { - return fmt.Sprintf("%d", current*100/uint64(c)) -} - -// stat stores sizes and count for a parameter -type stat struct { - size common.StorageSize - count counter -} - -// Add size to the stat and increase the counter by 1 -func (s *stat) Add(size common.StorageSize) { - s.size += size - s.count++ -} - -func (s *stat) Size() string { - return s.size.String() -} - -func (s *stat) Count() string { - return s.count.String() -} - -// InspectDatabase traverses the entire database and checks the size -// of all different categories of data. -func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { - it := db.NewIterator(keyPrefix, keyStart) - defer it.Release() - - var ( - count int64 - start = time.Now() - logged = time.Now() - - // Key-value store statistics - headers stat - bodies stat - receipts stat - numHashPairings stat - hashNumPairings stat - legacyTries stat - stateLookups stat - accountTries stat - storageTries stat - codes stat - txLookups stat - accountSnaps stat - storageSnaps stat - preimages stat - bloomBits stat - cliqueSnaps stat - - // State sync statistics - codeToFetch stat - syncProgress stat - syncSegments stat - syncPerformed stat - - // Les statistic - chtTrieNodes stat - bloomTrieNodes stat - - // Meta- and unaccounted data - metadata stat - unaccounted stat - - // 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 - switch { - case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength): - headers.Add(size) - case bytes.HasPrefix(key, blockBodyPrefix) && len(key) == (len(blockBodyPrefix)+8+common.HashLength): - bodies.Add(size) - case bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength): - receipts.Add(size) - case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix): - numHashPairings.Add(size) - case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength): - hashNumPairings.Add(size) - case IsLegacyTrieNode(key, it.Value()): - legacyTries.Add(size) - case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: - stateLookups.Add(size) - case IsAccountTrieNode(key): - accountTries.Add(size) - case IsStorageTrieNode(key): - storageTries.Add(size) - case bytes.HasPrefix(key, CodePrefix) && len(key) == len(CodePrefix)+common.HashLength: - codes.Add(size) - case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength): - txLookups.Add(size) - case bytes.HasPrefix(key, SnapshotAccountPrefix) && len(key) == (len(SnapshotAccountPrefix)+common.HashLength): - accountSnaps.Add(size) - case bytes.HasPrefix(key, SnapshotStoragePrefix) && len(key) == (len(SnapshotStoragePrefix)+2*common.HashLength): - storageSnaps.Add(size) - case bytes.HasPrefix(key, PreimagePrefix) && len(key) == (len(PreimagePrefix)+common.HashLength): - preimages.Add(size) - case bytes.HasPrefix(key, configPrefix) && len(key) == (len(configPrefix)+common.HashLength): - metadata.Add(size) - case bytes.HasPrefix(key, upgradeConfigPrefix) && len(key) == (len(upgradeConfigPrefix)+common.HashLength): - metadata.Add(size) - case bytes.HasPrefix(key, bloomBitsPrefix) && len(key) == (len(bloomBitsPrefix)+10+common.HashLength): - bloomBits.Add(size) - case bytes.HasPrefix(key, BloomBitsIndexPrefix): - bloomBits.Add(size) - case bytes.HasPrefix(key, syncStorageTriesPrefix) && len(key) == syncStorageTriesKeyLength: - syncProgress.Add(size) - case bytes.HasPrefix(key, syncSegmentsPrefix) && len(key) == syncSegmentsKeyLength: - syncSegments.Add(size) - case bytes.HasPrefix(key, CodeToFetchPrefix) && len(key) == codeToFetchKeyLength: - codeToFetch.Add(size) - case bytes.HasPrefix(key, syncPerformedPrefix) && len(key) == syncPerformedKeyLength: - syncPerformed.Add(size) - default: - var accounted bool - for _, meta := range [][]byte{ - databaseVersionKey, headHeaderKey, headBlockKey, - snapshotRootKey, snapshotBlockHashKey, snapshotGeneratorKey, - uncleanShutdownKey, syncRootKey, txIndexTailKey, - persistentStateIDKey, trieJournalKey, - } { - if bytes.Equal(key, meta) { - metadata.Add(size) - accounted = true - break - } - } - if !accounted { - unaccounted.Add(size) - } - } - count++ - if count%1000 == 0 && time.Since(logged) > 8*time.Second { - log.Info("Inspecting database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - // Display the database statistic. - stats := [][]string{ - {"Key-Value store", "Headers", headers.Size(), headers.Count()}, - {"Key-Value store", "Bodies", bodies.Size(), bodies.Count()}, - {"Key-Value store", "Receipt lists", receipts.Size(), receipts.Count()}, - {"Key-Value store", "Block number->hash", numHashPairings.Size(), numHashPairings.Count()}, - {"Key-Value store", "Block hash->number", hashNumPairings.Size(), hashNumPairings.Count()}, - {"Key-Value store", "Transaction index", txLookups.Size(), txLookups.Count()}, - {"Key-Value store", "Bloombit index", bloomBits.Size(), bloomBits.Count()}, - {"Key-Value store", "Contract codes", codes.Size(), codes.Count()}, - {"Key-Value store", "Hash trie nodes", legacyTries.Size(), legacyTries.Count()}, - {"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()}, - {"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()}, - {"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()}, - {"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()}, - {"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()}, - {"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()}, - {"Key-Value store", "Clique snapshots", cliqueSnaps.Size(), cliqueSnaps.Count()}, - {"Key-Value store", "Singleton metadata", metadata.Size(), metadata.Count()}, - {"Light client", "CHT trie nodes", chtTrieNodes.Size(), chtTrieNodes.Count()}, - {"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()}, - {"State sync", "Trie segments", syncSegments.Size(), syncSegments.Count()}, - {"State sync", "Storage tries to fetch", syncProgress.Size(), syncProgress.Count()}, - {"State sync", "Code to fetch", codeToFetch.Size(), codeToFetch.Count()}, - {"State sync", "Block numbers synced to", syncPerformed.Size(), syncPerformed.Count()}, - } - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Database", "Category", "Size", "Items"}) - table.SetFooter([]string{"", "Total", total.String(), " "}) - table.AppendBulk(stats) - table.Render() - - if unaccounted.size > 0 { - log.Error("Database contains unaccounted data", "size", unaccounted.size, "count", unaccounted.count) - } - return nil -} - -// ClearPrefix removes all keys in db that begin with prefix and match an -// expected key length. [keyLen] should include the length of the prefix. -func ClearPrefix(db ethdb.KeyValueStore, prefix []byte, keyLen int) error { - it := db.NewIterator(prefix, nil) - defer it.Release() - - batch := db.NewBatch() - for it.Next() { - key := common.CopyBytes(it.Key()) - if len(key) != keyLen { - // avoid deleting keys that do not match the expected length - continue - } - if err := batch.Delete(key); err != nil { - return err - } - if batch.ValueSize() > ethdb.IdealBatchSize { - if err := batch.Write(); err != nil { - return err - } - batch.Reset() - } - } - if err := it.Error(); err != nil { - return err - } - return batch.Write() -} - -/// TODO: Consider adding ReadChainMetadata diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go deleted file mode 100644 index 622cbb3ff9..0000000000 --- a/core/rawdb/freezer.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -// convertLegacyFn takes a raw freezer entry in an older format and -// returns it in the new format. -type convertLegacyFn = func([]byte) ([]byte, error) diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go deleted file mode 100644 index bc999be25b..0000000000 --- a/core/rawdb/freezer_table.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import "errors" - -var ( - // errNotSupported is returned if the database doesn't support the required operation. - errNotSupported = errors.New("this operation is not supported") -) diff --git a/core/rawdb/key_length_iterator.go b/core/rawdb/key_length_iterator.go deleted file mode 100644 index 8d1a7d2f54..0000000000 --- a/core/rawdb/key_length_iterator.go +++ /dev/null @@ -1,57 +0,0 @@ -// (c) 2022, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2022 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import "github.com/ava-labs/libevm/ethdb" - -// KeyLengthIterator is a wrapper for a database iterator that ensures only key-value pairs -// with a specific key length will be returned. -type KeyLengthIterator struct { - requiredKeyLength int - ethdb.Iterator -} - -// NewKeyLengthIterator returns a wrapped version of the iterator that will only return key-value -// pairs where keys with a specific key length will be returned. -func NewKeyLengthIterator(it ethdb.Iterator, keyLen int) ethdb.Iterator { - return &KeyLengthIterator{ - Iterator: it, - requiredKeyLength: keyLen, - } -} - -func (it *KeyLengthIterator) Next() bool { - // Return true as soon as a key with the required key length is discovered - for it.Iterator.Next() { - if len(it.Iterator.Key()) == it.requiredKeyLength { - return true - } - } - - // Return false when we exhaust the keys in the underlying iterator. - return false -} diff --git a/core/rawdb/key_length_iterator_test.go b/core/rawdb/key_length_iterator_test.go deleted file mode 100644 index 654efc5b55..0000000000 --- a/core/rawdb/key_length_iterator_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "encoding/binary" - "testing" -) - -func TestKeyLengthIterator(t *testing.T) { - db := NewMemoryDatabase() - - keyLen := 8 - expectedKeys := make(map[string]struct{}) - for i := 0; i < 100; i++ { - key := make([]byte, keyLen) - binary.BigEndian.PutUint64(key, uint64(i)) - if err := db.Put(key, []byte{0x1}); err != nil { - t.Fatal(err) - } - expectedKeys[string(key)] = struct{}{} - - longerKey := make([]byte, keyLen*2) - binary.BigEndian.PutUint64(longerKey, uint64(i)) - if err := db.Put(longerKey, []byte{0x1}); err != nil { - t.Fatal(err) - } - } - - it := NewKeyLengthIterator(db.NewIterator(nil, nil), keyLen) - for it.Next() { - key := it.Key() - _, exists := expectedKeys[string(key)] - if !exists { - t.Fatalf("Found unexpected key %d", binary.BigEndian.Uint64(key)) - } - delete(expectedKeys, string(key)) - if len(key) != keyLen { - t.Fatalf("Found unexpected key in key length iterator with length %d", len(key)) - } - } - - if len(expectedKeys) != 0 { - t.Fatalf("Expected all keys of length %d to be removed from expected keys during iteration", keyLen) - } -} diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go deleted file mode 100644 index 7e57e83288..0000000000 --- a/core/rawdb/schema.go +++ /dev/null @@ -1,316 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Package rawdb contains a collection of low level database accessors. -package rawdb - -import ( - "bytes" - "encoding/binary" - - "github.com/ava-labs/avalanchego/utils/wrappers" - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/libevm/metrics" -) - -// The fields below define the low level database schema prefixing. -var ( - // databaseVersionKey tracks the current database version. - databaseVersionKey = []byte("DatabaseVersion") - - // headHeaderKey tracks the latest known header's hash. - headHeaderKey = []byte("LastHeader") - - // headBlockKey tracks the latest known full block's hash. - headBlockKey = []byte("LastBlock") - - // persistentStateIDKey tracks the id of latest stored state(for path-based only). - persistentStateIDKey = []byte("LastStateID") - - // snapshotRootKey tracks the hash of the last snapshot. - snapshotRootKey = []byte("SnapshotRoot") - - // snapshotBlockHashKey tracks the block hash of the last snapshot. - snapshotBlockHashKey = []byte("SnapshotBlockHash") - - // snapshotGeneratorKey tracks the snapshot generation marker across restarts. - snapshotGeneratorKey = []byte("SnapshotGenerator") - - // trieJournalKey tracks the in-memory trie node layers across restarts. - trieJournalKey = []byte("TrieJournal") - - // txIndexTailKey tracks the oldest block whose transactions have been indexed. - txIndexTailKey = []byte("TransactionIndexTail") - - // uncleanShutdownKey tracks the list of local crashes - uncleanShutdownKey = []byte("unclean-shutdown") // config prefix for the db - - // offlinePruningKey tracks runs of offline pruning - offlinePruningKey = []byte("OfflinePruning") - - // populateMissingTriesKey tracks runs of trie backfills - populateMissingTriesKey = []byte("PopulateMissingTries") - - // pruningDisabledKey tracks whether the node has ever run in archival mode - // to ensure that a user does not accidentally corrupt an archival node. - pruningDisabledKey = []byte("PruningDisabled") - - // acceptorTipKey tracks the tip of the last accepted block that has been fully processed. - acceptorTipKey = []byte("AcceptorTipKey") - - // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). - headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header - headerHashSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash - headerNumberPrefix = []byte("H") // headerNumberPrefix + hash -> num (uint64 big endian) - - blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body - blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts - - txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata - bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits - SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value - SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value - CodePrefix = []byte("c") // CodePrefix + code hash -> account code - - // Path-based storage scheme of merkle patricia trie. - trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node - trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node - stateIDPrefix = []byte("L") // stateIDPrefix + state root -> state id - - PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage - configPrefix = []byte("ethereum-config-") // config prefix for the db - upgradeConfigPrefix = []byte("upgrade-config-") // upgrade bytes passed to the chain are stored with this prefix - - // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress - BloomBitsIndexPrefix = []byte("iB") - - preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) - preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) - - // State sync progress keys and prefixes - syncRootKey = []byte("sync_root") // indicates the root of the main account trie currently being synced - syncStorageTriesPrefix = []byte("sync_storage") // syncStorageTriesPrefix + trie root + account hash: indicates a storage trie must be fetched for the account - syncSegmentsPrefix = []byte("sync_segments") // syncSegmentsPrefix + trie root + 32-byte start key: indicates the trie at root has a segment starting at the specified key - CodeToFetchPrefix = []byte("CP") // CodeToFetchPrefix + code hash -> empty value tracks the outstanding code hashes we need to fetch. - - // State sync progress key lengths - syncStorageTriesKeyLength = len(syncStorageTriesPrefix) + 2*common.HashLength - syncSegmentsKeyLength = len(syncSegmentsPrefix) + 2*common.HashLength - codeToFetchKeyLength = len(CodeToFetchPrefix) + common.HashLength - - // State sync metadata - syncPerformedPrefix = []byte("sync_performed") - syncPerformedKeyLength = len(syncPerformedPrefix) + wrappers.LongLen // prefix + block number as uint64 -) - -// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary -// fields. -type LegacyTxLookupEntry struct { - BlockHash common.Hash - BlockIndex uint64 - Index uint64 -} - -// encodeBlockNumber encodes a block number as big endian uint64 -func encodeBlockNumber(number uint64) []byte { - enc := make([]byte, 8) - binary.BigEndian.PutUint64(enc, number) - return enc -} - -// headerKeyPrefix = headerPrefix + num (uint64 big endian) -func headerKeyPrefix(number uint64) []byte { - return append(headerPrefix, encodeBlockNumber(number)...) -} - -// headerKey = headerPrefix + num (uint64 big endian) + hash -func headerKey(number uint64, hash common.Hash) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix -func headerHashKey(number uint64) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) -} - -// headerNumberKey = headerNumberPrefix + hash -func headerNumberKey(hash common.Hash) []byte { - return append(headerNumberPrefix, hash.Bytes()...) -} - -// blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash -func blockBodyKey(number uint64, hash common.Hash) []byte { - return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash -func blockReceiptsKey(number uint64, hash common.Hash) []byte { - return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// txLookupKey = txLookupPrefix + hash -func txLookupKey(hash common.Hash) []byte { - return append(txLookupPrefix, hash.Bytes()...) -} - -// accountSnapshotKey = SnapshotAccountPrefix + hash -func accountSnapshotKey(hash common.Hash) []byte { - return append(SnapshotAccountPrefix, hash.Bytes()...) -} - -// storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash -func storageSnapshotKey(accountHash, storageHash common.Hash) []byte { - buf := make([]byte, len(SnapshotStoragePrefix)+common.HashLength+common.HashLength) - n := copy(buf, SnapshotStoragePrefix) - n += copy(buf[n:], accountHash.Bytes()) - copy(buf[n:], storageHash.Bytes()) - return buf -} - -// storageSnapshotsKey = SnapshotStoragePrefix + account hash + storage hash -func storageSnapshotsKey(accountHash common.Hash) []byte { - return append(SnapshotStoragePrefix, accountHash.Bytes()...) -} - -// bloomBitsKey = bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -func bloomBitsKey(bit uint, section uint64, hash common.Hash) []byte { - key := append(append(bloomBitsPrefix, make([]byte, 10)...), hash.Bytes()...) - - binary.BigEndian.PutUint16(key[1:], uint16(bit)) - binary.BigEndian.PutUint64(key[3:], section) - - return key -} - -// preimageKey = preimagePrefix + hash -func preimageKey(hash common.Hash) []byte { - return append(PreimagePrefix, hash.Bytes()...) -} - -// codeKey = CodePrefix + hash -func codeKey(hash common.Hash) []byte { - return append(CodePrefix, hash.Bytes()...) -} - -// IsCodeKey reports whether the given byte slice is the key of contract code, -// if so return the raw code hash as well. -func IsCodeKey(key []byte) (bool, []byte) { - if bytes.HasPrefix(key, CodePrefix) && len(key) == common.HashLength+len(CodePrefix) { - return true, key[len(CodePrefix):] - } - return false, nil -} - -// configKey = configPrefix + hash -func configKey(hash common.Hash) []byte { - return append(configPrefix, hash.Bytes()...) -} - -// upgradeConfigKey = upgradeConfigPrefix + hash -func upgradeConfigKey(hash common.Hash) []byte { - return append(upgradeConfigPrefix, hash.Bytes()...) -} - -// stateIDKey = stateIDPrefix + root (32 bytes) -func stateIDKey(root common.Hash) []byte { - return append(stateIDPrefix, root.Bytes()...) -} - -// accountTrieNodeKey = trieNodeAccountPrefix + nodePath. -func accountTrieNodeKey(path []byte) []byte { - return append(trieNodeAccountPrefix, path...) -} - -// storageTrieNodeKey = trieNodeStoragePrefix + accountHash + nodePath. -func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte { - buf := make([]byte, len(trieNodeStoragePrefix)+common.HashLength+len(path)) - n := copy(buf, trieNodeStoragePrefix) - n += copy(buf[n:], accountHash.Bytes()) - copy(buf[n:], path) - return buf -} - -// IsLegacyTrieNode reports whether a provided database entry is a legacy trie -// node. The characteristics of legacy trie node are: -// - the key length is 32 bytes -// - the key is the hash of val -func IsLegacyTrieNode(key []byte, val []byte) bool { - if len(key) != common.HashLength { - return false - } - return bytes.Equal(key, crypto.Keccak256(val)) -} - -// ResolveAccountTrieNodeKey reports whether a provided database entry is an -// account trie node in path-based state scheme, and returns the resolved -// node path if so. -func ResolveAccountTrieNodeKey(key []byte) (bool, []byte) { - if !bytes.HasPrefix(key, trieNodeAccountPrefix) { - return false, nil - } - // The remaining key should only consist a hex node path - // whose length is in the range 0 to 64 (64 is excluded - // since leaves are always wrapped with shortNode). - if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 { - return false, nil - } - return true, key[len(trieNodeAccountPrefix):] -} - -// IsAccountTrieNode reports whether a provided database entry is an account -// trie node in path-based state scheme. -func IsAccountTrieNode(key []byte) bool { - ok, _ := ResolveAccountTrieNodeKey(key) - return ok -} - -// ResolveStorageTrieNode reports whether a provided database entry is a storage -// trie node in path-based state scheme, and returns the resolved account hash -// and node path if so. -func ResolveStorageTrieNode(key []byte) (bool, common.Hash, []byte) { - if !bytes.HasPrefix(key, trieNodeStoragePrefix) { - return false, common.Hash{}, nil - } - // The remaining key consists of 2 parts: - // - 32 bytes account hash - // - hex node path whose length is in the range 0 to 64 - if len(key) < len(trieNodeStoragePrefix)+common.HashLength { - return false, common.Hash{}, nil - } - if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 { - return false, common.Hash{}, nil - } - accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength]) - return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:] -} - -// IsStorageTrieNode reports whether a provided database entry is a storage -// trie node in path-based state scheme. -func IsStorageTrieNode(key []byte) bool { - ok, _, _ := ResolveStorageTrieNode(key) - return ok -} diff --git a/core/rawdb/table.go b/core/rawdb/table.go deleted file mode 100644 index cb9156173a..0000000000 --- a/core/rawdb/table.go +++ /dev/null @@ -1,317 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "github.com/ava-labs/libevm/ethdb" -) - -// table is a wrapper around a database that prefixes each key access with a pre- -// configured string. -type table struct { - db ethdb.Database - prefix string -} - -// NewTable returns a database object that prefixes all keys with a given string. -func NewTable(db ethdb.Database, prefix string) ethdb.Database { - return &table{ - db: db, - prefix: prefix, - } -} - -// Close is a noop to implement the Database interface. -func (t *table) Close() error { - return nil -} - -// Has retrieves if a prefixed version of a key is present in the database. -func (t *table) Has(key []byte) (bool, error) { - return t.db.Has(append([]byte(t.prefix), key...)) -} - -// Get retrieves the given prefixed key if it's present in the database. -func (t *table) Get(key []byte) ([]byte, error) { - return t.db.Get(append([]byte(t.prefix), key...)) -} - -// HasAncient is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) HasAncient(kind string, number uint64) (bool, error) { - return t.db.HasAncient(kind, number) -} - -// Ancient is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Ancient(kind string, number uint64) ([]byte, error) { - return t.db.Ancient(kind, number) -} - -// AncientRange is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - return t.db.AncientRange(kind, start, count, maxBytes) -} - -// Ancients is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Ancients() (uint64, error) { - return t.db.Ancients() -} - -// Tail is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Tail() (uint64, error) { - return t.db.Tail() -} - -// AncientSize is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) AncientSize(kind string) (uint64, error) { - return t.db.AncientSize(kind) -} - -// ModifyAncients runs an ancient write operation on the underlying database. -func (t *table) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (int64, error) { - return t.db.ModifyAncients(fn) -} - -func (t *table) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { - return t.db.ReadAncients(fn) -} - -// TruncateHead is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) TruncateHead(items uint64) (uint64, error) { - return t.db.TruncateHead(items) -} - -// TruncateTail is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) TruncateTail(items uint64) (uint64, error) { - return t.db.TruncateTail(items) -} - -// Sync is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Sync() error { - return t.db.Sync() -} - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (t *table) MigrateTable(kind string, convert convertLegacyFn) error { - return t.db.MigrateTable(kind, convert) -} - -// AncientDatadir returns the ancient datadir of the underlying database. -func (t *table) AncientDatadir() (string, error) { - return t.db.AncientDatadir() -} - -// Put inserts the given value into the database at a prefixed version of the -// provided key. -func (t *table) Put(key []byte, value []byte) error { - return t.db.Put(append([]byte(t.prefix), key...), value) -} - -// Delete removes the given prefixed key from the database. -func (t *table) Delete(key []byte) error { - return t.db.Delete(append([]byte(t.prefix), key...)) -} - -// NewIterator creates a binary-alphabetical iterator over a subset -// of database content with a particular key prefix, starting at a particular -// initial key (or after, if it does not exist). -func (t *table) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - innerPrefix := append([]byte(t.prefix), prefix...) - iter := t.db.NewIterator(innerPrefix, start) - return &tableIterator{ - iter: iter, - prefix: t.prefix, - } -} - -// Stat returns a particular internal stat of the database. -func (t *table) Stat(property string) (string, error) { - return t.db.Stat(property) -} - -// Compact flattens the underlying data store for the given key range. In essence, -// deleted and overwritten versions are discarded, and the data is rearranged to -// reduce the cost of operations needed to access them. -// -// A nil start is treated as a key before all keys in the data store; a nil limit -// is treated as a key after all keys in the data store. If both is nil then it -// will compact entire data store. -func (t *table) Compact(start []byte, limit []byte) error { - // If no start was specified, use the table prefix as the first value - if start == nil { - start = []byte(t.prefix) - } else { - start = append([]byte(t.prefix), start...) - } - // If no limit was specified, use the first element not matching the prefix - // as the limit - if limit == nil { - limit = []byte(t.prefix) - for i := len(limit) - 1; i >= 0; i-- { - // Bump the current character, stopping if it doesn't overflow - limit[i]++ - if limit[i] > 0 { - break - } - // Character overflown, proceed to the next or nil if the last - if i == 0 { - limit = nil - } - } - } else { - limit = append([]byte(t.prefix), limit...) - } - // Range correctly calculated based on table prefix, delegate down - return t.db.Compact(start, limit) -} - -// NewBatch creates a write-only database that buffers changes to its host db -// until a final write is called, each operation prefixing all keys with the -// pre-configured string. -func (t *table) NewBatch() ethdb.Batch { - return &tableBatch{t.db.NewBatch(), t.prefix} -} - -// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -func (t *table) NewBatchWithSize(size int) ethdb.Batch { - return &tableBatch{t.db.NewBatchWithSize(size), t.prefix} -} - -// NewSnapshot creates a database snapshot based on the current state. -// The created snapshot will not be affected by all following mutations -// happened on the database. -func (t *table) NewSnapshot() (ethdb.Snapshot, error) { - return t.db.NewSnapshot() -} - -// tableBatch is a wrapper around a database batch that prefixes each key access -// with a pre-configured string. -type tableBatch struct { - batch ethdb.Batch - prefix string -} - -// Put inserts the given value into the batch for later committing. -func (b *tableBatch) Put(key, value []byte) error { - return b.batch.Put(append([]byte(b.prefix), key...), value) -} - -// Delete inserts a key removal into the batch for later committing. -func (b *tableBatch) Delete(key []byte) error { - return b.batch.Delete(append([]byte(b.prefix), key...)) -} - -// ValueSize retrieves the amount of data queued up for writing. -func (b *tableBatch) ValueSize() int { - return b.batch.ValueSize() -} - -// Write flushes any accumulated data to disk. -func (b *tableBatch) Write() error { - return b.batch.Write() -} - -// Reset resets the batch for reuse. -func (b *tableBatch) Reset() { - b.batch.Reset() -} - -// tableReplayer is a wrapper around a batch replayer which truncates -// the added prefix. -type tableReplayer struct { - w ethdb.KeyValueWriter - prefix string -} - -// Put implements the interface KeyValueWriter. -func (r *tableReplayer) Put(key []byte, value []byte) error { - trimmed := key[len(r.prefix):] - return r.w.Put(trimmed, value) -} - -// Delete implements the interface KeyValueWriter. -func (r *tableReplayer) Delete(key []byte) error { - trimmed := key[len(r.prefix):] - return r.w.Delete(trimmed) -} - -// Replay replays the batch contents. -func (b *tableBatch) Replay(w ethdb.KeyValueWriter) error { - return b.batch.Replay(&tableReplayer{w: w, prefix: b.prefix}) -} - -// tableIterator is a wrapper around a database iterator that prefixes each key access -// with a pre-configured string. -type tableIterator struct { - iter ethdb.Iterator - prefix string -} - -// Next moves the iterator to the next key/value pair. It returns whether the -// iterator is exhausted. -func (iter *tableIterator) Next() bool { - return iter.iter.Next() -} - -// Error returns any accumulated error. Exhausting all the key/value pairs -// is not considered to be an error. -func (iter *tableIterator) Error() error { - return iter.iter.Error() -} - -// Key returns the key of the current key/value pair, or nil if done. The caller -// should not modify the contents of the returned slice, and its contents may -// change on the next call to Next. -func (iter *tableIterator) Key() []byte { - key := iter.iter.Key() - if key == nil { - return nil - } - return key[len(iter.prefix):] -} - -// Value returns the value of the current key/value pair, or nil if done. The -// caller should not modify the contents of the returned slice, and its contents -// may change on the next call to Next. -func (iter *tableIterator) Value() []byte { - return iter.iter.Value() -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (iter *tableIterator) Release() { - iter.iter.Release() -} diff --git a/core/rawdb/table_test.go b/core/rawdb/table_test.go deleted file mode 100644 index a6f4b454f6..0000000000 --- a/core/rawdb/table_test.go +++ /dev/null @@ -1,138 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2020 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package rawdb - -import ( - "bytes" - "testing" - - "github.com/ava-labs/libevm/ethdb" -) - -func TestTableDatabase(t *testing.T) { testTableDatabase(t, "prefix") } -func TestEmptyPrefixTableDatabase(t *testing.T) { testTableDatabase(t, "") } - -type testReplayer struct { - puts [][]byte - dels [][]byte -} - -func (r *testReplayer) Put(key []byte, value []byte) error { - r.puts = append(r.puts, key) - return nil -} - -func (r *testReplayer) Delete(key []byte) error { - r.dels = append(r.dels, key) - return nil -} - -func testTableDatabase(t *testing.T, prefix string) { - db := NewTable(NewMemoryDatabase(), prefix) - - var entries = []struct { - key []byte - value []byte - }{ - {[]byte{0x01, 0x02}, []byte{0x0a, 0x0b}}, - {[]byte{0x03, 0x04}, []byte{0x0c, 0x0d}}, - {[]byte{0x05, 0x06}, []byte{0x0e, 0x0f}}, - - {[]byte{0xff, 0xff, 0x01}, []byte{0x1a, 0x1b}}, - {[]byte{0xff, 0xff, 0x02}, []byte{0x1c, 0x1d}}, - {[]byte{0xff, 0xff, 0x03}, []byte{0x1e, 0x1f}}, - } - - // Test Put/Get operation - for _, entry := range entries { - db.Put(entry.key, entry.value) - } - for _, entry := range entries { - got, err := db.Get(entry.key) - if err != nil { - t.Fatalf("Failed to get value: %v", err) - } - if !bytes.Equal(got, entry.value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entry.value, got) - } - } - - // Test batch operation - db = NewTable(NewMemoryDatabase(), prefix) - batch := db.NewBatch() - for _, entry := range entries { - batch.Put(entry.key, entry.value) - } - batch.Write() - for _, entry := range entries { - got, err := db.Get(entry.key) - if err != nil { - t.Fatalf("Failed to get value: %v", err) - } - if !bytes.Equal(got, entry.value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entry.value, got) - } - } - - // Test batch replayer - r := &testReplayer{} - batch.Replay(r) - for index, entry := range entries { - got := r.puts[index] - if !bytes.Equal(got, entry.key) { - t.Fatalf("Key mismatch: want=%v, got=%v", entry.key, got) - } - } - - check := func(iter ethdb.Iterator, expCount, index int) { - count := 0 - for iter.Next() { - key, value := iter.Key(), iter.Value() - if !bytes.Equal(key, entries[index].key) { - t.Fatalf("Key mismatch: want=%v, got=%v", entries[index].key, key) - } - if !bytes.Equal(value, entries[index].value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entries[index].value, value) - } - index += 1 - count++ - } - if count != expCount { - t.Fatalf("Wrong number of elems, exp %d got %d", expCount, count) - } - iter.Release() - } - // Test iterators - check(db.NewIterator(nil, nil), 6, 0) - // Test iterators with prefix - check(db.NewIterator([]byte{0xff, 0xff}, nil), 3, 3) - // Test iterators with start point - check(db.NewIterator(nil, []byte{0xff, 0xff, 0x02}), 2, 4) - // Test iterators with prefix and start point - check(db.NewIterator([]byte{0xee}, nil), 0, 0) - check(db.NewIterator(nil, []byte{0x00}), 6, 0) -} diff --git a/core/rlp_test.go b/core/rlp_test.go index a608ac2550..108262aca3 100644 --- a/core/rlp_test.go +++ b/core/rlp_test.go @@ -32,10 +32,10 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "golang.org/x/crypto/sha3" ) diff --git a/core/sender_cacher.go b/core/sender_cacher.go index 87b1339326..0693d3c424 100644 --- a/core/sender_cacher.go +++ b/core/sender_cacher.go @@ -29,7 +29,7 @@ package core import ( "sync" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) // txSenderCacherRequest is a request for recovering transaction senders with a diff --git a/core/state/database.go b/core/state/database.go index 02ffa8ce3e..fe1fb7a0b0 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -1,4 +1,4 @@ -// (c) 2019-2020, Ava Labs, Inc. +// (c) 2019-2025, Ava Labs, Inc. // // This file is a derived work, based on the go-ethereum library whose original // notices appear below. @@ -27,165 +27,24 @@ package state import ( - "errors" - "fmt" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/lru" ethstate "github.com/ava-labs/libevm/core/state" - "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/libevm/trie/utils" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/crate-crypto/go-ipa/banderwagon" ) -const ( - // Number of codehash->size associations to keep. - codeSizeCacheSize = 100000 - - // Cache size granted for caching clean code. - codeCacheSize = 64 * 1024 * 1024 - - // commitmentSize is the size of commitment stored in cache. - commitmentSize = banderwagon.UncompressedSize - - // Cache item granted for caching commitment results. - commitmentCacheItems = 64 * 1024 * 1024 / (commitmentSize + common.AddressLength) +type ( + Database = ethstate.Database + Trie = ethstate.Trie ) -// Database wraps access to tries and contract code. -type Database interface { - // OpenTrie opens the main account trie. - OpenTrie(root common.Hash) (Trie, error) - - // OpenStorageTrie opens the storage trie of an account. - OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error) - - // CopyTrie returns an independent copy of the given trie. - CopyTrie(Trie) Trie - - // ContractCode retrieves a particular contract's code. - ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) - - // ContractCodeSize retrieves a particular contracts code's size. - ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) - - // DiskDB returns the underlying key-value disk database. - DiskDB() ethdb.KeyValueStore - - // TrieDB returns the underlying trie database for managing trie nodes. - TrieDB() *triedb.Database -} - -// Trie is a Ethereum Merkle Patricia trie. -type Trie = ethstate.Trie - -// NewDatabase creates a backing store for state. The returned database is safe for -// concurrent use, but does not retain any recent trie nodes in memory. To keep some -// historical state in memory, use the NewDatabaseWithConfig constructor. -func NewDatabase(db ethdb.Database) Database { - return NewDatabaseWithConfig(db, nil) -} - -// NewDatabaseWithConfig creates a backing store for state. The returned database -// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a -// large memory cache. -func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database { - return &cachingDB{ - disk: db, - codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), - codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: triedb.NewDatabase(db, config), - } -} - -// NewDatabaseWithNodeDB creates a state database with an already initialized node database. -func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database { - return &cachingDB{ - disk: db, - codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), - codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: triedb, - } -} - -type cachingDB struct { - disk ethdb.KeyValueStore - codeSizeCache *lru.Cache[common.Hash, int] - codeCache *lru.SizeConstrainedCache[common.Hash, []byte] - triedb *triedb.Database -} - -// OpenTrie opens the main account trie at a specific root hash. -func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { - if db.triedb.IsVerkle() { - return trie.NewVerkleTrie(root, db.triedb, utils.NewPointCache(commitmentCacheItems)) - } - tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) - if err != nil { - return nil, err - } - return tr, nil -} - -// OpenStorageTrie opens the storage trie of an account. -func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) { - // In the verkle case, there is only one tree. But the two-tree structure - // is hardcoded in the codebase. So we need to return the same trie in this - // case. - if db.triedb.IsVerkle() { - return self, nil - } - tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) - if err != nil { - return nil, err - } - return tr, nil -} - -// CopyTrie returns an independent copy of the given trie. -func (db *cachingDB) CopyTrie(t Trie) Trie { - switch t := t.(type) { - case *trie.StateTrie: - return t.Copy() - default: - panic(fmt.Errorf("unknown trie type %T", t)) - } -} - -// ContractCode retrieves a particular contract's code. -func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) { - code, _ := db.codeCache.Get(codeHash) - if len(code) > 0 { - return code, nil - } - code = rawdb.ReadCode(db.disk, codeHash) - if len(code) > 0 { - db.codeCache.Add(codeHash, code) - db.codeSizeCache.Add(codeHash, len(code)) - return code, nil - } - return nil, errors.New("not found") -} - -// ContractCodeSize retrieves a particular contracts code's size. -func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) { - if cached, ok := db.codeSizeCache.Get(codeHash); ok { - return cached, nil - } - code, err := db.ContractCode(addr, codeHash) - return len(code), err +func NewDatabase(db ethdb.Database) ethstate.Database { + return ethstate.NewDatabase(db) } -// DiskDB returns the underlying key-value disk database. -func (db *cachingDB) DiskDB() ethdb.KeyValueStore { - return db.disk +func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) ethstate.Database { + return ethstate.NewDatabaseWithConfig(db, config) } -// TrieDB retrieves any intermediate trie-node caching layer. -func (db *cachingDB) TrieDB() *triedb.Database { - return db.triedb +func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) ethstate.Database { + return ethstate.NewDatabaseWithNodeDB(db, triedb) } diff --git a/core/state/pruner/bloom.go b/core/state/pruner/bloom.go index fe741461f4..8231d21b68 100644 --- a/core/state/pruner/bloom.go +++ b/core/state/pruner/bloom.go @@ -32,8 +32,8 @@ import ( "os" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" bloomfilter "github.com/holiman/bloomfilter/v2" ) diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 0ad5ee464b..82eca9b8f3 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -38,14 +38,15 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) const ( @@ -217,7 +218,7 @@ func prune(maindb ethdb.Database, stateBloom *stateBloom, bloomPath string, star // Write marker to DB to indicate offline pruning finished successfully. We write before calling os.RemoveAll // to guarantee that if the node dies midway through pruning, then this will run during RecoverPruning. - if err := rawdb.WriteOfflinePruning(maindb); err != nil { + if err := customrawdb.WriteOfflinePruning(maindb); err != nil { return fmt.Errorf("failed to write offline pruning success marker: %w", err) } diff --git a/core/state/snapshot/conversion.go b/core/state/snapshot/conversion.go index d48dadb853..46da66cbaa 100644 --- a/core/state/snapshot/conversion.go +++ b/core/state/snapshot/conversion.go @@ -36,12 +36,12 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) // trieKV represents a trie key-value pair diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go index 257315180e..e6a9ce8328 100644 --- a/core/state/snapshot/difflayer.go +++ b/core/state/snapshot/difflayer.go @@ -36,8 +36,8 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" bloomfilter "github.com/holiman/bloomfilter/v2" "golang.org/x/exp/slices" ) diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go index 817eb7d939..9698cebaef 100644 --- a/core/state/snapshot/disklayer.go +++ b/core/state/snapshot/disklayer.go @@ -32,11 +32,11 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/utils" ) diff --git a/core/state/snapshot/disklayer_test.go b/core/state/snapshot/disklayer_test.go index 023ac923e8..e76511789a 100644 --- a/core/state/snapshot/disklayer_test.go +++ b/core/state/snapshot/disklayer_test.go @@ -31,9 +31,10 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb/memorydb" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) // reverse reverses the contents of a byte slice. It's used to update random accs @@ -106,7 +107,7 @@ func TestDiskMerge(t *testing.T) { rawdb.WriteAccountSnapshot(db, conNukeCache, conNukeCache[:]) rawdb.WriteStorageSnapshot(db, conNukeCache, conNukeCacheSlot, conNukeCacheSlot[:]) - rawdb.WriteSnapshotBlockHash(db, baseBlockHash) + customrawdb.WriteSnapshotBlockHash(db, baseBlockHash) rawdb.WriteSnapshotRoot(db, baseRoot) // Create a disk layer based on the above and cache in some data @@ -297,7 +298,7 @@ func TestDiskPartialMerge(t *testing.T) { insertAccount(conNukeCache, conNukeCache[:]) insertStorage(conNukeCache, conNukeCacheSlot, conNukeCacheSlot[:]) - rawdb.WriteSnapshotBlockHash(db, baseBlockHash) + customrawdb.WriteSnapshotBlockHash(db, baseBlockHash) rawdb.WriteSnapshotRoot(db, baseRoot) // Create a disk layer based on the above using a random progress marker @@ -452,7 +453,7 @@ func TestDiskGeneratorPersistence(t *testing.T) { rawdb.WriteAccountSnapshot(db, accOne, accOne[:]) rawdb.WriteStorageSnapshot(db, accOne, accOneSlotOne, accOneSlotOne[:]) rawdb.WriteStorageSnapshot(db, accOne, accOneSlotTwo, accOneSlotTwo[:]) - rawdb.WriteSnapshotBlockHash(db, baseBlockHash) + customrawdb.WriteSnapshotBlockHash(db, baseBlockHash) rawdb.WriteSnapshotRoot(db, baseRoot) // Create a disk layer based on all above updates @@ -527,7 +528,7 @@ func TestDiskSeek(t *testing.T) { baseRoot := randomHash() baseBlockHash := randomHash() - rawdb.WriteSnapshotBlockHash(db, baseBlockHash) + customrawdb.WriteSnapshotBlockHash(db, baseBlockHash) rawdb.WriteSnapshotRoot(db, baseRoot) snaps := NewTestTree(db, baseBlockHash, baseRoot) diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index d8daf5d678..047b01b132 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -32,13 +32,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/utils" ) @@ -62,7 +63,7 @@ func generateSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, cache batch = diskdb.NewBatch() genMarker = []byte{} // Initialized but empty! ) - rawdb.WriteSnapshotBlockHash(batch, blockHash) + customrawdb.WriteSnapshotBlockHash(batch, blockHash) rawdb.WriteSnapshotRoot(batch, root) journalProgress(batch, genMarker, stats) if err := batch.Write(); err != nil { diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 6452850bba..718093e2c4 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -33,14 +33,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/triedb/hashdb" "github.com/ava-labs/subnet-evm/triedb/pathdb" "github.com/holiman/uint256" diff --git a/core/state/snapshot/iterator.go b/core/state/snapshot/iterator.go index fc62749843..46da2873f9 100644 --- a/core/state/snapshot/iterator.go +++ b/core/state/snapshot/iterator.go @@ -32,41 +32,18 @@ import ( "sort" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" ethsnapshot "github.com/ava-labs/libevm/core/state/snapshot" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/subnet-evm/core/rawdb" ) // Iterator is an iterator to step over all the accounts or the specific // storage in a snapshot which may or may not be composed of multiple layers. -type Iterator interface { - // Next steps the iterator forward one element, returning false if exhausted, - // or an error if iteration failed for some reason (e.g. root being iterated - // becomes stale and garbage collected). - Next() bool - - // Error returns any failure that occurred during iteration, which might have - // caused a premature iteration exit (e.g. snapshot stack becoming stale). - Error() error - - // Hash returns the hash of the account or storage slot the iterator is - // currently at. - Hash() common.Hash - - // Release releases associated resources. Release should always succeed and - // can be called multiple times without causing error. - Release() -} +type Iterator = ethsnapshot.Iterator // AccountIterator is an iterator to step over all the accounts in a snapshot, // which may or may not be composed of multiple layers. -type AccountIterator interface { - Iterator - - // Account returns the RLP encoded slim account the iterator is currently at. - // An error will be returned if the iterator becomes invalid - Account() []byte -} +type AccountIterator = ethsnapshot.AccountIterator // StorageIterator is an iterator to step over the specific storage in a snapshot, // which may or may not be composed of multiple layers. diff --git a/core/state/snapshot/iterator_test.go b/core/state/snapshot/iterator_test.go index 79d287b394..b522ce0db0 100644 --- a/core/state/snapshot/iterator_test.go +++ b/core/state/snapshot/iterator_test.go @@ -35,7 +35,7 @@ import ( "testing" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/libevm/core/rawdb" ) // TestAccountIteratorBasics tests some simple single-layer(diff and disk) iteration diff --git a/core/state/snapshot/journal.go b/core/state/snapshot/journal.go index 786b7af135..9215d03e4d 100644 --- a/core/state/snapshot/journal.go +++ b/core/state/snapshot/journal.go @@ -33,11 +33,12 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) // journalGenerator is a disk layer entry containing the generator progress marker. @@ -59,7 +60,7 @@ type journalGenerator struct { func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, cache int, blockHash, root common.Hash, noBuild bool) (snapshot, bool, error) { // Retrieve the block number and hash of the snapshot, failing if no snapshot // is present in the database (or crashed mid-update). - baseBlockHash := rawdb.ReadSnapshotBlockHash(diskdb) + baseBlockHash := customrawdb.ReadSnapshotBlockHash(diskdb) if baseBlockHash == (common.Hash{}) { return nil, false, errors.New("missing or corrupted snapshot, no snapshot block hash") } diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go index 3d39efb92a..4a6ccba927 100644 --- a/core/state/snapshot/snapshot.go +++ b/core/state/snapshot/snapshot.go @@ -35,13 +35,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" ethsnapshot "github.com/ava-labs/libevm/core/state/snapshot" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/libevm/stateconf" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) const ( @@ -636,7 +637,7 @@ func diffToDisk(bottom *diffLayer) (*diskLayer, bool, error) { base.abortGeneration() // Put the deletion in the batch writer, flush all updates in the final step. - rawdb.DeleteSnapshotBlockHash(batch) + customrawdb.DeleteSnapshotBlockHash(batch) rawdb.DeleteSnapshotRoot(batch) // Mark the original base as stale as we're going to create a new wrapper @@ -728,7 +729,7 @@ func diffToDisk(bottom *diffLayer) (*diskLayer, bool, error) { } } // Update the snapshot block marker and write any remainder data - rawdb.WriteSnapshotBlockHash(batch, bottom.blockHash) + customrawdb.WriteSnapshotBlockHash(batch, bottom.blockHash) rawdb.WriteSnapshotRoot(batch, bottom.root) // Write out the generator progress marker and report diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go index bd98f50140..06e6d5a1a1 100644 --- a/core/state/snapshot/snapshot_test.go +++ b/core/state/snapshot/snapshot_test.go @@ -34,9 +34,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/core/state/snapshot/utils.go b/core/state/snapshot/utils.go index af62b72686..020a7aee3c 100644 --- a/core/state/snapshot/utils.go +++ b/core/state/snapshot/utils.go @@ -32,9 +32,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" ) // CheckDanglingStorage iterates the snap storage data, and verifies that all diff --git a/core/state/snapshot/wipe.go b/core/state/snapshot/wipe.go index 451930ce69..7fe304a651 100644 --- a/core/state/snapshot/wipe.go +++ b/core/state/snapshot/wipe.go @@ -31,9 +31,10 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) // WipeSnapshot starts a goroutine to iterate over the entire key-value database @@ -43,7 +44,7 @@ import ( func WipeSnapshot(db ethdb.KeyValueStore, full bool) chan struct{} { // Wipe the snapshot root marker synchronously if full { - rawdb.DeleteSnapshotBlockHash(db) + customrawdb.DeleteSnapshotBlockHash(db) rawdb.DeleteSnapshotRoot(db) } // Wipe everything else asynchronously diff --git a/core/state/snapshot/wipe_test.go b/core/state/snapshot/wipe_test.go index 18d13311f7..9110ab971d 100644 --- a/core/state/snapshot/wipe_test.go +++ b/core/state/snapshot/wipe_test.go @@ -31,8 +31,9 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb/memorydb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) // Tests that given a database with random data content, all parts of a snapshot @@ -43,7 +44,7 @@ func TestWipe(t *testing.T) { for i := 0; i < 128; i++ { rawdb.WriteAccountSnapshot(db, randomHash(), randomHash().Bytes()) } - rawdb.WriteSnapshotBlockHash(db, randomHash()) + customrawdb.WriteSnapshotBlockHash(db, randomHash()) rawdb.WriteSnapshotRoot(db, randomHash()) // Add some random non-snapshot data too to make wiping harder @@ -70,7 +71,7 @@ func TestWipe(t *testing.T) { if items := count(); items != 128 { t.Fatalf("snapshot size mismatch: have %d, want %d", items, 128) } - if hash := rawdb.ReadSnapshotBlockHash(db); hash == (common.Hash{}) { + if hash := customrawdb.ReadSnapshotBlockHash(db); hash == (common.Hash{}) { t.Errorf("snapshot block hash marker mismatch: have %#x, want ", hash) } if hash := rawdb.ReadSnapshotRoot(db); hash == (common.Hash{}) { @@ -94,7 +95,7 @@ func TestWipe(t *testing.T) { t.Fatalf("misc item count mismatch: have %d, want %d", items, 1000) } - if hash := rawdb.ReadSnapshotBlockHash(db); hash != (common.Hash{}) { + if hash := customrawdb.ReadSnapshotBlockHash(db); hash != (common.Hash{}) { t.Errorf("snapshot block hash marker remained after wipe: %#x", hash) } if hash := rawdb.ReadSnapshotRoot(db); hash != (common.Hash{}) { diff --git a/core/state/state_test.go b/core/state/state_test.go index 4f2f6b792f..6bf027ae52 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -30,9 +30,9 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) type stateEnv struct { diff --git a/core/state/statedb.go b/core/state/statedb.go index f6073af670..211c926157 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -120,7 +120,7 @@ func (s *StateDB) Copy() *StateDB { } // NormalizeCoinID ORs the 0th bit of the first byte in -// [coinID], which ensures this bit will be 1 and all other +// `coinID`, which ensures this bit will be 1 and all other // bits are left the same. // This partitions multicoin storage from normal state storage. func NormalizeCoinID(coinID *common.Hash) { @@ -128,7 +128,7 @@ func NormalizeCoinID(coinID *common.Hash) { } // NormalizeStateKey ANDs the 0th bit of the first byte in -// [key], which ensures this bit will be 0 and all other bits +// `key`, which ensures this bit will be 0 and all other bits // are left the same. // This partitions normal state storage from multicoin storage. func NormalizeStateKey(key *common.Hash) { diff --git a/core/state/trie_prefetcher_extra_test.go b/core/state/trie_prefetcher_extra_test.go index 7246a1fc12..d899cce093 100644 --- a/core/state/trie_prefetcher_extra_test.go +++ b/core/state/trie_prefetcher_extra_test.go @@ -14,12 +14,12 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/metrics" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/triedb/hashdb" "github.com/stretchr/testify/require" ) diff --git a/core/state_manager.go b/core/state_manager.go index c6e3e40035..805c3ffd38 100644 --- a/core/state_manager.go +++ b/core/state_manager.go @@ -32,8 +32,8 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/subnet-evm/core/types" ) func init() { diff --git a/core/state_manager_test.go b/core/state_manager_test.go index 370117a858..13033358fc 100644 --- a/core/state_manager_test.go +++ b/core/state_manager_test.go @@ -7,7 +7,7 @@ import ( "math/big" "testing" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/common" "github.com/stretchr/testify/assert" diff --git a/core/state_processor.go b/core/state_processor.go index afb236f5f4..2b3b0a75be 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -31,12 +31,12 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) @@ -93,7 +93,6 @@ func (p *StateProcessor) Process(block *types.Block, parent *types.Header, state if beaconRoot := block.BeaconRoot(); beaconRoot != nil { ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) } - // Iterate over and process the individual transactions for i, tx := range block.Transactions() { msg, err := TransactionToMessage(tx, signer, header.BaseFee) @@ -126,6 +125,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta if err != nil { return nil, err } + // Update the state with pending changes. var root []byte if config.IsByzantium(blockNumber) { @@ -182,7 +182,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, blockContext // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // contract. This method is exported to be used in tests. -func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM, statedb *state.StateDB) { +func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with // the new root msg := &Message{ @@ -194,8 +194,8 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM, statedb *state. To: ¶ms.BeaconRootsStorageAddress, Data: beaconRoot[:], } - evm.Reset(NewEVMTxContext(msg), statedb) + vmenv.Reset(NewEVMTxContext(msg), statedb) statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress) - _, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) + _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) statedb.Finalise(true) } diff --git a/core/state_processor_ext.go b/core/state_processor_ext.go index 65af93ee91..36e865b010 100644 --- a/core/state_processor_ext.go +++ b/core/state_processor_ext.go @@ -1,4 +1,5 @@ -// (c) 2025, Ava Labs, Inc. +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. package core @@ -17,16 +18,17 @@ import ( ) // ApplyPrecompileActivations checks if any of the precompiles specified by the chain config are enabled or disabled by the block -// transition from [parentTimestamp] to the timestamp set in [blockContext]. If this is the case, it calls [Configure] +// transition from `parentTimestamp` to the timestamp set in `blockContext`. If this is the case, it calls [modules.Module]'s Configure // to apply the necessary state transitions for the upgrade. // This function is called within genesis setup to configure the starting state for precompiles enabled at genesis. -// In block processing and building, ApplyUpgrades is called instead which also applies state upgrades. +// In block processing and building, [ApplyUpgrades] is called instead which also applies state upgrades. func ApplyPrecompileActivations(c *params.ChainConfig, parentTimestamp *uint64, blockContext contract.ConfigurationBlockContext, statedb *state.StateDB) error { blockTimestamp := blockContext.Timestamp() - // Note: RegisteredModules returns precompiles sorted by module addresses. - // This ensures that the order we call Configure for each precompile is consistent. - // This ensures even if precompiles read/write state other than their own they will observe - // an identical global state in a deterministic order when they are configured. + // Note: [modules.RegisteredModules] returns precompiles sorted by module addresses. + // This ensures: + // - the order we call [modules.Module]'s Configure for each precompile is consistent + // - even if precompiles read/write state other than their own they will observe + // an identical global state in a deterministic order when they are configured. extra := params.GetExtra(c) for _, module := range modules.RegisteredModules() { for _, activatingConfig := range extra.GetActivatingPrecompileConfigs(module.Address, parentTimestamp, blockTimestamp, extra.PrecompileUpgrades) { @@ -35,32 +37,32 @@ func ApplyPrecompileActivations(c *params.ChainConfig, parentTimestamp *uint64, if activatingConfig.IsDisabled() { log.Info("Disabling precompile", "name", module.ConfigKey) statedb.SelfDestruct(module.Address) - // Calling Finalise here effectively commits Suicide call and wipes the contract state. + // Calling [state.StateDB]'s Finalise here effectively commits the SelfDestruct call and wipes the contract state. // This enables re-configuration of the same contract state in the same block. - // Without an immediate Finalise call after the Suicide, a reconfigured precompiled state can be wiped out - // since Suicide will be committed after the reconfiguration. + // Without an immediate Finalise call after the SelfDestruct, a reconfigured precompiled state can be wiped out + // since SelfDestruct will be committed after the reconfiguration. statedb.Finalise(true) + continue + } + var printIntf interface{} + marshalled, err := json.Marshal(activatingConfig) + if err == nil { + printIntf = string(marshalled) } else { - var printIntf interface{} - marshalled, err := json.Marshal(activatingConfig) - if err == nil { - printIntf = string(marshalled) - } else { - printIntf = activatingConfig - } + printIntf = activatingConfig + } - log.Info("Activating new precompile", "name", module.ConfigKey, "config", printIntf) - // Set the nonce of the precompile's address (as is done when a contract is created) to ensure - // that it is marked as non-empty and will not be cleaned up when the statedb is finalized. - statedb.SetNonce(module.Address, 1) - // Set the code of the precompile's address to a non-zero length byte slice to ensure that the precompile - // can be called from within Solidity contracts. Solidity adds a check before invoking a contract to ensure - // that it does not attempt to invoke a non-existent contract. - statedb.SetCode(module.Address, []byte{0x1}) - extstatedb := &extstate.StateDB{VmStateDB: statedb} - if err := module.Configure(params.GetExtra(c), activatingConfig, extstatedb, blockContext); err != nil { - return fmt.Errorf("could not configure precompile, name: %s, reason: %w", module.ConfigKey, err) - } + log.Info("Activating new precompile", "name", module.ConfigKey, "config", printIntf) + // Set the nonce of the precompile's address (as is done when a contract is created) to ensure + // that it is marked as non-empty and will not be cleaned up when the statedb is finalized. + statedb.SetNonce(module.Address, 1) + // Set the code of the precompile's address to a non-zero length byte slice to ensure that the precompile + // can be called from within Solidity contracts. Solidity adds a check before invoking a contract to ensure + // that it does not attempt to invoke a non-existent contract. + statedb.SetCode(module.Address, []byte{0x1}) + extstatedb := extstate.New(statedb) + if err := module.Configure(params.GetExtra(c), activatingConfig, extstatedb, blockContext); err != nil { + return fmt.Errorf("could not configure precompile, name: %s, reason: %w", module.ConfigKey, err) } } } @@ -95,17 +97,22 @@ func ApplyUpgrades(c *params.ChainConfig, parentTimestamp *uint64, blockContext return applyStateUpgrades(c, parentTimestamp, blockContext, statedb) } -type blockContext struct { +// BlockContext implements [contract.ConfigurationBlockContext]. +type BlockContext struct { number *big.Int timestamp uint64 } -func NewBlockContext(number *big.Int, timestamp uint64) *blockContext { - return &blockContext{ +// NewBlockContext creates a [BlockContext] using the block number +// and block timestamp provided. This function is usually necessary to convert +// a `*types.Block` to be passed as a [contract.ConfigurationBlockContext] +// to [ApplyUpgrades]. +func NewBlockContext(number *big.Int, timestamp uint64) *BlockContext { + return &BlockContext{ number: number, timestamp: timestamp, } } -func (bc *blockContext) Number() *big.Int { return bc.number } -func (bc *blockContext) Timestamp() uint64 { return bc.timestamp } +func (bc *BlockContext) Number() *big.Int { return bc.number } +func (bc *BlockContext) Timestamp() uint64 { return bc.timestamp } diff --git a/core/state_processor_ext_test.go b/core/state_processor_ext_test.go index 566bf7caae..272960b850 100644 --- a/core/state_processor_ext_test.go +++ b/core/state_processor_ext_test.go @@ -1,4 +1,5 @@ -// (c) 2025, Ava Labs, Inc. +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. package core @@ -7,11 +8,11 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist" diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 83861d7f5d..89c6f7f634 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -33,16 +33,17 @@ import ( "github.com/ava-labs/avalanchego/upgrade" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" "github.com/holiman/uint256" @@ -379,7 +380,8 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr } if params.GetExtra(config).IsSubnetEVM(header.Time) { - header.BlockGasCost = big.NewInt(0) + headerExtra := customtypes.GetHeaderExtra(header) + headerExtra.BlockGasCost = big.NewInt(0) } var receipts []*types.Receipt // The post-state result doesn't need to be correct (this is a bad block), but we do need something there diff --git a/core/state_transition.go b/core/state_transition.go index 18fa39f41d..e52a61fcb8 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -33,13 +33,13 @@ import ( "github.com/ava-labs/libevm/common" cmath "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto/kzg4844" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/vmerrors" "github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist" "github.com/ava-labs/subnet-evm/utils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/holiman/uint256" ) @@ -73,7 +73,7 @@ func (result *ExecutionResult) Return() []byte { // Revert returns the concrete revert reason if the execution is aborted by `REVERT` // opcode. Note the reason can be nil if no data supplied with revert opcode. func (result *ExecutionResult) Revert() []byte { - if result.Err != vmerrs.ErrExecutionReverted { + if result.Err != vm.ErrExecutionReverted { return nil } return common.CopyBytes(result.ReturnData) @@ -358,7 +358,7 @@ func (st *StateTransition) preCheck() error { if params.GetExtra(st.evm.ChainConfig()).IsPrecompileEnabled(txallowlist.ContractAddress, st.evm.Context.Time) { txAllowListRole := txallowlist.GetTxAllowListStatus(st.state, msg.From) if !txAllowListRole.IsEnabled() { - return fmt.Errorf("%w: %s", vmerrs.ErrSenderAddressNotAllowListed, msg.From) + return fmt.Errorf("%w: %s", vmerrors.ErrSenderAddressNotAllowListed, msg.From) } } } @@ -485,7 +485,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { // Check whether the init code size has been exceeded. if rulesExtra.IsDurango && contractCreation && len(msg.Data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", vmerrs.ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) + return nil, fmt.Errorf("%w: code size %v limit %v", vm.ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) } // Execute the preparatory steps for state transition which includes: diff --git a/core/test_blockchain.go b/core/test_blockchain.go index c2354ce500..663ca4a378 100644 --- a/core/test_blockchain.go +++ b/core/test_blockchain.go @@ -10,13 +10,13 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/precompile/allowlist" diff --git a/core/trie_stress_bench_test.go b/core/trie_stress_bench_test.go index 11b01bfa11..2e7b384ab9 100644 --- a/core/trie_stress_bench_test.go +++ b/core/trie_stress_bench_test.go @@ -32,8 +32,8 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/stretchr/testify/require" diff --git a/core/txindexer.go b/core/txindexer.go index 9d99e1a2ef..f7932b762f 100644 --- a/core/txindexer.go +++ b/core/txindexer.go @@ -20,9 +20,9 @@ import ( "fmt" "time" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" ) // TxIndexProgress is the struct describing the progress for transaction indexing. diff --git a/core/txindexer_test.go b/core/txindexer_test.go index b430c97e90..8d34e59ca8 100644 --- a/core/txindexer_test.go +++ b/core/txindexer_test.go @@ -22,11 +22,11 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/consensus/dummy" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/stretchr/testify/require" ) diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 4de018dc4d..d9ce1ec5f0 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -40,6 +40,7 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" @@ -48,7 +49,6 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/holiman/billy" diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 50fdb8de71..a583a317c2 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -40,6 +40,8 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/crypto/kzg4844" "github.com/ava-labs/libevm/ethdb/memorydb" @@ -48,10 +50,8 @@ import ( "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" diff --git a/core/txpool/blobpool/interface.go b/core/txpool/blobpool/interface.go index ced9bf3c50..0b7282c031 100644 --- a/core/txpool/blobpool/interface.go +++ b/core/txpool/blobpool/interface.go @@ -30,9 +30,9 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/core/txpool/blobpool/limbo.go b/core/txpool/blobpool/limbo.go index fbbaa674f2..bf133f7a3b 100644 --- a/core/txpool/blobpool/limbo.go +++ b/core/txpool/blobpool/limbo.go @@ -30,9 +30,9 @@ import ( "errors" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/billy" ) diff --git a/core/txpool/legacypool/journal.go b/core/txpool/legacypool/journal.go index cc81b03409..cc5e900947 100644 --- a/core/txpool/legacypool/journal.go +++ b/core/txpool/legacypool/journal.go @@ -33,9 +33,9 @@ import ( "os" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" ) // errNoActiveJournal is returned if a transaction is attempted to be inserted diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index d52f0848a9..45cadee9ff 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -38,6 +38,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/prque" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" @@ -45,7 +46,6 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" @@ -1793,13 +1793,14 @@ func (pool *LegacyPool) demoteUnexecutables() { } func (pool *LegacyPool) startPeriodicFeeUpdate() { - if params.GetExtra(pool.chainconfig).SubnetEVMTimestamp == nil { + subnetEVMTimestamp := params.GetExtra(pool.chainconfig).SubnetEVMTimestamp + if subnetEVMTimestamp == nil { return } // Call updateBaseFee here to ensure that there is not a [baseFeeUpdateInterval] delay - // when starting up in Subnet EVM before the base fee is updated. - if time.Now().After(utils.Uint64ToTime(params.GetExtra(pool.chainconfig).SubnetEVMTimestamp)) { + // when starting up in ApricotPhase3 before the base fee is updated. + if time.Now().After(utils.Uint64ToTime(subnetEVMTimestamp)) { pool.updateBaseFee() } @@ -1811,8 +1812,9 @@ func (pool *LegacyPool) periodicBaseFeeUpdate() { defer pool.wg.Done() // Sleep until its time to start the periodic base fee update or the tx pool is shutting down + subnetEVMTime := utils.Uint64ToTime(params.GetExtra(pool.chainconfig).SubnetEVMTimestamp) select { - case <-time.After(time.Until(utils.Uint64ToTime(params.GetExtra(pool.chainconfig).SubnetEVMTimestamp))): + case <-time.After(time.Until(subnetEVMTime)): case <-pool.generalShutdownChan: return // Return early if shutting down } diff --git a/core/txpool/legacypool/legacypool2_test.go b/core/txpool/legacypool/legacypool2_test.go index a36bdb02df..081958bcae 100644 --- a/core/txpool/legacypool/legacypool2_test.go +++ b/core/txpool/legacypool/legacypool2_test.go @@ -31,11 +31,11 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/event" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 035ffdac22..b1c56dfbfe 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -40,15 +40,15 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/holiman/uint256" ) diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go index 7bf2966ed1..89ababa830 100644 --- a/core/txpool/legacypool/list.go +++ b/core/txpool/legacypool/list.go @@ -36,7 +36,7 @@ import ( "time" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/holiman/uint256" "golang.org/x/exp/slices" ) diff --git a/core/txpool/legacypool/list_test.go b/core/txpool/legacypool/list_test.go index a37120a5a9..f0eea8c8ea 100644 --- a/core/txpool/legacypool/list_test.go +++ b/core/txpool/legacypool/list_test.go @@ -32,8 +32,8 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index e1668ca573..d68ef856de 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -31,9 +31,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 05e4bf7137..2f9872f2ed 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -34,11 +34,11 @@ import ( "sync/atomic" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" ) var ( diff --git a/core/txpool/validation.go b/core/txpool/validation.go index be02e7949f..813eff1981 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -32,14 +32,15 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto/kzg4844" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/vmerrors" "github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist" - "github.com/ava-labs/subnet-evm/vmerrs" ) var ( @@ -86,7 +87,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Check whether the init code size has been exceeded if opts.Config.IsShanghai(head.Number, head.Time) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - return fmt.Errorf("%w: code size %v, limit %v", vmerrs.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) + return fmt.Errorf("%w: code size %v, limit %v", vm.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) } // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur for transactions created using the RPC. @@ -277,7 +278,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op if params.GetRulesExtra(opts.Rules).IsPrecompileEnabled(txallowlist.ContractAddress) { txAllowListRole := txallowlist.GetTxAllowListStatus(opts.State, from) if !txAllowListRole.IsEnabled() { - return fmt.Errorf("%w: %s", vmerrs.ErrSenderAddressNotAllowListed, from) + return fmt.Errorf("%w: %s", vmerrors.ErrSenderAddressNotAllowListed, from) } } diff --git a/core/types.go b/core/types.go index 31a608585d..10aad3a204 100644 --- a/core/types.go +++ b/core/types.go @@ -27,9 +27,9 @@ package core import ( + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" ) // Validator is an interface which defines the standard for block validation. It diff --git a/core/types/account.go b/core/types/account.go deleted file mode 100644 index efc0927770..0000000000 --- a/core/types/account.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2024 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package types - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/libevm/common/math" -) - -//go:generate go run github.com/fjl/gencodec -type Account -field-override accountMarshaling -out gen_account.go - -// Account represents an Ethereum account and its attached data. -// This type is used to specify accounts in the genesis block state, and -// is also useful for JSON encoding/decoding of accounts. -type Account struct { - Code []byte `json:"code,omitempty"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty"` - Balance *big.Int `json:"balance" gencodec:"required"` - Nonce uint64 `json:"nonce,omitempty"` - - // used in tests - PrivateKey []byte `json:"secretKey,omitempty"` -} - -type accountMarshaling struct { - Code hexutil.Bytes - Balance *math.HexOrDecimal256 - Nonce math.HexOrDecimal64 - Storage map[storageJSON]storageJSON - PrivateKey hexutil.Bytes -} - -// storageJSON represents a 256 bit byte array, but allows less than 256 bits when -// unmarshaling from hex. -type storageJSON common.Hash - -func (h *storageJSON) UnmarshalText(text []byte) error { - text = bytes.TrimPrefix(text, []byte("0x")) - if len(text) > 64 { - return fmt.Errorf("too many hex characters in storage key/value %q", text) - } - offset := len(h) - len(text)/2 // pad on the left - if _, err := hex.Decode(h[offset:], text); err != nil { - return fmt.Errorf("invalid hex storage key/value %q", text) - } - return nil -} - -func (h storageJSON) MarshalText() ([]byte, error) { - return hexutil.Bytes(h[:]).MarshalText() -} - -// GenesisAlloc specifies the initial state of a genesis block. -type GenesisAlloc map[common.Address]Account - -func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { - m := make(map[common.UnprefixedAddress]Account) - if err := json.Unmarshal(data, &m); err != nil { - return err - } - *ga = make(GenesisAlloc) - for addr, a := range m { - (*ga)[common.Address(addr)] = a - } - return nil -} diff --git a/core/types/block.go b/core/types/block.go deleted file mode 100644 index fa234d9326..0000000000 --- a/core/types/block.go +++ /dev/null @@ -1,435 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Package types contains data types related to Ethereum consensus. -package types - -import ( - "encoding/binary" - "io" - "math/big" - "reflect" - "sync/atomic" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/libevm/rlp" -) - -// A BlockNonce is a 64-bit hash which proves (combined with the -// mix-hash) that a sufficient amount of computation has been carried -// out on a block. -type BlockNonce [8]byte - -// EncodeNonce converts the given integer to a block nonce. -func EncodeNonce(i uint64) BlockNonce { - var n BlockNonce - binary.BigEndian.PutUint64(n[:], i) - return n -} - -// Uint64 returns the integer value of a block nonce. -func (n BlockNonce) Uint64() uint64 { - return binary.BigEndian.Uint64(n[:]) -} - -// MarshalText encodes n as a hex string with 0x prefix. -func (n BlockNonce) MarshalText() ([]byte, error) { - return hexutil.Bytes(n[:]).MarshalText() -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (n *BlockNonce) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("BlockNonce", input, n[:]) -} - -//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go -//go:generate go run github.com/ava-labs/libevm/rlp/rlpgen -type Header -out gen_header_rlp.go - -// Header represents a block header in the Ethereum blockchain. -type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner" gencodec:"required"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *big.Int `json:"difficulty" gencodec:"required"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - - // BaseFee was added by EIP-1559 and is ignored in legacy headers. - BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` - - // BlockGasCost was added by SubnetEVM and is ignored in legacy - // headers. - BlockGasCost *big.Int `json:"blockGasCost" rlp:"optional"` - - // BlobGasUsed was added by EIP-4844 and is ignored in legacy headers. - BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` - - // ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers. - ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` - - // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` -} - -// field type overrides for gencodec -type headerMarshaling struct { - Difficulty *hexutil.Big - Number *hexutil.Big - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Time hexutil.Uint64 - Extra hexutil.Bytes - BaseFee *hexutil.Big - BlockGasCost *hexutil.Big - Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON - BlobGasUsed *hexutil.Uint64 - ExcessBlobGas *hexutil.Uint64 -} - -// Hash returns the block hash of the header, which is simply the keccak256 hash of its -// RLP encoding. -func (h *Header) Hash() common.Hash { - return rlpHash(h) -} - -var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) - -// Size returns the approximate memory used by all internal contents. It is used -// to approximate and limit the memory consumption of various caches. -func (h *Header) Size() common.StorageSize { - var baseFeeBits int - if h.BaseFee != nil { - baseFeeBits = h.BaseFee.BitLen() - } - return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+baseFeeBits)/8) -} - -// EmptyBody returns true if there is no additional 'body' to complete the header -// that is: no transactions and no uncles. -func (h *Header) EmptyBody() bool { - return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash -} - -// EmptyReceipts returns true if there are no receipts for this header/block. -func (h *Header) EmptyReceipts() bool { - return h.ReceiptHash == EmptyReceiptsHash -} - -// Body is a simple (mutable, non-safe) data container for storing and moving -// a block's data contents (transactions and uncles) together. -type Body struct { - Transactions []*Transaction - Uncles []*Header -} - -// Block represents an Ethereum block. -// -// Note the Block type tries to be 'immutable', and contains certain caches that rely -// on that. The rules around block immutability are as follows: -// -// - We copy all data when the block is constructed. This makes references held inside -// the block independent of whatever value was passed in. -// -// - We copy all header data on access. This is because any change to the header would mess -// up the cached hash and size values in the block. Calling code is expected to take -// advantage of this to avoid over-allocating! -// -// - When new body data is attached to the block, a shallow copy of the block is returned. -// This ensures block modifications are race-free. -// -// - We do not copy body data on access because it does not affect the caches, and also -// because it would be too expensive. -type Block struct { - header *Header - uncles []*Header - transactions Transactions - - // caches - hash atomic.Value - size atomic.Value -} - -// "external" block encoding. used for eth protocol, etc. -type extblock struct { - Header *Header - Txs []*Transaction - Uncles []*Header -} - -// NewBlock creates a new block. The input data is copied, changes to header and to the -// field values will not affect the block. -// -// The values of TxHash, UncleHash, ReceiptHash and Bloom in header -// are ignored and set to values derived from the given txs, uncles -// and receipts. -func NewBlock( - header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, hasher TrieHasher, -) *Block { - b := &Block{header: CopyHeader(header)} - - // TODO: panic if len(txs) != len(receipts) - if len(txs) == 0 { - b.header.TxHash = EmptyTxsHash - } else { - b.header.TxHash = DeriveSha(Transactions(txs), hasher) - b.transactions = make(Transactions, len(txs)) - copy(b.transactions, txs) - } - - if len(receipts) == 0 { - b.header.ReceiptHash = EmptyReceiptsHash - } else { - b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) - b.header.Bloom = CreateBloom(receipts) - } - - if len(uncles) == 0 { - b.header.UncleHash = EmptyUncleHash - } else { - b.header.UncleHash = CalcUncleHash(uncles) - b.uncles = make([]*Header, len(uncles)) - for i := range uncles { - b.uncles[i] = CopyHeader(uncles[i]) - } - } - - return b -} - -// CopyHeader creates a deep copy of a block header. -func CopyHeader(h *Header) *Header { - cpy := *h - if cpy.Difficulty = new(big.Int); h.Difficulty != nil { - cpy.Difficulty.Set(h.Difficulty) - } - if cpy.Number = new(big.Int); h.Number != nil { - cpy.Number.Set(h.Number) - } - if h.BaseFee != nil { - cpy.BaseFee = new(big.Int).Set(h.BaseFee) - } - if h.BlockGasCost != nil { - cpy.BlockGasCost = new(big.Int).Set(h.BlockGasCost) - } - if len(h.Extra) > 0 { - cpy.Extra = make([]byte, len(h.Extra)) - copy(cpy.Extra, h.Extra) - } - if h.ExcessBlobGas != nil { - cpy.ExcessBlobGas = new(uint64) - *cpy.ExcessBlobGas = *h.ExcessBlobGas - } - if h.BlobGasUsed != nil { - cpy.BlobGasUsed = new(uint64) - *cpy.BlobGasUsed = *h.BlobGasUsed - } - if h.ParentBeaconRoot != nil { - cpy.ParentBeaconRoot = new(common.Hash) - *cpy.ParentBeaconRoot = *h.ParentBeaconRoot - } - return &cpy -} - -// DecodeRLP decodes a block from RLP. -func (b *Block) DecodeRLP(s *rlp.Stream) error { - var eb extblock - _, size, _ := s.Kind() - if err := s.Decode(&eb); err != nil { - return err - } - b.header, b.uncles, b.transactions = eb.Header, eb.Uncles, eb.Txs - b.size.Store(rlp.ListSize(size)) - return nil -} - -// EncodeRLP serializes a block as RLP. -func (b *Block) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, &extblock{ - Header: b.header, - Txs: b.transactions, - Uncles: b.uncles, - }) -} - -// Body returns the non-header content of the block. -// Note the returned data is not an independent copy. -func (b *Block) Body() *Body { - return &Body{b.transactions, b.uncles} -} - -// Accessors for body data. These do not return a copy because the content -// of the body slices does not affect the cached hash/size in block. - -func (b *Block) Uncles() []*Header { return b.uncles } -func (b *Block) Transactions() Transactions { return b.transactions } - -func (b *Block) Transaction(hash common.Hash) *Transaction { - for _, transaction := range b.transactions { - if transaction.Hash() == hash { - return transaction - } - } - return nil -} - -// Header returns the block header (as a copy). -func (b *Block) Header() *Header { - return CopyHeader(b.header) -} - -// Header value accessors. These do copy! - -func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } -func (b *Block) GasLimit() uint64 { return b.header.GasLimit } -func (b *Block) GasUsed() uint64 { return b.header.GasUsed } -func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } -func (b *Block) Time() uint64 { return b.header.Time } - -func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } -func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } -func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } -func (b *Block) Bloom() Bloom { return b.header.Bloom } -func (b *Block) Coinbase() common.Address { return b.header.Coinbase } -func (b *Block) Root() common.Hash { return b.header.Root } -func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } -func (b *Block) TxHash() common.Hash { return b.header.TxHash } -func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash } -func (b *Block) UncleHash() common.Hash { return b.header.UncleHash } -func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } - -func (b *Block) BaseFee() *big.Int { - if b.header.BaseFee == nil { - return nil - } - return new(big.Int).Set(b.header.BaseFee) -} - -func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot } - -func (b *Block) ExcessBlobGas() *uint64 { - var excessBlobGas *uint64 - if b.header.ExcessBlobGas != nil { - excessBlobGas = new(uint64) - *excessBlobGas = *b.header.ExcessBlobGas - } - return excessBlobGas -} - -func (b *Block) BlobGasUsed() *uint64 { - var blobGasUsed *uint64 - if b.header.BlobGasUsed != nil { - blobGasUsed = new(uint64) - *blobGasUsed = *b.header.BlobGasUsed - } - return blobGasUsed -} - -func (b *Block) BlockGasCost() *big.Int { - if b.header.BlockGasCost == nil { - return nil - } - return new(big.Int).Set(b.header.BlockGasCost) -} - -// Size returns the true RLP encoded storage size of the block, either by encoding -// and returning it, or returning a previously cached value. -func (b *Block) Size() uint64 { - if size := b.size.Load(); size != nil { - return size.(uint64) - } - c := writeCounter(0) - rlp.Encode(&c, b) - b.size.Store(uint64(c)) - return uint64(c) -} - -type writeCounter uint64 - -func (c *writeCounter) Write(b []byte) (int, error) { - *c += writeCounter(len(b)) - return len(b), nil -} - -func CalcUncleHash(uncles []*Header) common.Hash { - if len(uncles) == 0 { - return EmptyUncleHash - } - return rlpHash(uncles) -} - -// NewBlockWithHeader creates a block with the given header data. The -// header data is copied, changes to header and to the field values -// will not affect the block. -func NewBlockWithHeader(header *Header) *Block { - return &Block{header: CopyHeader(header)} -} - -// WithSeal returns a new block with the data from b but the header replaced with -// the sealed one. -func (b *Block) WithSeal(header *Header) *Block { - return &Block{ - header: CopyHeader(header), - transactions: b.transactions, - uncles: b.uncles, - } -} - -// WithBody returns a copy of the block with the given transaction and uncle contents. -func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block { - block := &Block{ - header: b.header, - transactions: make([]*Transaction, len(transactions)), - uncles: make([]*Header, len(uncles)), - } - copy(block.transactions, transactions) - for i := range uncles { - block.uncles[i] = CopyHeader(uncles[i]) - } - return block -} - -// Hash returns the keccak256 hash of b's header. -// The hash is computed on the first call and cached thereafter. -func (b *Block) Hash() common.Hash { - if hash := b.hash.Load(); hash != nil { - return hash.(common.Hash) - } - v := b.header.Hash() - b.hash.Store(v) - return v -} - -type Blocks []*Block diff --git a/core/types/gen_account.go b/core/types/gen_account.go deleted file mode 100644 index c3c7fb3fdf..0000000000 --- a/core/types/gen_account.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/libevm/common/math" -) - -var _ = (*accountMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (a Account) MarshalJSON() ([]byte, error) { - type Account struct { - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey hexutil.Bytes `json:"secretKey,omitempty"` - } - var enc Account - enc.Code = a.Code - if a.Storage != nil { - enc.Storage = make(map[storageJSON]storageJSON, len(a.Storage)) - for k, v := range a.Storage { - enc.Storage[storageJSON(k)] = storageJSON(v) - } - } - enc.Balance = (*math.HexOrDecimal256)(a.Balance) - enc.Nonce = math.HexOrDecimal64(a.Nonce) - enc.PrivateKey = a.PrivateKey - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (a *Account) UnmarshalJSON(input []byte) error { - type Account struct { - Code *hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"` - } - var dec Account - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Code != nil { - a.Code = *dec.Code - } - if dec.Storage != nil { - a.Storage = make(map[common.Hash]common.Hash, len(dec.Storage)) - for k, v := range dec.Storage { - a.Storage[common.Hash(k)] = common.Hash(v) - } - } - if dec.Balance == nil { - return errors.New("missing required field 'balance' for Account") - } - a.Balance = (*big.Int)(dec.Balance) - if dec.Nonce != nil { - a.Nonce = uint64(*dec.Nonce) - } - if dec.PrivateKey != nil { - a.PrivateKey = *dec.PrivateKey - } - return nil -} diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go deleted file mode 100644 index 3921526a6b..0000000000 --- a/core/types/gen_header_json.go +++ /dev/null @@ -1,168 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/common/hexutil" -) - -var _ = (*headerMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (h Header) MarshalJSON() ([]byte, error) { - type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner" gencodec:"required"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - BlockGasCost *hexutil.Big `json:"blockGasCost" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - Hash common.Hash `json:"hash"` - } - var enc Header - enc.ParentHash = h.ParentHash - enc.UncleHash = h.UncleHash - enc.Coinbase = h.Coinbase - enc.Root = h.Root - enc.TxHash = h.TxHash - enc.ReceiptHash = h.ReceiptHash - enc.Bloom = h.Bloom - enc.Difficulty = (*hexutil.Big)(h.Difficulty) - enc.Number = (*hexutil.Big)(h.Number) - enc.GasLimit = hexutil.Uint64(h.GasLimit) - enc.GasUsed = hexutil.Uint64(h.GasUsed) - enc.Time = hexutil.Uint64(h.Time) - enc.Extra = h.Extra - enc.MixDigest = h.MixDigest - enc.Nonce = h.Nonce - enc.BaseFee = (*hexutil.Big)(h.BaseFee) - enc.BlockGasCost = (*hexutil.Big)(h.BlockGasCost) - enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed) - enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas) - enc.ParentBeaconRoot = h.ParentBeaconRoot - enc.Hash = h.Hash() - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (h *Header) UnmarshalJSON(input []byte) error { - type Header struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase *common.Address `json:"miner" gencodec:"required"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom *Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - BlockGasCost *hexutil.Big `json:"blockGasCost" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - } - var dec Header - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.ParentHash == nil { - return errors.New("missing required field 'parentHash' for Header") - } - h.ParentHash = *dec.ParentHash - if dec.UncleHash == nil { - return errors.New("missing required field 'sha3Uncles' for Header") - } - h.UncleHash = *dec.UncleHash - if dec.Coinbase == nil { - return errors.New("missing required field 'miner' for Header") - } - h.Coinbase = *dec.Coinbase - if dec.Root == nil { - return errors.New("missing required field 'stateRoot' for Header") - } - h.Root = *dec.Root - if dec.TxHash == nil { - return errors.New("missing required field 'transactionsRoot' for Header") - } - h.TxHash = *dec.TxHash - if dec.ReceiptHash == nil { - return errors.New("missing required field 'receiptsRoot' for Header") - } - h.ReceiptHash = *dec.ReceiptHash - if dec.Bloom == nil { - return errors.New("missing required field 'logsBloom' for Header") - } - h.Bloom = *dec.Bloom - if dec.Difficulty == nil { - return errors.New("missing required field 'difficulty' for Header") - } - h.Difficulty = (*big.Int)(dec.Difficulty) - if dec.Number == nil { - return errors.New("missing required field 'number' for Header") - } - h.Number = (*big.Int)(dec.Number) - if dec.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for Header") - } - h.GasLimit = uint64(*dec.GasLimit) - if dec.GasUsed == nil { - return errors.New("missing required field 'gasUsed' for Header") - } - h.GasUsed = uint64(*dec.GasUsed) - if dec.Time == nil { - return errors.New("missing required field 'timestamp' for Header") - } - h.Time = uint64(*dec.Time) - if dec.Extra == nil { - return errors.New("missing required field 'extraData' for Header") - } - h.Extra = *dec.Extra - if dec.MixDigest != nil { - h.MixDigest = *dec.MixDigest - } - if dec.Nonce != nil { - h.Nonce = *dec.Nonce - } - if dec.BaseFee != nil { - h.BaseFee = (*big.Int)(dec.BaseFee) - } - if dec.BlockGasCost != nil { - h.BlockGasCost = (*big.Int)(dec.BlockGasCost) - } - if dec.BlobGasUsed != nil { - h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) - } - if dec.ExcessBlobGas != nil { - h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - if dec.ParentBeaconRoot != nil { - h.ParentBeaconRoot = dec.ParentBeaconRoot - } - return nil -} diff --git a/core/types/hashes.go b/core/types/hashes.go deleted file mode 100644 index f40d2e7336..0000000000 --- a/core/types/hashes.go +++ /dev/null @@ -1,63 +0,0 @@ -// (c) 2023, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2023 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package types - -import ( - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/libevm/log" -) - -var ( - // EmptyRootHash is the known root hash of an empty merkle trie. - EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyUncleHash is the known hash of the empty uncle set. - EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 - - // EmptyCodeHash is the known hash of the empty EVM bytecode. - EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 - - // EmptyTxsHash is the known hash of the empty transaction set. - EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyReceiptsHash is the known hash of the empty receipt set. - EmptyReceiptsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyVerkleHash is the known hash of an empty verkle trie. - EmptyVerkleHash = common.Hash{} -) - -// TrieRootHash returns the hash itself if it's non-empty or the predefined -// emptyHash one instead. -func TrieRootHash(hash common.Hash) common.Hash { - if hash == (common.Hash{}) { - log.Error("Zero trie root hash!") - return EmptyRootHash - } - return hash -} diff --git a/core/types/hashing.go b/core/types/hashing.go deleted file mode 100644 index b6b631c7bc..0000000000 --- a/core/types/hashing.go +++ /dev/null @@ -1,114 +0,0 @@ -// (c) 2019-2021, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2021 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package types - -import ( - "bytes" - "sync" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/libevm/rlp" - "golang.org/x/crypto/sha3" -) - -// hasherPool holds LegacyKeccak256 hashers for rlpHash. -var hasherPool = sync.Pool{ - New: func() interface{} { return sha3.NewLegacyKeccak256() }, -} - -// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. -var encodeBufferPool = sync.Pool{ - New: func() interface{} { return new(bytes.Buffer) }, -} - -// rlpHash encodes x and hashes the encoded bytes. -func rlpHash(x interface{}) (h common.Hash) { - sha := hasherPool.Get().(crypto.KeccakState) - defer hasherPool.Put(sha) - sha.Reset() - rlp.Encode(sha, x) - sha.Read(h[:]) - return h -} - -// TrieHasher is the tool used to calculate the hash of derivable list. -// This is internal, do not use. -type TrieHasher interface { - Reset() - Update([]byte, []byte) error - Hash() common.Hash -} - -// DerivableList is the input to DeriveSha. -// It is implemented by the 'Transactions' and 'Receipts' types. -// This is internal, do not use these methods. -type DerivableList interface { - Len() int - EncodeIndex(int, *bytes.Buffer) -} - -func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte { - buf.Reset() - list.EncodeIndex(i, buf) - // It's really unfortunate that we need to perform this copy. - // StackTrie holds onto the values until Hash is called, so the values - // written to it must not alias. - return common.CopyBytes(buf.Bytes()) -} - -// DeriveSha creates the tree hashes of transactions, receipts, and withdrawals in a block header. -func DeriveSha(list DerivableList, hasher TrieHasher) common.Hash { - hasher.Reset() - - valueBuf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(valueBuf) - - // StackTrie requires values to be inserted in increasing hash order, which is not the - // order that `list` provides hashes in. This insertion sequence ensures that the - // order is correct. - // - // The error returned by hasher is omitted because hasher will produce an incorrect - // hash in case any error occurs. - var indexBuf []byte - for i := 1; i < list.Len() && i <= 0x7f; i++ { - indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) - value := encodeForDerive(list, i, valueBuf) - hasher.Update(indexBuf, value) - } - if list.Len() > 0 { - indexBuf = rlp.AppendUint64(indexBuf[:0], 0) - value := encodeForDerive(list, 0, valueBuf) - hasher.Update(indexBuf, value) - } - for i := 0x80; i < list.Len(); i++ { - indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) - value := encodeForDerive(list, i, valueBuf) - hasher.Update(indexBuf, value) - } - return hasher.Hash() -} diff --git a/core/types/imports.go b/core/types/imports.go deleted file mode 100644 index 81c661d959..0000000000 --- a/core/types/imports.go +++ /dev/null @@ -1,77 +0,0 @@ -// (c) 2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package types - -import ( - ethtypes "github.com/ava-labs/libevm/core/types" -) - -// The following types are used directly as their upstream definitions. -// So we list them all here to avoid having many individual files. -type ( - AccessList = ethtypes.AccessList - AccessTuple = ethtypes.AccessTuple - AccessListTx = ethtypes.AccessListTx - Bloom = ethtypes.Bloom - Receipt = ethtypes.Receipt - Receipts = ethtypes.Receipts - ReceiptForStorage = ethtypes.ReceiptForStorage - LegacyTx = ethtypes.LegacyTx - DynamicFeeTx = ethtypes.DynamicFeeTx - BlobTx = ethtypes.BlobTx - BlobTxSidecar = ethtypes.BlobTxSidecar - Signer = ethtypes.Signer - HomesteadSigner = ethtypes.HomesteadSigner - FrontierSigner = ethtypes.FrontierSigner - - Transaction = ethtypes.Transaction - Transactions = ethtypes.Transactions - TxByNonce = ethtypes.TxByNonce - TxData = ethtypes.TxData -) - -// The following constants are used directly as their upstream definitions. -const ( - BloomBitLength = ethtypes.BloomBitLength - BloomByteLength = ethtypes.BloomByteLength - ReceiptStatusFailed = ethtypes.ReceiptStatusFailed - ReceiptStatusSuccessful = ethtypes.ReceiptStatusSuccessful - - // Transaction types. - LegacyTxType = ethtypes.LegacyTxType - AccessListTxType = ethtypes.AccessListTxType - DynamicFeeTxType = ethtypes.DynamicFeeTxType - BlobTxType = ethtypes.BlobTxType -) - -// The following functions are used directly as their upstream definitions. -var ( - BloomLookup = ethtypes.BloomLookup - BytesToBloom = ethtypes.BytesToBloom - CreateBloom = ethtypes.CreateBloom - NewReceipt = ethtypes.NewReceipt - NewContractCreation = ethtypes.NewContractCreation - NewTransaction = ethtypes.NewTransaction - - // Signers - NewEIP155Signer = ethtypes.NewEIP155Signer - NewEIP2930Signer = ethtypes.NewEIP2930Signer - NewLondonSigner = ethtypes.NewLondonSigner - NewCancunSigner = ethtypes.NewCancunSigner - MakeSigner = ethtypes.MakeSigner - LatestSigner = ethtypes.LatestSigner - LatestSignerForChainID = ethtypes.LatestSignerForChainID - SignTx = ethtypes.SignTx - SignNewTx = ethtypes.SignNewTx - MustSignNewTx = ethtypes.MustSignNewTx - Sender = ethtypes.Sender - - // Transactions - NewTx = ethtypes.NewTx - TxDifference = ethtypes.TxDifference - - // Errors - ErrTxTypeNotSupported = ethtypes.ErrTxTypeNotSupported - ErrGasFeeCapTooLow = ethtypes.ErrGasFeeCapTooLow -) diff --git a/core/types/log.go b/core/types/log.go deleted file mode 100644 index 5ddb090034..0000000000 --- a/core/types/log.go +++ /dev/null @@ -1,42 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package types - -import ethtypes "github.com/ava-labs/libevm/core/types" - -// Log represents a contract log event. These events are generated by the LOG opcode and -// stored/indexed by the node. -type Log = ethtypes.Log - -// FlattenLogs converts a nested array of logs to a single array of logs. -func FlattenLogs(list [][]*Log) []*Log { - var flat []*Log - for _, logs := range list { - flat = append(flat, logs...) - } - return flat -} diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 65aa12d933..7a5c5e14b2 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -31,11 +31,11 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 653a6cbdae..51b2adf245 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -35,14 +35,14 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/core/asm" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/tracers" "github.com/ava-labs/subnet-evm/params" diff --git a/eth/api_admin.go b/eth/api_admin.go index 3e25d62e0e..bc26c7da2f 100644 --- a/eth/api_admin.go +++ b/eth/api_admin.go @@ -34,9 +34,9 @@ import ( "os" "strings" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" ) // AdminAPI is the collection of Ethereum full node related APIs for node diff --git a/eth/api_backend.go b/eth/api_backend.go index 05eeff7844..dab0eec90b 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -34,6 +34,7 @@ import ( "github.com/ava-labs/libevm/accounts" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" @@ -43,7 +44,6 @@ import ( "github.com/ava-labs/subnet-evm/core/bloombits" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/gasprice" "github.com/ava-labs/subnet-evm/eth/tracers" "github.com/ava-labs/subnet-evm/params" diff --git a/eth/api_backend_test.go b/eth/api_backend_test.go index 4b9be62dbc..b4cef1abd8 100644 --- a/eth/api_backend_test.go +++ b/eth/api_backend_test.go @@ -31,8 +31,8 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/eth/api_debug.go b/eth/api_debug.go index 067523775f..0dbff3ca00 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -34,13 +34,13 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/rpc" ) diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go index 02d339ca10..ea583a0c30 100644 --- a/eth/api_debug_test.go +++ b/eth/api_debug_test.go @@ -33,17 +33,14 @@ import ( "strings" "testing" + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/holiman/uint256" - "github.com/davecgh/go-spew/spew" - - "github.com/ava-labs/libevm/common" - "github.com/ava-labs/libevm/crypto" - + "github.com/holiman/uint256" "golang.org/x/exp/slices" ) diff --git a/eth/backend.go b/eth/backend.go index cccde7c5f1..c748b8f2a2 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -37,6 +37,8 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/libevm/accounts" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" @@ -44,11 +46,9 @@ import ( "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/pruner" "github.com/ava-labs/subnet-evm/core/txpool" "github.com/ava-labs/subnet-evm/core/txpool/legacypool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/ethconfig" "github.com/ava-labs/subnet-evm/eth/filters" "github.com/ava-labs/subnet-evm/eth/gasprice" @@ -58,6 +58,7 @@ import ( "github.com/ava-labs/subnet-evm/miner" "github.com/ava-labs/subnet-evm/node" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/rpc" ) @@ -418,13 +419,13 @@ func (s *Ethereum) precheckPopulateMissingTries() error { if s.config.PopulateMissingTries == nil { // Delete the populate missing tries marker to indicate that the node started with // populate missing tries disabled. - if err := rawdb.DeletePopulateMissingTries(s.chainDb); err != nil { + if err := customrawdb.DeletePopulateMissingTries(s.chainDb); err != nil { return fmt.Errorf("failed to write populate missing tries disabled marker: %w", err) } return nil } - if lastRun, err := rawdb.ReadPopulateMissingTries(s.chainDb); err == nil { + if lastRun, err := customrawdb.ReadPopulateMissingTries(s.chainDb); err == nil { log.Error("Populate missing tries is not meant to be left enabled permanently. Please disable populate missing tries and allow your node to start successfully before running again.") return fmt.Errorf("cannot start chain with populate missing tries enabled on consecutive starts (last=%v)", lastRun) } @@ -441,7 +442,7 @@ func (s *Ethereum) handleOfflinePruning(cacheConfig *core.CacheConfig, gspec *co if !s.config.OfflinePruning { // Delete the offline pruning marker to indicate that the node started with offline pruning disabled. - if err := rawdb.DeleteOfflinePruning(s.chainDb); err != nil { + if err := customrawdb.DeleteOfflinePruning(s.chainDb); err != nil { return fmt.Errorf("failed to write offline pruning disabled marker: %w", err) } return nil @@ -451,7 +452,7 @@ func (s *Ethereum) handleOfflinePruning(cacheConfig *core.CacheConfig, gspec *co // to the last accepted block before pruning begins. // If offline pruning marker is on disk, then we force the node to be started with offline pruning disabled // before allowing another run of offline pruning. - if lastRun, err := rawdb.ReadOfflinePruning(s.chainDb); err == nil { + if lastRun, err := customrawdb.ReadOfflinePruning(s.chainDb); err == nil { log.Error("Offline pruning is not meant to be left enabled permanently. Please disable offline pruning and allow your node to start successfully before running offline pruning again.") return fmt.Errorf("cannot start chain with offline pruning enabled on consecutive starts (last=%v)", lastRun) } diff --git a/eth/bloombits.go b/eth/bloombits.go index 40fb97de96..775b0c708d 100644 --- a/eth/bloombits.go +++ b/eth/bloombits.go @@ -30,7 +30,7 @@ import ( "time" "github.com/ava-labs/libevm/common/bitutil" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/libevm/core/rawdb" ) const ( diff --git a/eth/chain_with_final_block.go b/eth/chain_with_final_block.go index d67f33144f..0b390f7cb7 100644 --- a/eth/chain_with_final_block.go +++ b/eth/chain_with_final_block.go @@ -2,8 +2,8 @@ package eth import ( + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" ) const blocksToKeep = 604_800 // Approx. 2 weeks worth of blocks assuming 2s block time diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go new file mode 100644 index 0000000000..844e0137f5 --- /dev/null +++ b/eth/ethconfig/gen_config.go @@ -0,0 +1,273 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package ethconfig + +import ( + "time" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/subnet-evm/core" + "github.com/ava-labs/subnet-evm/core/txpool/blobpool" + "github.com/ava-labs/subnet-evm/core/txpool/legacypool" + "github.com/ava-labs/subnet-evm/eth/gasprice" + "github.com/ava-labs/subnet-evm/miner" +) + +// MarshalTOML marshals as TOML. +func (c Config) MarshalTOML() (interface{}, error) { + type Config struct { + Genesis *core.Genesis `toml:",omitempty"` + NetworkId uint64 + Pruning bool + AcceptorQueueLimit int + CommitInterval uint64 + PopulateMissingTries *uint64 + PopulateMissingTriesParallelism int + AllowMissingTries bool + SnapshotDelayInit bool + SnapshotWait bool + SnapshotVerify bool + SkipSnapshotRebuild bool + SkipBcVersionCheck bool `toml:"-"` + TrieCleanCache int + TrieDirtyCache int + TrieDirtyCommitTarget int + TriePrefetcherParallelism int + SnapshotCache int + Preimages bool + AcceptedCacheSize int + Miner miner.Config + TxPool legacypool.Config + BlobPool blobpool.Config + GPO gasprice.Config + EnablePreimageRecording bool + RPCGasCap uint64 `toml:",omitempty"` + RPCEVMTimeout time.Duration + RPCTxFeeCap float64 `toml:",omitempty"` + AllowUnfinalizedQueries bool + HistoricalProofQueryWindow uint64 + AllowUnprotectedTxs bool + AllowUnprotectedTxHashes []common.Hash + OfflinePruning bool + OfflinePruningBloomFilterSize uint64 + OfflinePruningDataDirectory string + SkipUpgradeCheck bool + TransactionHistory uint64 `toml:",omitempty"` + StateHistory uint64 `toml:",omitempty"` + StateScheme string `toml:",omitempty"` + SkipTxIndexing bool + } + var enc Config + enc.Genesis = c.Genesis + enc.NetworkId = c.NetworkId + enc.Pruning = c.Pruning + enc.AcceptorQueueLimit = c.AcceptorQueueLimit + enc.CommitInterval = c.CommitInterval + enc.PopulateMissingTries = c.PopulateMissingTries + enc.PopulateMissingTriesParallelism = c.PopulateMissingTriesParallelism + enc.AllowMissingTries = c.AllowMissingTries + enc.SnapshotDelayInit = c.SnapshotDelayInit + enc.SnapshotWait = c.SnapshotWait + enc.SnapshotVerify = c.SnapshotVerify + enc.SkipSnapshotRebuild = c.SkipSnapshotRebuild + enc.SkipBcVersionCheck = c.SkipBcVersionCheck + enc.TrieCleanCache = c.TrieCleanCache + enc.TrieDirtyCache = c.TrieDirtyCache + enc.TrieDirtyCommitTarget = c.TrieDirtyCommitTarget + enc.TriePrefetcherParallelism = c.TriePrefetcherParallelism + enc.SnapshotCache = c.SnapshotCache + enc.Preimages = c.Preimages + enc.AcceptedCacheSize = c.AcceptedCacheSize + enc.Miner = c.Miner + enc.TxPool = c.TxPool + enc.BlobPool = c.BlobPool + enc.GPO = c.GPO + enc.EnablePreimageRecording = c.EnablePreimageRecording + enc.RPCGasCap = c.RPCGasCap + enc.RPCEVMTimeout = c.RPCEVMTimeout + enc.RPCTxFeeCap = c.RPCTxFeeCap + enc.AllowUnfinalizedQueries = c.AllowUnfinalizedQueries + enc.HistoricalProofQueryWindow = c.HistoricalProofQueryWindow + enc.AllowUnprotectedTxs = c.AllowUnprotectedTxs + enc.AllowUnprotectedTxHashes = c.AllowUnprotectedTxHashes + enc.OfflinePruning = c.OfflinePruning + enc.OfflinePruningBloomFilterSize = c.OfflinePruningBloomFilterSize + enc.OfflinePruningDataDirectory = c.OfflinePruningDataDirectory + enc.SkipUpgradeCheck = c.SkipUpgradeCheck + enc.TransactionHistory = c.TransactionHistory + enc.StateHistory = c.StateHistory + enc.StateScheme = c.StateScheme + enc.SkipTxIndexing = c.SkipTxIndexing + return &enc, nil +} + +// UnmarshalTOML unmarshals from TOML. +func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { + type Config struct { + Genesis *core.Genesis `toml:",omitempty"` + NetworkId *uint64 + Pruning *bool + AcceptorQueueLimit *int + CommitInterval *uint64 + PopulateMissingTries *uint64 + PopulateMissingTriesParallelism *int + AllowMissingTries *bool + SnapshotDelayInit *bool + SnapshotWait *bool + SnapshotVerify *bool + SkipSnapshotRebuild *bool + SkipBcVersionCheck *bool `toml:"-"` + TrieCleanCache *int + TrieDirtyCache *int + TrieDirtyCommitTarget *int + TriePrefetcherParallelism *int + SnapshotCache *int + Preimages *bool + AcceptedCacheSize *int + Miner *miner.Config + TxPool *legacypool.Config + BlobPool *blobpool.Config + GPO *gasprice.Config + EnablePreimageRecording *bool + RPCGasCap *uint64 `toml:",omitempty"` + RPCEVMTimeout *time.Duration + RPCTxFeeCap *float64 `toml:",omitempty"` + AllowUnfinalizedQueries *bool + HistoricalProofQueryWindow *uint64 + AllowUnprotectedTxs *bool + AllowUnprotectedTxHashes []common.Hash + OfflinePruning *bool + OfflinePruningBloomFilterSize *uint64 + OfflinePruningDataDirectory *string + SkipUpgradeCheck *bool + TransactionHistory *uint64 `toml:",omitempty"` + StateHistory *uint64 `toml:",omitempty"` + StateScheme *string `toml:",omitempty"` + SkipTxIndexing *bool + } + var dec Config + if err := unmarshal(&dec); err != nil { + return err + } + if dec.Genesis != nil { + c.Genesis = dec.Genesis + } + if dec.NetworkId != nil { + c.NetworkId = *dec.NetworkId + } + if dec.Pruning != nil { + c.Pruning = *dec.Pruning + } + if dec.AcceptorQueueLimit != nil { + c.AcceptorQueueLimit = *dec.AcceptorQueueLimit + } + if dec.CommitInterval != nil { + c.CommitInterval = *dec.CommitInterval + } + if dec.PopulateMissingTries != nil { + c.PopulateMissingTries = dec.PopulateMissingTries + } + if dec.PopulateMissingTriesParallelism != nil { + c.PopulateMissingTriesParallelism = *dec.PopulateMissingTriesParallelism + } + if dec.AllowMissingTries != nil { + c.AllowMissingTries = *dec.AllowMissingTries + } + if dec.SnapshotDelayInit != nil { + c.SnapshotDelayInit = *dec.SnapshotDelayInit + } + if dec.SnapshotWait != nil { + c.SnapshotWait = *dec.SnapshotWait + } + if dec.SnapshotVerify != nil { + c.SnapshotVerify = *dec.SnapshotVerify + } + if dec.SkipSnapshotRebuild != nil { + c.SkipSnapshotRebuild = *dec.SkipSnapshotRebuild + } + if dec.SkipBcVersionCheck != nil { + c.SkipBcVersionCheck = *dec.SkipBcVersionCheck + } + if dec.TrieCleanCache != nil { + c.TrieCleanCache = *dec.TrieCleanCache + } + if dec.TrieDirtyCache != nil { + c.TrieDirtyCache = *dec.TrieDirtyCache + } + if dec.TrieDirtyCommitTarget != nil { + c.TrieDirtyCommitTarget = *dec.TrieDirtyCommitTarget + } + if dec.TriePrefetcherParallelism != nil { + c.TriePrefetcherParallelism = *dec.TriePrefetcherParallelism + } + if dec.SnapshotCache != nil { + c.SnapshotCache = *dec.SnapshotCache + } + if dec.Preimages != nil { + c.Preimages = *dec.Preimages + } + if dec.AcceptedCacheSize != nil { + c.AcceptedCacheSize = *dec.AcceptedCacheSize + } + if dec.Miner != nil { + c.Miner = *dec.Miner + } + if dec.TxPool != nil { + c.TxPool = *dec.TxPool + } + if dec.BlobPool != nil { + c.BlobPool = *dec.BlobPool + } + if dec.GPO != nil { + c.GPO = *dec.GPO + } + if dec.EnablePreimageRecording != nil { + c.EnablePreimageRecording = *dec.EnablePreimageRecording + } + if dec.RPCGasCap != nil { + c.RPCGasCap = *dec.RPCGasCap + } + if dec.RPCEVMTimeout != nil { + c.RPCEVMTimeout = *dec.RPCEVMTimeout + } + if dec.RPCTxFeeCap != nil { + c.RPCTxFeeCap = *dec.RPCTxFeeCap + } + if dec.AllowUnfinalizedQueries != nil { + c.AllowUnfinalizedQueries = *dec.AllowUnfinalizedQueries + } + if dec.HistoricalProofQueryWindow != nil { + c.HistoricalProofQueryWindow = *dec.HistoricalProofQueryWindow + } + if dec.AllowUnprotectedTxs != nil { + c.AllowUnprotectedTxs = *dec.AllowUnprotectedTxs + } + if dec.AllowUnprotectedTxHashes != nil { + c.AllowUnprotectedTxHashes = dec.AllowUnprotectedTxHashes + } + if dec.OfflinePruning != nil { + c.OfflinePruning = *dec.OfflinePruning + } + if dec.OfflinePruningBloomFilterSize != nil { + c.OfflinePruningBloomFilterSize = *dec.OfflinePruningBloomFilterSize + } + if dec.OfflinePruningDataDirectory != nil { + c.OfflinePruningDataDirectory = *dec.OfflinePruningDataDirectory + } + if dec.SkipUpgradeCheck != nil { + c.SkipUpgradeCheck = *dec.SkipUpgradeCheck + } + if dec.TransactionHistory != nil { + c.TransactionHistory = *dec.TransactionHistory + } + if dec.StateHistory != nil { + c.StateHistory = *dec.StateHistory + } + if dec.StateScheme != nil { + c.StateScheme = *dec.StateScheme + } + if dec.SkipTxIndexing != nil { + c.SkipTxIndexing = *dec.SkipTxIndexing + } + return nil +} diff --git a/eth/filters/api.go b/eth/filters/api.go index 490ac562e9..9666baf49c 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -35,11 +35,11 @@ import ( "sync" "time" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/rpc" ) @@ -333,12 +333,12 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc ) if api.sys.backend.IsAllowUnfinalizedQueries() { - logsSub, err = api.events.SubscribeLogs(interfaces.FilterQuery(crit), matchedLogs) + logsSub, err = api.events.SubscribeLogs(ethereum.FilterQuery(crit), matchedLogs) if err != nil { return nil, err } } else { - logsSub, err = api.events.SubscribeAcceptedLogs(interfaces.FilterQuery(crit), matchedLogs) + logsSub, err = api.events.SubscribeAcceptedLogs(ethereum.FilterQuery(crit), matchedLogs) if err != nil { return nil, err } @@ -364,8 +364,8 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc } // FilterCriteria represents a request to create a new filter. -// Same as interfaces.FilterQuery but with UnmarshalJSON() method. -type FilterCriteria interfaces.FilterQuery +// Same as [ethereum.FilterQuery] with the method [FilterCriteria.UnmarshalJSON]. +type FilterCriteria ethereum.FilterQuery // NewFilter creates a new filter and returns the filter id. It can be // used to retrieve logs when the state changes. This method cannot be @@ -386,12 +386,12 @@ func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) { ) if api.sys.backend.IsAllowUnfinalizedQueries() { - logsSub, err = api.events.SubscribeLogs(interfaces.FilterQuery(crit), logs) + logsSub, err = api.events.SubscribeLogs(ethereum.FilterQuery(crit), logs) if err != nil { return "", err } } else { - logsSub, err = api.events.SubscribeAcceptedLogs(interfaces.FilterQuery(crit), logs) + logsSub, err = api.events.SubscribeAcceptedLogs(ethereum.FilterQuery(crit), logs) if err != nil { return "", err } diff --git a/eth/filters/bench_test.go b/eth/filters/bench_test.go index b25775b42d..ec81feb9a4 100644 --- a/eth/filters/bench_test.go +++ b/eth/filters/bench_test.go @@ -34,10 +34,10 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/bitutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) func BenchmarkBloomBits512(b *testing.B) { diff --git a/eth/filters/filter.go b/eth/filters/filter.go index d84bbfe333..0f04d89be3 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -33,8 +33,9 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/rpc" ) @@ -341,7 +342,7 @@ func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*typ return nil, err } - unfiltered := types.FlattenLogs(logsList) + unfiltered := customtypes.FlattenLogs(logsList) logs := filterLogs(unfiltered, nil, nil, f.addresses, f.topics) if len(logs) == 0 { return nil, nil diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index 941e056129..5d83f3d9b2 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -34,14 +34,14 @@ import ( "sync" "time" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" ) @@ -162,7 +162,7 @@ type subscription struct { id rpc.ID typ Type created time.Time - logsCrit interfaces.FilterQuery + logsCrit ethereum.FilterQuery logs chan []*types.Log txs chan []*types.Transaction headers chan *types.Header @@ -288,7 +288,7 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription { // SubscribeLogs creates a subscription that will write all logs matching the // given criteria to the given logs channel. Default value for the from and to // block is "latest". If the fromBlock > toBlock an error is returned. -func (es *EventSystem) SubscribeLogs(crit interfaces.FilterQuery, logs chan []*types.Log) (*Subscription, error) { +func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) { if len(crit.Topics) > maxTopics { return nil, errExceedMaxTopics } @@ -327,7 +327,7 @@ func (es *EventSystem) SubscribeLogs(crit interfaces.FilterQuery, logs chan []*t return nil, errInvalidBlockRange } -func (es *EventSystem) SubscribeAcceptedLogs(crit interfaces.FilterQuery, logs chan []*types.Log) (*Subscription, error) { +func (es *EventSystem) SubscribeAcceptedLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) { var from, to rpc.BlockNumber if crit.FromBlock == nil { from = rpc.LatestBlockNumber @@ -352,7 +352,7 @@ func (es *EventSystem) SubscribeAcceptedLogs(crit interfaces.FilterQuery, logs c return nil, fmt.Errorf("invalid from and to block combination: from > to") } -func (es *EventSystem) subscribeAcceptedLogs(crit interfaces.FilterQuery, logs chan []*types.Log) *Subscription { +func (es *EventSystem) subscribeAcceptedLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { sub := &subscription{ id: rpc.NewID(), typ: AcceptedLogsSubscription, @@ -369,7 +369,7 @@ func (es *EventSystem) subscribeAcceptedLogs(crit interfaces.FilterQuery, logs c // subscribeMinedPendingLogs creates a subscription that returned mined and // pending logs that match the given criteria. -func (es *EventSystem) subscribeMinedPendingLogs(crit interfaces.FilterQuery, logs chan []*types.Log) *Subscription { +func (es *EventSystem) subscribeMinedPendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { sub := &subscription{ id: rpc.NewID(), typ: MinedAndPendingLogsSubscription, @@ -386,7 +386,7 @@ func (es *EventSystem) subscribeMinedPendingLogs(crit interfaces.FilterQuery, lo // subscribeLogs creates a subscription that will write all logs matching the // given criteria to the given logs channel. -func (es *EventSystem) subscribeLogs(crit interfaces.FilterQuery, logs chan []*types.Log) *Subscription { +func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { sub := &subscription{ id: rpc.NewID(), typ: LogsSubscription, @@ -403,7 +403,7 @@ func (es *EventSystem) subscribeLogs(crit interfaces.FilterQuery, logs chan []*t // subscribePendingLogs creates a subscription that writes contract event logs for // transactions that enter the transaction pool. -func (es *EventSystem) subscribePendingLogs(crit interfaces.FilterQuery, logs chan []*types.Log) *Subscription { +func (es *EventSystem) subscribePendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { sub := &subscription{ id: rpc.NewID(), typ: PendingLogsSubscription, diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 70028206d5..8e24bb3eee 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -37,17 +37,18 @@ import ( "testing" "time" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/rpc" "github.com/stretchr/testify/require" ) @@ -97,7 +98,7 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe switch blockNr { case rpc.FinalizedBlockNumber: var err error - hash, err = rawdb.ReadAcceptorTip(b.db) + hash, err = customrawdb.ReadAcceptorTip(b.db) if err != nil { return nil, err } @@ -658,7 +659,7 @@ func TestPendingLogsSubscription(t *testing.T) { pendingBlockNumber = big.NewInt(rpc.PendingBlockNumber.Int64()) testCases = []struct { - crit interfaces.FilterQuery + crit ethereum.FilterQuery expected []*types.Log c chan []*types.Log sub *Subscription @@ -666,67 +667,67 @@ func TestPendingLogsSubscription(t *testing.T) { }{ // match all { - interfaces.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, flattenLogs(allLogs), nil, nil, nil, }, // match none due to no matching addresses { - interfaces.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, nil, nil, nil, nil, }, // match logs based on addresses, ignore topics { - interfaces.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, append(flattenLogs(allLogs[:2]), allLogs[5][3]), nil, nil, nil, }, // match none due to no matching topics (match with address) { - interfaces.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, nil, nil, nil, nil, }, // match logs based on addresses and topics { - interfaces.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, append(flattenLogs(allLogs[3:5]), allLogs[5][0]), nil, nil, nil, }, // match logs based on multiple addresses and "or" topics { - interfaces.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, append(flattenLogs(allLogs[2:5]), allLogs[5][0]), nil, nil, nil, }, // multiple pending logs, should match only 2 topics from the logs in block 5 { - interfaces.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, + ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, []*types.Log{allLogs[5][0], allLogs[5][2]}, nil, nil, nil, }, // match none due to only matching new mined logs { - interfaces.FilterQuery{}, + ethereum.FilterQuery{}, nil, nil, nil, nil, }, // match none due to only matching mined logs within a specific block range { - interfaces.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, + ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, nil, nil, nil, nil, }, // match all due to matching mined and pending logs { - interfaces.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, + ethereum.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, flattenLogs(allLogs), nil, nil, nil, }, // match none due to matching logs from a specific block number to new mined blocks { - interfaces.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, + ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, nil, nil, nil, nil, }, diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 76ed3e1941..3ac00e252a 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -35,15 +35,16 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/rpc" "github.com/stretchr/testify/require" ) @@ -273,7 +274,7 @@ func TestFilters(t *testing.T) { // Set block 998 as Finalized (-3) // bc.SetFinalized(chain[998].Header()) - err = rawdb.WriteAcceptorTip(db, chain[998].Hash()) + err = customrawdb.WriteAcceptorTip(db, chain[998].Hash()) require.NoError(t, err) for i, tc := range []struct { diff --git a/eth/gasestimator/gasestimator.go b/eth/gasestimator/gasestimator.go index 23c492391c..ecb009a8da 100644 --- a/eth/gasestimator/gasestimator.go +++ b/eth/gasestimator/gasestimator.go @@ -34,13 +34,12 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" - "github.com/ava-labs/subnet-evm/vmerrs" ) // Options are the contextual parameters to execute the requested call. @@ -128,7 +127,7 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin return 0, nil, err } if failed { - if result != nil && !errors.Is(result.Err, vmerrs.ErrOutOfGas) { + if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) { return 0, result.Revert(), result.Err } return 0, nil, fmt.Errorf("gas required exceeds allowance (%d)", hi) diff --git a/eth/gasprice/fee_info_provider.go b/eth/gasprice/fee_info_provider.go index d4e5ee531b..9518c61433 100644 --- a/eth/gasprice/fee_info_provider.go +++ b/eth/gasprice/fee_info_provider.go @@ -30,8 +30,8 @@ import ( "context" "math/big" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/rpc" lru "github.com/hashicorp/golang-lru" ) diff --git a/eth/gasprice/fee_info_provider_test.go b/eth/gasprice/fee_info_provider_test.go index 1a128482a1..4ae6b5763d 100644 --- a/eth/gasprice/fee_info_provider_test.go +++ b/eth/gasprice/fee_info_provider_test.go @@ -9,8 +9,8 @@ import ( "sync" "testing" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/stretchr/testify/require" ) diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go index 5805179793..1d9e8b557c 100644 --- a/eth/gasprice/feehistory.go +++ b/eth/gasprice/feehistory.go @@ -34,8 +34,8 @@ import ( "slices" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/rpc" ) diff --git a/eth/gasprice/feehistory_test.go b/eth/gasprice/feehistory_test.go index 34da967adb..9041b0bcaf 100644 --- a/eth/gasprice/feehistory_test.go +++ b/eth/gasprice/feehistory_test.go @@ -32,8 +32,8 @@ import ( "math/big" "testing" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/stretchr/testify/require" "github.com/ava-labs/libevm/common" diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 39d9dcdcdc..ad76d85952 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -34,11 +34,11 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/lru" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index b6d8d2acb1..dd12719853 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -33,14 +33,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/event" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 9e83f25424..f06b0eb4d7 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -33,14 +33,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/tracers" ) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 76b05cc175..c52d793e97 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -39,6 +39,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/libevm/ethdb" @@ -47,7 +48,6 @@ import ( "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" diff --git a/eth/tracers/api_extra_test.go b/eth/tracers/api_extra_test.go index fcb2aa9263..ffd29c7e8f 100644 --- a/eth/tracers/api_extra_test.go +++ b/eth/tracers/api_extra_test.go @@ -15,9 +15,9 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 7bb989d28d..d5bb0b7d0d 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -39,6 +39,8 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/eth/tracers/logger" @@ -46,9 +48,7 @@ import ( "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/ethapi" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" diff --git a/eth/tracers/tracers.go b/eth/tracers/tracers.go index e235b4c5e6..2f0a0a8dab 100644 --- a/eth/tracers/tracers.go +++ b/eth/tracers/tracers.go @@ -18,10 +18,6 @@ package tracers import ( - "errors" - "fmt" - - "github.com/ava-labs/libevm/core/vm" ethtracers "github.com/ava-labs/libevm/eth/tracers" ) @@ -36,26 +32,6 @@ type Tracer = ethtracers.Tracer // DefaultDirectory is the collection of tracers bundled by default. var DefaultDirectory = ethtracers.DefaultDirectory -const ( - memoryPadLimit = 1024 * 1024 -) - // GetMemoryCopyPadded returns offset + size as a new slice. // It zero-pads the slice if it extends beyond memory bounds. -func GetMemoryCopyPadded(m *vm.Memory, offset, size int64) ([]byte, error) { - if offset < 0 || size < 0 { - return nil, errors.New("offset or size must not be negative") - } - if int(offset+size) < m.Len() { // slice fully inside memory - return m.GetCopy(offset, size), nil - } - paddingNeeded := int(offset+size) - m.Len() - if paddingNeeded > memoryPadLimit { - return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded) - } - cpy := make([]byte, size) - if overlap := int64(m.Len()) - offset; overlap > 0 { - copy(cpy, m.GetPtr(offset, overlap)) - } - return cpy, nil -} +var GetMemoryCopyPadded = ethtracers.GetMemoryCopyPadded diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index b8dffad3b9..7a9d0e7789 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -31,12 +31,12 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/eth/tracers/logger" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/tests" ) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index a87c10df8e..a7f192ed2f 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -34,10 +34,11 @@ import ( "fmt" "math/big" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" @@ -54,14 +55,14 @@ var ( _ bind.ContractTransactor = (*client)(nil) _ bind.DeployBackend = (*client)(nil) - _ interfaces.ChainReader = (*client)(nil) - _ interfaces.ChainStateReader = (*client)(nil) - _ interfaces.TransactionReader = (*client)(nil) - _ interfaces.TransactionSender = (*client)(nil) - _ interfaces.ContractCaller = (*client)(nil) - _ interfaces.GasEstimator = (*client)(nil) - _ interfaces.GasPricer = (*client)(nil) - _ interfaces.LogFilterer = (*client)(nil) + _ ethereum.ChainReader = (*client)(nil) + _ ethereum.ChainStateReader = (*client)(nil) + _ ethereum.TransactionReader = (*client)(nil) + _ ethereum.TransactionSender = (*client)(nil) + _ ethereum.ContractCaller = (*client)(nil) + _ ethereum.GasEstimator = (*client)(nil) + _ ethereum.GasPricer = (*client)(nil) + _ ethereum.LogFilterer = (*client)(nil) _ interfaces.AcceptedStateReader = (*client)(nil) _ interfaces.AcceptedContractCaller = (*client)(nil) @@ -86,9 +87,9 @@ type Client interface { TransactionInBlock(context.Context, common.Hash, uint) (*types.Transaction, error) TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) SyncProgress(ctx context.Context) error - SubscribeNewAcceptedTransactions(context.Context, chan<- *common.Hash) (interfaces.Subscription, error) - SubscribeNewPendingTransactions(context.Context, chan<- *common.Hash) (interfaces.Subscription, error) - SubscribeNewHead(context.Context, chan<- *types.Header) (interfaces.Subscription, error) + SubscribeNewAcceptedTransactions(context.Context, chan<- *common.Hash) (ethereum.Subscription, error) + SubscribeNewPendingTransactions(context.Context, chan<- *common.Hash) (ethereum.Subscription, error) + SubscribeNewHead(context.Context, chan<- *types.Header) (ethereum.Subscription, error) NetworkID(context.Context) (*big.Int, error) BalanceAt(context.Context, common.Address, *big.Int) (*big.Int, error) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) @@ -98,17 +99,17 @@ type Client interface { CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) NonceAt(context.Context, common.Address, *big.Int) (uint64, error) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) - FilterLogs(context.Context, interfaces.FilterQuery) ([]types.Log, error) - SubscribeFilterLogs(context.Context, interfaces.FilterQuery, chan<- types.Log) (interfaces.Subscription, error) + FilterLogs(context.Context, ethereum.FilterQuery) ([]types.Log, error) + SubscribeFilterLogs(context.Context, ethereum.FilterQuery, chan<- types.Log) (ethereum.Subscription, error) AcceptedCodeAt(context.Context, common.Address) ([]byte, error) AcceptedNonceAt(context.Context, common.Address) (uint64, error) - AcceptedCallContract(context.Context, interfaces.CallMsg) ([]byte, error) - CallContract(context.Context, interfaces.CallMsg, *big.Int) ([]byte, error) - CallContractAtHash(ctx context.Context, msg interfaces.CallMsg, blockHash common.Hash) ([]byte, error) + AcceptedCallContract(context.Context, ethereum.CallMsg) ([]byte, error) + CallContract(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error) + CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) SuggestGasPrice(context.Context) (*big.Int, error) SuggestGasTipCap(context.Context) (*big.Int, error) - FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*interfaces.FeeHistory, error) - EstimateGas(context.Context, interfaces.CallMsg) (uint64, error) + FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) + EstimateGas(context.Context, ethereum.CallMsg) (uint64, error) EstimateBaseFee(context.Context) (*big.Int, error) SendTransaction(context.Context, *types.Transaction) error } @@ -198,7 +199,7 @@ func (ec *client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumb var r []*types.Receipt err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) if err == nil && r == nil { - return nil, interfaces.NotFound + return nil, ethereum.NotFound } return r, err } @@ -225,7 +226,7 @@ func (ec *client) getBlock(ctx context.Context, method string, args ...interface } // When the block is not found, the API returns JSON null. if head == nil { - return nil, interfaces.NotFound + return nil, ethereum.NotFound } var body rpcBlock @@ -277,7 +278,11 @@ func (ec *client) getBlock(ctx context.Context, method string, args ...interface } txs[i] = tx.tx } - return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil + return types.NewBlockWithHeader(head).WithBody( + types.Body{ + Transactions: txs, + Uncles: uncles, + }), nil } // HeaderByHash returns the block header with the given hash. @@ -285,7 +290,7 @@ func (ec *client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.He var head *types.Header err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) if err == nil && head == nil { - err = interfaces.NotFound + err = ethereum.NotFound } return head, err } @@ -296,7 +301,7 @@ func (ec *client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H var head *types.Header err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", ToBlockNumArg(number), false) if err == nil && head == nil { - err = interfaces.NotFound + err = ethereum.NotFound } return head, err } @@ -326,7 +331,7 @@ func (ec *client) TransactionByHash(ctx context.Context, hash common.Hash) (tx * if err != nil { return nil, false, err } else if json == nil { - return nil, false, interfaces.NotFound + return nil, false, ethereum.NotFound } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { return nil, false, errors.New("server returned transaction without signature") } @@ -378,7 +383,7 @@ func (ec *client) TransactionInBlock(ctx context.Context, blockHash common.Hash, return nil, err } if json == nil { - return nil, interfaces.NotFound + return nil, ethereum.NotFound } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { return nil, errors.New("server returned transaction without signature") } @@ -394,7 +399,7 @@ func (ec *client) TransactionReceipt(ctx context.Context, txHash common.Hash) (* var r *types.Receipt err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) if err == nil && r == nil { - return nil, interfaces.NotFound + return nil, ethereum.NotFound } return r, err } @@ -418,7 +423,7 @@ func (ec *client) SyncProgress(ctx context.Context) error { } // SubscribeNewAcceptedTransactions subscribes to notifications about the accepted transaction hashes on the given channel. -func (ec *client) SubscribeNewAcceptedTransactions(ctx context.Context, ch chan<- *common.Hash) (interfaces.Subscription, error) { +func (ec *client) SubscribeNewAcceptedTransactions(ctx context.Context, ch chan<- *common.Hash) (ethereum.Subscription, error) { sub, err := ec.c.EthSubscribe(ctx, ch, "newAcceptedTransactions") if err != nil { // Defensively prefer returning nil interface explicitly on error-path, instead @@ -430,7 +435,7 @@ func (ec *client) SubscribeNewAcceptedTransactions(ctx context.Context, ch chan< } // SubscribeNewPendingTransactions subscribes to notifications about the pending transaction hashes on the given channel. -func (ec *client) SubscribeNewPendingTransactions(ctx context.Context, ch chan<- *common.Hash) (interfaces.Subscription, error) { +func (ec *client) SubscribeNewPendingTransactions(ctx context.Context, ch chan<- *common.Hash) (ethereum.Subscription, error) { sub, err := ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") if err != nil { // Defensively prefer returning nil interface explicitly on error-path, instead @@ -443,7 +448,7 @@ func (ec *client) SubscribeNewPendingTransactions(ctx context.Context, ch chan<- // SubscribeNewHead subscribes to notifications about the current blockchain head // on the given channel. -func (ec *client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (interfaces.Subscription, error) { +func (ec *client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads") if err != nil { // Defensively prefer returning nil interface explicitly on error-path, instead @@ -532,7 +537,7 @@ func (ec *client) NonceAtHash(ctx context.Context, account common.Address, block // Filters // FilterLogs executes a filter query. -func (ec *client) FilterLogs(ctx context.Context, q interfaces.FilterQuery) ([]types.Log, error) { +func (ec *client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { var result []types.Log arg, err := toFilterArg(q) if err != nil { @@ -543,7 +548,7 @@ func (ec *client) FilterLogs(ctx context.Context, q interfaces.FilterQuery) ([]t } // SubscribeFilterLogs subscribes to the results of a streaming filter query. -func (ec *client) SubscribeFilterLogs(ctx context.Context, q interfaces.FilterQuery, ch chan<- types.Log) (interfaces.Subscription, error) { +func (ec *client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { arg, err := toFilterArg(q) if err != nil { return nil, err @@ -558,7 +563,7 @@ func (ec *client) SubscribeFilterLogs(ctx context.Context, q interfaces.FilterQu return sub, nil } -func toFilterArg(q interfaces.FilterQuery) (interface{}, error) { +func toFilterArg(q ethereum.FilterQuery) (interface{}, error) { arg := map[string]interface{}{ "address": q.Addresses, "topics": q.Topics, @@ -592,7 +597,7 @@ func (ec *client) AcceptedNonceAt(ctx context.Context, account common.Address) ( // AcceptedCallContract executes a message call transaction in the accepted // state. -func (ec *client) AcceptedCallContract(ctx context.Context, msg interfaces.CallMsg) ([]byte, error) { +func (ec *client) AcceptedCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { return ec.CallContract(ctx, msg, nil) } @@ -604,7 +609,7 @@ func (ec *client) AcceptedCallContract(ctx context.Context, msg interfaces.CallM // blockNumber selects the block height at which the call runs. It can be nil, in which // case the code is taken from the latest known block. Note that state from very old // blocks might not be available. -func (ec *client) CallContract(ctx context.Context, msg interfaces.CallMsg, blockNumber *big.Int) ([]byte, error) { +func (ec *client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { var hex hexutil.Bytes err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), ToBlockNumArg(blockNumber)) if err != nil { @@ -615,7 +620,7 @@ func (ec *client) CallContract(ctx context.Context, msg interfaces.CallMsg, bloc // CallContractAtHash is almost the same as CallContract except that it selects // the block by block hash instead of block height. -func (ec *client) CallContractAtHash(ctx context.Context, msg interfaces.CallMsg, blockHash common.Hash) ([]byte, error) { +func (ec *client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) { var hex hexutil.Bytes err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) if err != nil { @@ -652,7 +657,7 @@ type feeHistoryResultMarshaling struct { } // FeeHistory retrieves the fee market history. -func (ec *client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*interfaces.FeeHistory, error) { +func (ec *client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { var res feeHistoryResultMarshaling if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), ToBlockNumArg(lastBlock), rewardPercentiles); err != nil { return nil, err @@ -668,7 +673,7 @@ func (ec *client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock * for i, b := range res.BaseFee { baseFee[i] = (*big.Int)(b) } - return &interfaces.FeeHistory{ + return ðereum.FeeHistory{ OldestBlock: (*big.Int)(res.OldestBlock), Reward: reward, BaseFee: baseFee, @@ -680,7 +685,7 @@ func (ec *client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock * // the current pending state of the backend blockchain. There is no guarantee that this is // the true gas limit requirement as other transactions may be added or removed by miners, // but it should provide a basis for setting a reasonable default. -func (ec *client) EstimateGas(ctx context.Context, msg interfaces.CallMsg) (uint64, error) { +func (ec *client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { var hex hexutil.Uint64 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) if err != nil { @@ -728,7 +733,7 @@ func ToBlockNumArg(number *big.Int) string { return fmt.Sprintf("", number) } -func toCallArg(msg interfaces.CallMsg) interface{} { +func toCallArg(msg ethereum.CallMsg) interface{} { arg := map[string]interface{}{ "from": msg.From, "to": msg.To, diff --git a/ethclient/signer.go b/ethclient/signer.go index 2b5b400348..b570896a35 100644 --- a/ethclient/signer.go +++ b/ethclient/signer.go @@ -31,7 +31,7 @@ import ( "math/big" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) // senderFromServer is a types.Signer that remembers the sender address returned by the RPC diff --git a/ethclient/simulated/backend.go b/ethclient/simulated/backend.go index 6b167e5c8c..b44c0225f1 100644 --- a/ethclient/simulated/backend.go +++ b/ethclient/simulated/backend.go @@ -22,12 +22,13 @@ import ( "time" "github.com/ava-labs/avalanchego/utils/timer/mockable" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/constants" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth" "github.com/ava-labs/subnet-evm/eth/ethconfig" "github.com/ava-labs/subnet-evm/ethclient" @@ -45,20 +46,20 @@ func (*fakePushGossiper) Add(*types.Transaction) {} // Client exposes the methods provided by the Ethereum RPC client. type Client interface { - interfaces.BlockNumberReader - interfaces.ChainReader - interfaces.ChainStateReader - interfaces.ContractCaller - interfaces.GasEstimator - interfaces.GasPricer - interfaces.GasPricer1559 - interfaces.FeeHistoryReader - interfaces.LogFilterer + ethereum.BlockNumberReader + ethereum.ChainReader + ethereum.ChainStateReader + ethereum.ContractCaller + ethereum.GasEstimator + ethereum.GasPricer + ethereum.GasPricer1559 + ethereum.FeeHistoryReader + ethereum.LogFilterer interfaces.AcceptedStateReader interfaces.AcceptedContractCaller - interfaces.TransactionReader - interfaces.TransactionSender - interfaces.ChainIDReader + ethereum.TransactionReader + ethereum.TransactionSender + ethereum.ChainIDReader } // simClient wraps ethclient. This exists to prevent extracting ethclient.Client diff --git a/ethclient/simulated/backend_test.go b/ethclient/simulated/backend_test.go index 2b5b552ee9..df1e25a147 100644 --- a/ethclient/simulated/backend_test.go +++ b/ethclient/simulated/backend_test.go @@ -25,9 +25,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" "github.com/stretchr/testify/require" diff --git a/ethclient/simulated/options_test.go b/ethclient/simulated/options_test.go index f57f215496..9bc16c23bf 100644 --- a/ethclient/simulated/options_test.go +++ b/ethclient/simulated/options_test.go @@ -22,9 +22,9 @@ import ( "strings" "testing" + ethereum "github.com/ava-labs/libevm" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/params" ) @@ -63,7 +63,7 @@ func TestWithCallGasLimitOption(t *testing.T) { defer sim.Close() client := sim.Client() - _, err := client.CallContract(context.Background(), interfaces.CallMsg{ + _, err := client.CallContract(context.Background(), ethereum.CallMsg{ From: testAddr, To: &testAddr, Gas: 21000, diff --git a/ethclient/subnetevmclient/subnet_evm_client.go b/ethclient/subnetevmclient/subnet_evm_client.go index de2189aae0..b5b79d691f 100644 --- a/ethclient/subnetevmclient/subnet_evm_client.go +++ b/ethclient/subnetevmclient/subnet_evm_client.go @@ -33,11 +33,11 @@ import ( "runtime" "runtime/debug" + ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/ethclient" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/rpc" ) @@ -55,7 +55,7 @@ func New(c *rpc.Client) *Client { // CreateAccessList tries to create an access list for a specific transaction based on the // current pending state of the blockchain. -func (ec *Client) CreateAccessList(ctx context.Context, msg interfaces.CallMsg) (*types.AccessList, uint64, string, error) { +func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*types.AccessList, uint64, string, error) { type accessListResult struct { Accesslist *types.AccessList `json:"accessList"` Error string `json:"error,omitempty"` @@ -152,7 +152,7 @@ type OverrideAccount struct { // overrides specifies a map of contract states that should be overwritten before executing // the message call. // Please use ethclient.CallContract instead if you don't need the override functionality. -func (ec *Client) CallContract(ctx context.Context, msg interfaces.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount) ([]byte, error) { +func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount) ([]byte, error) { var hex hexutil.Bytes err := ec.c.CallContext( ctx, &hex, "eth_call", toCallArg(msg), @@ -180,7 +180,7 @@ func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- co return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") } -func toCallArg(msg interfaces.CallMsg) interface{} { +func toCallArg(msg ethereum.CallMsg) interface{} { arg := map[string]interface{}{ "from": msg.From, "to": msg.To, diff --git a/go.mod b/go.mod index 1feb8284b8..693b964ec7 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ require ( github.com/antithesishq/antithesis-sdk-go v0.3.8 github.com/ava-labs/avalanchego v1.12.3-rc.1.0.20250326132201-73294af08342 github.com/ava-labs/libevm v1.13.14-0.2.0.rc.4 - github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 + github.com/fjl/gencodec v0.1.1 github.com/go-cmd/cmd v1.4.1 github.com/gorilla/rpc v1.2.0 github.com/gorilla/websocket v1.5.0 @@ -20,7 +20,6 @@ require ( github.com/holiman/uint256 v1.2.4 github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-isatty v0.0.17 - github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo/v2 v2.13.1 github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.3.0 @@ -64,6 +63,7 @@ require ( github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/distribution/reference v0.5.0 // indirect @@ -74,6 +74,7 @@ require ( github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect @@ -120,6 +121,7 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect diff --git a/go.sum b/go.sum index d4f8c5d85a..25432615d0 100644 --- a/go.sum +++ b/go.sum @@ -193,6 +193,8 @@ github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/gencodec v0.1.1 h1:DhQY29Q6JLXB/GgMqE86NbOEuvckiYcJCbXFu02toms= +github.com/fjl/gencodec v0.1.1/go.mod h1:chDHL3wKXuBgauP8x3XNZkl5EIAR5SoCTmmmDTZRzmw= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -200,6 +202,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= diff --git a/interfaces/interfaces.go b/interfaces/interfaces.go index aa4efd7c03..39f8dcd371 100644 --- a/interfaces/interfaces.go +++ b/interfaces/interfaces.go @@ -1,198 +1,15 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. -// Package ethereum defines interfaces for interacting with Ethereum. package interfaces import ( "context" - "errors" - "math/big" ethereum "github.com/ava-labs/libevm" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" ) -// NotFound is returned by API methods if the requested item does not exist. -var NotFound = errors.New("not found") - -// Subscription represents an event subscription where events are -// delivered on a data channel. -type Subscription interface { - // Unsubscribe cancels the sending of events to the data channel - // and closes the error channel. - Unsubscribe() - // Err returns the subscription error channel. The error channel receives - // a value if there is an issue with the subscription (e.g. the network connection - // delivering the events has been closed). Only one value will ever be sent. - // The error channel is closed by Unsubscribe. - Err() <-chan error -} - -// ChainReader provides access to the blockchain. The methods in this interface access raw -// data from either the canonical chain (when requesting by block number) or any -// blockchain fork that was previously downloaded and processed by the node. The block -// number argument can be nil to select the latest canonical block. Reading block headers -// should be preferred over full blocks whenever possible. -// -// The returned error is NotFound if the requested item does not exist. -type ChainReader interface { - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) - TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) - TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) - - // This method subscribes to notifications about changes of the head block of - // the canonical chain. - SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (Subscription, error) -} - -// TransactionReader provides access to past transactions and their receipts. -// Implementations may impose arbitrary restrictions on the transactions and receipts that -// can be retrieved. Historic transactions may not be available. -// -// Avoid relying on this interface if possible. Contract logs (through the LogFilterer -// interface) are more reliable and usually safer in the presence of chain -// reorganisations. -// -// The returned error is NotFound if the requested item does not exist. -type TransactionReader interface { - // TransactionByHash checks the pool of pending transactions in addition to the - // blockchain. The isPending return value indicates whether the transaction has been - // mined yet. Note that the transaction may not be part of the canonical chain even if - // it's not pending. - TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) - // TransactionReceipt returns the receipt of a mined transaction. Note that the - // transaction may not be included in the current canonical chain even if a receipt - // exists. - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) -} - -// ChainStateReader wraps access to the state trie of the canonical blockchain. Note that -// implementations of the interface may be unable to return state values for old blocks. -// In many cases, using CallContract can be preferable to reading raw contract storage. -type ChainStateReader = ethereum.ChainStateReader - -// CallMsg contains parameters for contract calls. -type CallMsg struct { - From common.Address // the sender of the 'transaction' - To *common.Address // the destination contract (nil for contract creation) - Gas uint64 // if 0, the call executes with near-infinite gas - GasPrice *big.Int // wei <-> gas exchange ratio - GasFeeCap *big.Int // EIP-1559 fee cap per gas. - GasTipCap *big.Int // EIP-1559 tip per gas. - Value *big.Int // amount of wei sent along with the call - Data []byte // input data, usually an ABI-encoded contract method invocation - - AccessList types.AccessList // EIP-2930 access list. - - // For BlobTxType - BlobGasFeeCap *big.Int - BlobHashes []common.Hash -} - -// A ContractCaller provides contract calls, essentially transactions that are executed by -// the EVM but not mined into the blockchain. ContractCall is a low-level method to -// execute such calls. For applications which are structured around specific contracts, -// the abigen tool provides a nicer, properly typed way to perform calls. -type ContractCaller interface { - CallContract(ctx context.Context, call CallMsg, blockNumber *big.Int) ([]byte, error) -} - -// FilterQuery contains options for contract log filtering. -type FilterQuery struct { - BlockHash *common.Hash // used by eth_getLogs, return logs only from block with this hash - FromBlock *big.Int // beginning of the queried range, nil means genesis block - ToBlock *big.Int // end of the range, nil means latest block - Addresses []common.Address // restricts matches to events created by specific contracts - - // The Topic list restricts matches to particular event topics. Each event has a list - // of topics. Topics matches a prefix of that list. An empty element slice matches any - // topic. Non-empty elements represent an alternative that matches any of the - // contained topics. - // - // Examples: - // {} or nil matches any topic list - // {{A}} matches topic A in first position - // {{}, {B}} matches any topic in first position AND B in second position - // {{A}, {B}} matches topic A in first position AND B in second position - // {{A, B}, {C, D}} matches topic (A OR B) in first position AND (C OR D) in second position - Topics [][]common.Hash -} - -// LogFilterer provides access to contract log events using a one-off query or continuous -// event subscription. -// -// Logs received through a streaming query subscription may have Removed set to true, -// indicating that the log was reverted due to a chain reorganisation. -type LogFilterer interface { - FilterLogs(ctx context.Context, q FilterQuery) ([]types.Log, error) - SubscribeFilterLogs(ctx context.Context, q FilterQuery, ch chan<- types.Log) (Subscription, error) -} - -// TransactionSender wraps transaction sending. The SendTransaction method injects a -// signed transaction into the pending transaction pool for execution. If the transaction -// was a contract creation, the TransactionReceipt method can be used to retrieve the -// contract address after the transaction has been mined. -// -// The transaction must be signed and have a valid nonce to be included. Consumers of the -// API can use package accounts to maintain local private keys and need can retrieve the -// next available nonce using AcceptedNonceAt. -type TransactionSender interface { - SendTransaction(ctx context.Context, tx *types.Transaction) error -} - -// GasPricer wraps the gas price oracle, which monitors the blockchain to determine the -// optimal gas price given current fee market conditions. -type GasPricer interface { - SuggestGasPrice(ctx context.Context) (*big.Int, error) -} - -// GasPricer1559 provides access to the EIP-1559 gas price oracle. -type GasPricer1559 interface { - SuggestGasTipCap(ctx context.Context) (*big.Int, error) -} - -// FeeHistoryReader provides access to the fee history oracle. -type FeeHistoryReader interface { - FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*FeeHistory, error) -} - -// FeeHistory provides recent fee market data that consumers can use to determine -// a reasonable maxPriorityFeePerGas value. -type FeeHistory struct { - OldestBlock *big.Int // block corresponding to first response value - Reward [][]*big.Int // list every txs priority fee per block - BaseFee []*big.Int // list of each block's base fee - GasUsedRatio []float64 // ratio of gas used out of the total available limit -} - // An AcceptedStateReceiver provides access to the accepted state ie. the state of the // most recently accepted block. type AcceptedStateReader interface { @@ -202,29 +19,5 @@ type AcceptedStateReader interface { // AcceptedContractCaller can be used to perform calls against the accepted state. type AcceptedContractCaller interface { - AcceptedCallContract(ctx context.Context, call CallMsg) ([]byte, error) -} - -// GasEstimator wraps EstimateGas, which tries to estimate the gas needed to execute a -// specific transaction based on the pending state. There is no guarantee that this is the -// true gas limit requirement as other transactions may be added or removed by miners, but -// it should provide a basis for setting a reasonable default. -type GasEstimator interface { - EstimateGas(ctx context.Context, call CallMsg) (uint64, error) -} - -// A PendingStateEventer provides access to real time notifications about changes to the -// pending state. -type PendingStateEventer interface { - SubscribePendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (Subscription, error) -} - -// BlockNumberReader provides access to the current block number. -type BlockNumberReader interface { - BlockNumber(ctx context.Context) (uint64, error) -} - -// ChainIDReader provides access to the chain ID. -type ChainIDReader interface { - ChainID(ctx context.Context) (*big.Int, error) + AcceptedCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 27335d32cd..2de75d35b7 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -41,6 +41,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/eth/tracers/logger" @@ -50,9 +51,9 @@ import ( "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/gasestimator" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/rpc" "github.com/davecgh/go-spew/spew" "github.com/holiman/uint256" @@ -1232,6 +1233,7 @@ func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, b // RPCMarshalHeader converts the given header to the RPC output . func RPCMarshalHeader(head *types.Header) map[string]interface{} { + headExtra := customtypes.GetHeaderExtra(head) result := map[string]interface{}{ "number": (*hexutil.Big)(head.Number), "hash": head.Hash(), @@ -1253,8 +1255,8 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { if head.BaseFee != nil { result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee) } - if head.BlockGasCost != nil { - result["blockGasCost"] = (*hexutil.Big)(head.BlockGasCost) + if headExtra.BlockGasCost != nil { + result["blockGasCost"] = (*hexutil.Big)(headExtra.BlockGasCost) } if head.BlobGasUsed != nil { result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed) diff --git a/internal/ethapi/api_extra.go b/internal/ethapi/api_extra.go index 2abd57fa56..b6a6781000 100644 --- a/internal/ethapi/api_extra.go +++ b/internal/ethapi/api_extra.go @@ -11,10 +11,10 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/rpc" diff --git a/internal/ethapi/api_extra_test.go b/internal/ethapi/api_extra_test.go index 41faa4b13b..19442a6f76 100644 --- a/internal/ethapi/api_extra_test.go +++ b/internal/ethapi/api_extra_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/rpc" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index c34904c9ce..0449b9301f 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -46,6 +46,8 @@ import ( "github.com/ava-labs/libevm/accounts/keystore" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/crypto/kzg4844" @@ -56,9 +58,7 @@ import ( "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/bloombits" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/internal/blocktest" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index de396c0373..01a2ed0ac0 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -34,6 +34,7 @@ import ( "github.com/ava-labs/libevm/accounts" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/event" @@ -42,7 +43,6 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/bloombits" "github.com/ava-labs/subnet-evm/core/state" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" ) diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go index 8418eb9e7f..99c5b45286 100644 --- a/internal/ethapi/errors.go +++ b/internal/ethapi/errors.go @@ -30,8 +30,8 @@ import ( "fmt" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/accounts/abi" - "github.com/ava-labs/subnet-evm/vmerrs" ) // revertError is an API error that encompasses an EVM revert with JSON error @@ -54,11 +54,11 @@ func (e *revertError) ErrorData() interface{} { // newRevertError creates a revertError instance with the provided revert data. func newRevertError(revert []byte) *revertError { - err := vmerrs.ErrExecutionReverted + err := vm.ErrExecutionReverted reason, errUnpack := abi.UnpackRevert(revert) if errUnpack == nil { - err = fmt.Errorf("%w: %v", vmerrs.ErrExecutionReverted, reason) + err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason) } return &revertError{ error: err, diff --git a/internal/ethapi/mocks_test.go b/internal/ethapi/mocks_test.go index a14be99a2d..6532cc7661 100644 --- a/internal/ethapi/mocks_test.go +++ b/internal/ethapi/mocks_test.go @@ -17,6 +17,7 @@ import ( accounts "github.com/ava-labs/libevm/accounts" common "github.com/ava-labs/libevm/common" + types "github.com/ava-labs/libevm/core/types" vm "github.com/ava-labs/libevm/core/vm" ethdb "github.com/ava-labs/libevm/ethdb" event "github.com/ava-labs/libevm/event" @@ -25,7 +26,6 @@ import ( core "github.com/ava-labs/subnet-evm/core" bloombits "github.com/ava-labs/subnet-evm/core/bloombits" state "github.com/ava-labs/subnet-evm/core/state" - types "github.com/ava-labs/subnet-evm/core/types" params "github.com/ava-labs/subnet-evm/params" rpc "github.com/ava-labs/subnet-evm/rpc" gomock "go.uber.org/mock/gomock" diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index dc6b5f2026..f71a2662a5 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -37,11 +37,11 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto/kzg4844" "github.com/ava-labs/libevm/log" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/rpc" "github.com/holiman/uint256" diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index f966d02340..a0e0326646 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -35,7 +35,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/internal/shutdowncheck/shutdown_tracker.go b/internal/shutdowncheck/shutdown_tracker.go index 41b8117a30..29e2ac9017 100644 --- a/internal/shutdowncheck/shutdown_tracker.go +++ b/internal/shutdowncheck/shutdown_tracker.go @@ -30,9 +30,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" ) // ShutdownTracker is a service that reports previous unclean shutdowns diff --git a/libevm/options/options.go b/libevm/options/options.go deleted file mode 100644 index af7bc751a9..0000000000 --- a/libevm/options/options.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 the libevm authors. -// -// The libevm additions to go-ethereum are free software: you can redistribute -// them and/or modify them under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The libevm additions are distributed in the hope that they will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -// General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see -// . - -// Package options provides a generic mechanism for defining configuration of -// arbitrary types. -package options - -// An Option configures values of arbitrary type. -type Option[T any] interface { - Configure(*T) -} - -// As applies Options to a zero-value T, which it then returns. -func As[T any](opts ...Option[T]) *T { - var t T - for _, o := range opts { - o.Configure(&t) - } - return &t -} - -// A Func converts a function into an [Option], using itself as the Configure -// method. -type Func[T any] func(*T) - -var _ Option[struct{}] = Func[struct{}](nil) - -// Configure implements the [Option] interface. -func (f Func[T]) Configure(t *T) { f(t) } diff --git a/libevm/sync/sync.go b/libevm/sync/sync.go deleted file mode 100644 index 7621e20d79..0000000000 --- a/libevm/sync/sync.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2024 the subnet-evm authors. -// -// The libevm additions to go-ethereum are free software: you can redistribute -// them and/or modify them under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The libevm additions are distributed in the hope that they will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -// General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see -// . - -// Package sync extends the standard library's sync package. -package sync - -import "sync" - -// Aliases of stdlib sync's types to avoid having to import it alongside this -// package. -type ( - Cond = sync.Cond - Locker = sync.Locker - Map = sync.Map - Mutex = sync.Mutex - Once = sync.Once - RWMutex = sync.RWMutex - WaitGroup = sync.WaitGroup -) - -// A Pool is a type-safe wrapper around [sync.Pool]. -type Pool[T any] struct { - New func() T - pool sync.Pool - once Once -} - -// Get is equivalent to [sync.Pool.Get]. -func (p *Pool[T]) Get() T { - p.once.Do(func() { // Do() guarantees at least once, not just only once - p.pool.New = func() any { return p.New() } - }) - return p.pool.Get().(T) //nolint:forcetypeassert -} - -// Put is equivalent to [sync.Pool.Put]. -func (p *Pool[T]) Put(t T) { - p.pool.Put(t) -} diff --git a/miner/miner.go b/miner/miner.go index 7fddd69b2f..19996d39dc 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -30,11 +30,11 @@ package miner import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/event" "github.com/ava-labs/subnet-evm/consensus" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" ) diff --git a/miner/ordering.go b/miner/ordering.go index 150bef5a0b..5ee0b59a28 100644 --- a/miner/ordering.go +++ b/miner/ordering.go @@ -31,8 +31,8 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/miner/ordering_test.go b/miner/ordering_test.go index 61b88c8847..d50ae13fea 100644 --- a/miner/ordering_test.go +++ b/miner/ordering_test.go @@ -34,9 +34,9 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" ) diff --git a/miner/worker.go b/miner/worker.go index 5a0920da5f..2b389597a2 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -39,6 +39,7 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/event" "github.com/ava-labs/libevm/log" @@ -48,7 +49,6 @@ import ( "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" customheader "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" diff --git a/params/config.go b/params/config.go index cd56b7576d..bccf103a32 100644 --- a/params/config.go +++ b/params/config.go @@ -36,7 +36,7 @@ import ( "github.com/ava-labs/subnet-evm/utils" ) -// Guarantees extras initialisation before a call to [ChainConfig.Rules]. +// Guarantees extras initialisation before a call to [params.ChainConfig.Rules]. var _ = libevmInit() var ( diff --git a/params/config_extra.go b/params/config_extra.go index 6924814e49..45eae6ac64 100644 --- a/params/config_extra.go +++ b/params/config_extra.go @@ -25,8 +25,6 @@ var ( DefaultFeeConfig = extras.DefaultFeeConfig ) -type ConfigCompatError = extras.ConfigCompatError - // SetEthUpgrades enables Etheruem network upgrades using the same time as // the Avalanche network upgrade that enables them. // diff --git a/params/config_libevm.go b/params/config_libevm.go index 5c75ccd9d8..52ba8a62b9 100644 --- a/params/config_libevm.go +++ b/params/config_libevm.go @@ -1,4 +1,4 @@ -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// (c) 2024-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package params @@ -14,7 +14,7 @@ import ( ) // libevmInit would ideally be a regular init() function, but it MUST be run -// before any calls to [ChainConfig.Rules]. See `config.go` for its call site. +// before any calls to [params.ChainConfig.Rules]. See `config.go` for its call site. func libevmInit() any { payloads = ethparams.RegisterExtras(ethparams.Extras[*extras.ChainConfig, RulesExtra]{ ReuseJSONRoot: true, // Reuse the root JSON input when unmarshalling the extra payload. diff --git a/params/config_test.go b/params/config_test.go index 8368d1846c..574a2524a4 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -35,6 +35,7 @@ import ( "time" "github.com/ava-labs/libevm/common" + ethparams "github.com/ava-labs/libevm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" "github.com/ava-labs/subnet-evm/precompile/contracts/rewardmanager" @@ -48,7 +49,7 @@ func TestCheckCompatible(t *testing.T) { stored, new *ChainConfig headBlock uint64 headTimestamp uint64 - wantErr *ConfigCompatError + wantErr *ethparams.ConfigCompatError } tests := []test{ {stored: TestChainConfig, new: TestChainConfig, headBlock: 0, headTimestamp: 0, wantErr: nil}, @@ -66,7 +67,7 @@ func TestCheckCompatible(t *testing.T) { new: &ChainConfig{HomesteadBlock: nil}, headBlock: 3, headTimestamp: 30, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "Homestead fork block", StoredBlock: big.NewInt(0), NewBlock: nil, @@ -78,7 +79,7 @@ func TestCheckCompatible(t *testing.T) { new: &ChainConfig{HomesteadBlock: big.NewInt(1)}, headBlock: 3, headTimestamp: 30, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "Homestead fork block", StoredBlock: big.NewInt(0), NewBlock: big.NewInt(1), @@ -90,7 +91,7 @@ func TestCheckCompatible(t *testing.T) { new: &ChainConfig{HomesteadBlock: big.NewInt(25), EIP150Block: big.NewInt(20)}, headBlock: 25, headTimestamp: 250, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "EIP150 fork block", StoredBlock: big.NewInt(10), NewBlock: big.NewInt(20), @@ -109,7 +110,7 @@ func TestCheckCompatible(t *testing.T) { new: &ChainConfig{ConstantinopleBlock: big.NewInt(30), PetersburgBlock: big.NewInt(31)}, headBlock: 40, headTimestamp: 400, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "Petersburg fork block", StoredBlock: nil, NewBlock: big.NewInt(31), @@ -121,7 +122,7 @@ func TestCheckCompatible(t *testing.T) { new: TestPreSubnetEVMChainConfig, headBlock: 0, headTimestamp: 0, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "SubnetEVM fork block timestamp", StoredTime: utils.NewUint64(0), NewTime: GetExtra(TestPreSubnetEVMChainConfig).NetworkUpgrades.SubnetEVMTimestamp, @@ -133,7 +134,7 @@ func TestCheckCompatible(t *testing.T) { new: TestPreSubnetEVMChainConfig, headBlock: 10, headTimestamp: 100, - wantErr: &ConfigCompatError{ + wantErr: ðparams.ConfigCompatError{ What: "SubnetEVM fork block timestamp", StoredTime: utils.NewUint64(0), NewTime: GetExtra(TestPreSubnetEVMChainConfig).NetworkUpgrades.SubnetEVMTimestamp, diff --git a/params/extras/config.go b/params/extras/config.go index 225369d9a0..4a3d267e95 100644 --- a/params/extras/config.go +++ b/params/extras/config.go @@ -126,15 +126,15 @@ type ChainConfig struct { UpgradeConfig `json:"-"` // Config specified in upgradeBytes (avalanche network upgrades or enable/disabling precompiles). Not serialized. } -func (c *ChainConfig) CheckConfigCompatible(newcfg_ *ethparams.ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError { +func (c *ChainConfig) CheckConfigCompatible(newcfg_ *ethparams.ChainConfig, headNumber *big.Int, headTimestamp uint64) *ethparams.ConfigCompatError { if c == nil { return nil } newcfg, ok := newcfg_.Hooks().(*ChainConfig) if !ok { - // Proper registration of the extras on libevm side should prevent this from happening. + // Proper registration of the extras on the libevm side should prevent this from happening. // Return an error to prevent the chain from starting, just in case. - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("ChainConfig.Hooks() is not of the expected type *extras.ChainConfig, got %T", newcfg_.Hooks()), utils.NewUint64(0), nil, @@ -143,7 +143,7 @@ func (c *ChainConfig) CheckConfigCompatible(newcfg_ *ethparams.ChainConfig, head return c.checkConfigCompatible(newcfg, headNumber, headTimestamp) } -func (c *ChainConfig) checkConfigCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError { +func (c *ChainConfig) checkConfigCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ethparams.ConfigCompatError { if err := c.checkNetworkUpgradesCompatible(&newcfg.NetworkUpgrades, headTimestamp); err != nil { return err } @@ -186,8 +186,7 @@ func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool { } // isTimestampForked returns whether a fork scheduled at timestamp s is active -// at the given head timestamp. Whilst this method is the same as isBlockForked, -// they are explicitly separate for clearer reading. +// at the given head timestamp. func isTimestampForked(s *uint64, head uint64) bool { if s == nil { return false @@ -205,34 +204,6 @@ func configTimestampEqual(x, y *uint64) bool { return *x == *y } -// ConfigCompatError is raised if the locally-stored blockchain is initialised with a -// ChainConfig that would alter the past. -type ConfigCompatError = ethparams.ConfigCompatError - -// newTimestampCompatError is taken verbatim from upstream. -// TODO: export this function from upstream in libevm, so it can be used here. -func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError { - var rew *uint64 - switch { - case storedtime == nil: - rew = newtime - case newtime == nil || *storedtime < *newtime: - rew = storedtime - default: - rew = newtime - } - err := &ConfigCompatError{ - What: what, - StoredTime: storedtime, - NewTime: newtime, - RewindToTime: 0, - } - if rew != nil && *rew > 0 { - err.RewindToTime = *rew - 1 - } - return err -} - // UnmarshalJSON parses the JSON-encoded data and stores the result in the // object pointed to by c. // This is a custom unmarshaler to handle the Precompiles field. @@ -304,8 +275,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { } // checkForks checks that forks are enabled in order and returns an error if not. -// [blockFork] is true if the fork is a block number fork, false if it is a timestamp fork -// TODO: This code was adapted from CheckConfigForkOrder, consider refactoring to avoid duplication. +// `blockFork` is true if the fork is a block number fork, false if it is a timestamp fork func checkForks(forks []fork, blockFork bool) error { lastFork := fork{} for _, cur := range forks { @@ -365,7 +335,7 @@ func (c *ChainConfig) Verify() error { return nil } -// IsPrecompileEnabled returns whether precompile with [address] is enabled at [timestamp]. +// IsPrecompileEnabled returns whether precompile with `address` is enabled at `timestamp`. func (c *ChainConfig) IsPrecompileEnabled(address common.Address, timestamp uint64) bool { config := c.GetActivePrecompileConfig(address, timestamp) return config != nil && !config.IsDisabled() @@ -383,11 +353,11 @@ func (c *ChainConfig) AllowedFeeRecipients() bool { return c.AllowFeeRecipients } -// IsForkTransition returns true if [fork] activates during the transition from -// [parent] to [current]. -// Taking [parent] as a pointer allows for us to pass nil when checking forks +// IsForkTransition returns true if `fork` activates during the transition from +// `parent` to `current`. +// Taking `parent` as a pointer allows for us to pass nil when checking forks // that activate during genesis. -// Note: [parent] and [current] can be either both timestamp values, or both +// Note: `parent` and `current` can be either both timestamp values, or both // block number values, since this function works for both block number and // timestamp activated forks. func IsForkTransition(fork *uint64, parent *uint64, current uint64) bool { @@ -398,10 +368,3 @@ func IsForkTransition(fork *uint64, parent *uint64, current uint64) bool { currentForked := isTimestampForked(fork, current) return !parentForked && currentForked } - -func ptrToString(val *uint64) string { - if val == nil { - return "nil" - } - return fmt.Sprintf("%d", *val) -} diff --git a/params/extras/network_upgrades.go b/params/extras/network_upgrades.go index 6ae694e592..261ee8c0ac 100644 --- a/params/extras/network_upgrades.go +++ b/params/extras/network_upgrades.go @@ -8,6 +8,7 @@ import ( "reflect" "github.com/ava-labs/avalanchego/upgrade" + ethparams "github.com/ava-labs/libevm/params" "github.com/ava-labs/subnet-evm/utils" ) @@ -33,18 +34,18 @@ func (n *NetworkUpgrades) Equal(other *NetworkUpgrades) bool { return reflect.DeepEqual(n, other) } -func (n *NetworkUpgrades) checkNetworkUpgradesCompatible(newcfg *NetworkUpgrades, time uint64) *ConfigCompatError { +func (n *NetworkUpgrades) checkNetworkUpgradesCompatible(newcfg *NetworkUpgrades, time uint64) *ethparams.ConfigCompatError { if isForkTimestampIncompatible(n.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp, time) { - return newTimestampCompatError("SubnetEVM fork block timestamp", n.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp) + return ethparams.NewTimestampCompatError("SubnetEVM fork block timestamp", n.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp) } if isForkTimestampIncompatible(n.DurangoTimestamp, newcfg.DurangoTimestamp, time) { - return newTimestampCompatError("Durango fork block timestamp", n.DurangoTimestamp, newcfg.DurangoTimestamp) + return ethparams.NewTimestampCompatError("Durango fork block timestamp", n.DurangoTimestamp, newcfg.DurangoTimestamp) } if isForkTimestampIncompatible(n.EtnaTimestamp, newcfg.EtnaTimestamp, time) { - return newTimestampCompatError("Etna fork block timestamp", n.EtnaTimestamp, newcfg.EtnaTimestamp) + return ethparams.NewTimestampCompatError("Etna fork block timestamp", n.EtnaTimestamp, newcfg.EtnaTimestamp) } if isForkTimestampIncompatible(n.FortunaTimestamp, newcfg.FortunaTimestamp, time) { - return newTimestampCompatError("Fortuna fork block timestamp", n.FortunaTimestamp, newcfg.FortunaTimestamp) + return ethparams.NewTimestampCompatError("Fortuna fork block timestamp", n.FortunaTimestamp, newcfg.FortunaTimestamp) } return nil @@ -59,7 +60,7 @@ func (n *NetworkUpgrades) forkOrder() []fork { } } -// setDefaults sets the default values for the network upgrades. +// SetDefaults sets the default values for the network upgrades. // This overrides deactivating the network upgrade by providing a timestamp of nil value. func (n *NetworkUpgrades) SetDefaults(agoUpgrades upgrade.Config) { defaults := getDefaultNetworkUpgrades(agoUpgrades) @@ -190,3 +191,10 @@ func verifyWithDefault(configTimestamp *uint64, defaultTimestamp *uint64) error } return nil } + +func ptrToString(val *uint64) string { + if val == nil { + return "nil" + } + return fmt.Sprintf("%d", *val) +} diff --git a/params/extras/precompile_upgrade.go b/params/extras/precompile_upgrade.go index 01504a45d2..e1c6ac84a8 100644 --- a/params/extras/precompile_upgrade.go +++ b/params/extras/precompile_upgrade.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/ava-labs/libevm/common" + ethparams "github.com/ava-labs/libevm/params" "github.com/ava-labs/subnet-evm/precompile/modules" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/utils" @@ -193,7 +194,7 @@ func (c *ChainConfig) GetActivatingPrecompileConfigs(address common.Address, fro // Assumes given timestamp is the last accepted block timestamp. // This ensures that as long as the node has not accepted a block with a different rule set it will allow a // new upgrade to be applied as long as it activates after the last accepted block. -func (c *ChainConfig) checkPrecompilesCompatible(precompileUpgrades []PrecompileUpgrade, time uint64) *ConfigCompatError { +func (c *ChainConfig) checkPrecompilesCompatible(precompileUpgrades []PrecompileUpgrade, time uint64) *ethparams.ConfigCompatError { for _, module := range modules.RegisteredModules() { if err := c.checkPrecompileCompatible(module.Address, precompileUpgrades, time); err != nil { return err @@ -207,7 +208,7 @@ func (c *ChainConfig) checkPrecompilesCompatible(precompileUpgrades []Precompile // and [precompileUpgrades] at [headTimestamp]. // Returns an error if upgrades already activated at [headTimestamp] are missing from [precompileUpgrades]. // Upgrades that have already gone into effect cannot be modified or absent from [precompileUpgrades]. -func (c *ChainConfig) checkPrecompileCompatible(address common.Address, precompileUpgrades []PrecompileUpgrade, time uint64) *ConfigCompatError { +func (c *ChainConfig) checkPrecompileCompatible(address common.Address, precompileUpgrades []PrecompileUpgrade, time uint64) *ethparams.ConfigCompatError { // All active upgrades (from nil to [lastTimestamp]) must match. activeUpgrades := c.GetActivatingPrecompileConfigs(address, nil, time, c.PrecompileUpgrades) newUpgrades := c.GetActivatingPrecompileConfigs(address, nil, time, precompileUpgrades) @@ -216,7 +217,7 @@ func (c *ChainConfig) checkPrecompileCompatible(address common.Address, precompi for i, upgrade := range activeUpgrades { if len(newUpgrades) <= i { // missing upgrade - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("missing PrecompileUpgrade[%d]", i), upgrade.Timestamp(), nil, @@ -224,7 +225,7 @@ func (c *ChainConfig) checkPrecompileCompatible(address common.Address, precompi } // All upgrades that have activated must be identical. if !upgrade.Equal(newUpgrades[i]) { - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("PrecompileUpgrade[%d]", i), upgrade.Timestamp(), newUpgrades[i].Timestamp(), @@ -234,7 +235,7 @@ func (c *ChainConfig) checkPrecompileCompatible(address common.Address, precompi // then, make sure newUpgrades does not have additional upgrades // that are already activated. (cannot perform retroactive upgrade) if len(newUpgrades) > len(activeUpgrades) { - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("cannot retroactively enable PrecompileUpgrade[%d]", len(activeUpgrades)), nil, newUpgrades[len(activeUpgrades)].Timestamp(), // this indexes to the first element in newUpgrades after the end of activeUpgrades diff --git a/params/extras/rules.go b/params/extras/rules.go index 612f578a2b..0478948df9 100644 --- a/params/extras/rules.go +++ b/params/extras/rules.go @@ -34,7 +34,7 @@ func (r *Rules) PredicaterExists(addr common.Address) bool { return ok } -// IsPrecompileEnabled returns true if the precompile at [addr] is enabled for this rule set. +// IsPrecompileEnabled returns true if the precompile at `addr` is enabled for this rule set. func (r *Rules) IsPrecompileEnabled(addr common.Address) bool { _, ok := r.Precompiles[addr] return ok diff --git a/params/extras/state_upgrade.go b/params/extras/state_upgrade.go index d73b8b0e1b..53757db625 100644 --- a/params/extras/state_upgrade.go +++ b/params/extras/state_upgrade.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + ethparams "github.com/ava-labs/libevm/params" ) // StateUpgrade describes the modifications to be made to the state during @@ -69,7 +70,7 @@ func (c *ChainConfig) GetActivatingStateUpgrades(from *uint64, to uint64, upgrad } // checkStateUpgradesCompatible checks if [stateUpgrades] are compatible with [c] at [headTimestamp]. -func (c *ChainConfig) checkStateUpgradesCompatible(stateUpgrades []StateUpgrade, lastTimestamp uint64) *ConfigCompatError { +func (c *ChainConfig) checkStateUpgradesCompatible(stateUpgrades []StateUpgrade, lastTimestamp uint64) *ethparams.ConfigCompatError { // All active upgrades (from nil to [lastTimestamp]) must match. activeUpgrades := c.GetActivatingStateUpgrades(nil, lastTimestamp, c.StateUpgrades) newUpgrades := c.GetActivatingStateUpgrades(nil, lastTimestamp, stateUpgrades) @@ -78,7 +79,7 @@ func (c *ChainConfig) checkStateUpgradesCompatible(stateUpgrades []StateUpgrade, for i, upgrade := range activeUpgrades { if len(newUpgrades) <= i { // missing upgrade - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("missing StateUpgrade[%d]", i), upgrade.BlockTimestamp, nil, @@ -86,7 +87,7 @@ func (c *ChainConfig) checkStateUpgradesCompatible(stateUpgrades []StateUpgrade, } // All upgrades that have activated must be identical. if !upgrade.Equal(&newUpgrades[i]) { - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("StateUpgrade[%d]", i), upgrade.BlockTimestamp, newUpgrades[i].BlockTimestamp, @@ -96,7 +97,7 @@ func (c *ChainConfig) checkStateUpgradesCompatible(stateUpgrades []StateUpgrade, // then, make sure newUpgrades does not have additional upgrades // that are already activated. (cannot perform retroactive upgrade) if len(newUpgrades) > len(activeUpgrades) { - return newTimestampCompatError( + return ethparams.NewTimestampCompatError( fmt.Sprintf("cannot retroactively enable StateUpgrade[%d]", len(activeUpgrades)), nil, newUpgrades[len(activeUpgrades)].BlockTimestamp, // this indexes to the first element in newUpgrades after the end of activeUpgrades diff --git a/params/hooks_libevm.go b/params/hooks_libevm.go index b7310cf73a..3702514eba 100644 --- a/params/hooks_libevm.go +++ b/params/hooks_libevm.go @@ -1,4 +1,4 @@ -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// (c) 2024-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package params @@ -72,7 +72,7 @@ func makePrecompile(contract contract.StatefulPrecompiledContract) libevm.Precom panic(err) // Should never happen, as results are already validated in block validation } } - accessableState := accessableState{ + accessibleState := accessibleState{ env: env, blockContext: &precompileBlockContext{ number: env.BlockNumber(), @@ -80,7 +80,7 @@ func makePrecompile(contract contract.StatefulPrecompiledContract) libevm.Precom predicateResults: predicateResults, }, } - return contract.Run(accessableState, env.Addresses().Caller, env.Addresses().Self, input, suppliedGas, env.ReadOnly()) + return contract.Run(accessibleState, env.Addresses().Caller, env.Addresses().Self, input, suppliedGas, env.ReadOnly()) } return vm.NewStatefulPrecompile(legacy.PrecompiledStatefulContract(run).Upgrade()) } @@ -100,13 +100,14 @@ func (r RulesExtra) PrecompileOverride(addr common.Address) (libevm.PrecompiledC return makePrecompile(module.Contract), true } -type accessableState struct { +type accessibleState struct { env vm.PrecompileEnvironment blockContext *precompileBlockContext } -func (a accessableState) GetStateDB() contract.StateDB { - // XXX: this should be moved to the precompiles +func (a accessibleState) GetStateDB() contract.StateDB { + // TODO the contracts should be refactored to call `env.ReadOnlyState` + // or `env.StateDB` based on the env.ReadOnly() flag var state libevm.StateReader if a.env.ReadOnly() { state = a.env.ReadOnlyState() @@ -116,19 +117,19 @@ func (a accessableState) GetStateDB() contract.StateDB { return state.(contract.StateDB) } -func (a accessableState) GetBlockContext() contract.BlockContext { +func (a accessibleState) GetBlockContext() contract.BlockContext { return a.blockContext } -func (a accessableState) GetChainConfig() precompileconfig.ChainConfig { +func (a accessibleState) GetChainConfig() precompileconfig.ChainConfig { return GetExtra(a.env.ChainConfig()) } -func (a accessableState) GetSnowContext() *snow.Context { +func (a accessibleState) GetSnowContext() *snow.Context { return GetExtra(a.env.ChainConfig()).SnowCtx } -func (a accessableState) GetPrecompileEnv() vm.PrecompileEnvironment { +func (a accessibleState) GetPrecompileEnv() vm.PrecompileEnvironment { return a.env } diff --git a/plugin/evm/block.go b/plugin/evm/block.go index 6657150c10..fe39acb228 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -13,9 +13,9 @@ import ( "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/header" @@ -64,8 +64,8 @@ func (b *Block) Accept(context.Context) error { // Call Accept for relevant precompile logs. Note we do this prior to // calling Accept on the blockChain so any side effects (eg warp signatures) // take place before the accepted log is emitted to subscribers. - rules := b.vm.chainConfig.Rules(b.ethBlock.Number(), params.IsMergeTODO, b.ethBlock.Time()) - if err := b.handlePrecompileAccept(*params.GetRulesExtra(rules)); err != nil { + rules := b.vm.rules(b.ethBlock.Number(), b.ethBlock.Time()) + if err := b.handlePrecompileAccept(rules); err != nil { return err } if err := vm.blockChain.Accept(b.ethBlock); err != nil { @@ -155,7 +155,7 @@ func (b *Block) Verify(context.Context) error { // ShouldVerifyWithContext implements the block.WithVerifyContext interface func (b *Block) ShouldVerifyWithContext(context.Context) (bool, error) { - rules := params.GetRulesExtra(b.vm.chainConfig.Rules(b.ethBlock.Number(), params.IsMergeTODO, b.ethBlock.Time())) + rules := b.vm.rules(b.ethBlock.Number(), b.ethBlock.Time()) predicates := rules.Predicaters // Short circuit early if there are no predicates to verify if len(predicates) == 0 { diff --git a/plugin/evm/block_test.go b/plugin/evm/block_test.go index 6056a32712..c209a12142 100644 --- a/plugin/evm/block_test.go +++ b/plugin/evm/block_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" diff --git a/plugin/evm/block_verification.go b/plugin/evm/block_verification.go index 04d371bd4e..e1c962d70f 100644 --- a/plugin/evm/block_verification.go +++ b/plugin/evm/block_verification.go @@ -10,9 +10,10 @@ import ( "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/plugin/evm/header" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" ) @@ -113,13 +114,14 @@ func (v blockValidator) SyntacticVerify(b *Block, rules params.Rules) error { } if rulesExtra.IsSubnetEVM { + blockGasCost := customtypes.GetHeaderExtra(ethHeader).BlockGasCost switch { // Make sure BlockGasCost is not nil // NOTE: ethHeader.BlockGasCost correctness is checked in header verification - case ethHeader.BlockGasCost == nil: + case blockGasCost == nil: return errNilBlockGasCostSubnetEVM - case !ethHeader.BlockGasCost.IsUint64(): - return fmt.Errorf("too large blockGasCost: %d", ethHeader.BlockGasCost) + case !blockGasCost.IsUint64(): + return fmt.Errorf("too large blockGasCost: %d", blockGasCost) } } diff --git a/plugin/evm/customrawdb/accessors_metadata_ext.go b/plugin/evm/customrawdb/accessors_metadata_ext.go new file mode 100644 index 0000000000..094974c0a2 --- /dev/null +++ b/plugin/evm/customrawdb/accessors_metadata_ext.go @@ -0,0 +1,153 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customrawdb + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/ava-labs/libevm/common" + ethrawdb "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/ethdb" + "github.com/ava-labs/libevm/log" + "github.com/ava-labs/libevm/rlp" + "github.com/ava-labs/subnet-evm/params" +) + +// writeCurrentTimeMarker writes a marker of the current time in the db at `key`. +func writeCurrentTimeMarker(db ethdb.KeyValueStore, key []byte) error { + data, err := rlp.EncodeToBytes(uint64(time.Now().Unix())) + if err != nil { + return err + } + return db.Put(key, data) +} + +// readTimeMarker reads the timestamp stored at `key` +func readTimeMarker(db ethdb.KeyValueStore, key []byte) (time.Time, error) { + data, err := db.Get(key) + if err != nil { + return time.Time{}, err + } + + var unix uint64 + if err := rlp.DecodeBytes(data, &unix); err != nil { + return time.Time{}, err + } + + return time.Unix(int64(unix), 0), nil +} + +// WriteOfflinePruning writes a time marker of the last attempt to run offline pruning. +// The marker is written when offline pruning completes and is deleted when the node +// is started successfully with offline pruning disabled. This ensures users must +// disable offline pruning and start their node successfully between runs of offline +// pruning. +func WriteOfflinePruning(db ethdb.KeyValueStore) error { + return writeCurrentTimeMarker(db, offlinePruningKey) +} + +// ReadOfflinePruning reads the most recent timestamp of an attempt to run offline +// pruning if present. +func ReadOfflinePruning(db ethdb.KeyValueStore) (time.Time, error) { + return readTimeMarker(db, offlinePruningKey) +} + +// DeleteOfflinePruning deletes any marker of the last attempt to run offline pruning. +func DeleteOfflinePruning(db ethdb.KeyValueStore) error { + return db.Delete(offlinePruningKey) +} + +// WritePopulateMissingTries writes a marker for the current attempt to populate +// missing tries. +func WritePopulateMissingTries(db ethdb.KeyValueStore) error { + return writeCurrentTimeMarker(db, populateMissingTriesKey) +} + +// ReadPopulateMissingTries reads the most recent timestamp of an attempt to +// re-populate missing trie nodes. +func ReadPopulateMissingTries(db ethdb.KeyValueStore) (time.Time, error) { + return readTimeMarker(db, populateMissingTriesKey) +} + +// DeletePopulateMissingTries deletes any marker of the last attempt to +// re-populate missing trie nodes. +func DeletePopulateMissingTries(db ethdb.KeyValueStore) error { + return db.Delete(populateMissingTriesKey) +} + +// WritePruningDisabled writes a marker to track whether the node has ever run +// with pruning disabled. +func WritePruningDisabled(db ethdb.KeyValueStore) error { + return db.Put(pruningDisabledKey, nil) +} + +// HasPruningDisabled returns true if there is a marker present indicating that +// the node has run with pruning disabled at some pooint. +func HasPruningDisabled(db ethdb.KeyValueStore) (bool, error) { + return db.Has(pruningDisabledKey) +} + +// WriteAcceptorTip writes `hash` as the last accepted block that has been fully processed. +func WriteAcceptorTip(db ethdb.KeyValueWriter, hash common.Hash) error { + return db.Put(acceptorTipKey, hash[:]) +} + +// ReadAcceptorTip reads the hash of the last accepted block that was fully processed. +// If there is no value present (the index is being initialized for the first time), then the +// empty hash is returned. +func ReadAcceptorTip(db ethdb.KeyValueReader) (common.Hash, error) { + has, err := db.Has(acceptorTipKey) + if err != nil { + return common.Hash{}, err + } + if !has { + // If the index is not present on disk, the [acceptorTipKey] index has not been initialized yet. + return common.Hash{}, nil + } + h, err := db.Get(acceptorTipKey) + if err != nil { + return common.Hash{}, err + } + if len(h) != common.HashLength { + return common.Hash{}, fmt.Errorf("value has incorrect length %d", len(h)) + } + return common.BytesToHash(h), nil +} + +// ReadChainConfig retrieves the consensus settings based on the given genesis hash. +func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) *params.ChainConfig { + config := ethrawdb.ReadChainConfig(db, hash) + + upgrade, _ := db.Get(upgradeConfigKey(hash)) + if len(upgrade) == 0 { + return config + } + + extra := params.GetExtra(config) + if err := json.Unmarshal(upgrade, &extra.UpgradeConfig); err != nil { + log.Error("Invalid upgrade config JSON", "err", err) + return nil + } + + return config +} + +// WriteChainConfig writes the chain config settings to the database. +func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, config *params.ChainConfig) { + ethrawdb.WriteChainConfig(db, hash, config) + if config == nil { + return + } + + extra := params.GetExtra(config) + data, err := json.Marshal(extra.UpgradeConfig) + if err != nil { + log.Crit("Failed to JSON encode upgrade config", "err", err) + } + if err := db.Put(upgradeConfigKey(hash), data); err != nil { + log.Crit("Failed to store upgrade config", "err", err) + } +} diff --git a/plugin/evm/customrawdb/accessors_snapshot_ext.go b/plugin/evm/customrawdb/accessors_snapshot_ext.go new file mode 100644 index 0000000000..0623594a59 --- /dev/null +++ b/plugin/evm/customrawdb/accessors_snapshot_ext.go @@ -0,0 +1,46 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customrawdb + +import ( + "github.com/ava-labs/libevm/common" + ethrawdb "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/ethdb" + "github.com/ava-labs/libevm/log" +) + +// ReadSnapshotBlockHash retrieves the hash of the block whose state is contained in +// the persisted snapshot. +func ReadSnapshotBlockHash(db ethdb.KeyValueReader) common.Hash { + data, _ := db.Get(snapshotBlockHashKey) + if len(data) != common.HashLength { + return common.Hash{} + } + return common.BytesToHash(data) +} + +// WriteSnapshotBlockHash stores the root of the block whose state is contained in +// the persisted snapshot. +func WriteSnapshotBlockHash(db ethdb.KeyValueWriter, blockHash common.Hash) { + if err := db.Put(snapshotBlockHashKey, blockHash[:]); err != nil { + log.Crit("Failed to store snapshot block hash", "err", err) + } +} + +// DeleteSnapshotBlockHash deletes the hash of the block whose state is contained in +// the persisted snapshot. Since snapshots are not immutable, this method can +// be used during updates, so a crash or failure will mark the entire snapshot +// invalid. +func DeleteSnapshotBlockHash(db ethdb.KeyValueWriter) { + if err := db.Delete(snapshotBlockHashKey); err != nil { + log.Crit("Failed to remove snapshot block hash", "err", err) + } +} + +// IterateAccountSnapshots returns an iterator for walking all of the accounts in the snapshot +func IterateAccountSnapshots(db ethdb.Iteratee) ethdb.Iterator { + it := db.NewIterator(ethrawdb.SnapshotAccountPrefix, nil) + keyLen := len(ethrawdb.SnapshotAccountPrefix) + common.HashLength + return ethrawdb.NewKeyLengthIterator(it, keyLen) +} diff --git a/core/rawdb/accessors_state_sync.go b/plugin/evm/customrawdb/accessors_state_sync.go similarity index 80% rename from core/rawdb/accessors_state_sync.go rename to plugin/evm/customrawdb/accessors_state_sync.go index 0781a8c142..8368ac1fcb 100644 --- a/core/rawdb/accessors_state_sync.go +++ b/plugin/evm/customrawdb/accessors_state_sync.go @@ -1,13 +1,14 @@ // (c) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package rawdb +package customrawdb import ( "encoding/binary" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/libevm/common" + ethrawdb "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" ) @@ -31,14 +32,14 @@ func WriteSyncRoot(db ethdb.KeyValueWriter, root common.Hash) error { return db.Put(syncRootKey, root[:]) } -// AddCodeToFetch adds a marker that we need to fetch the code for [hash]. +// AddCodeToFetch adds a marker that we need to fetch the code for `hash`. func AddCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) { if err := db.Put(codeToFetchKey(hash), nil); err != nil { log.Crit("Failed to put code to fetch", "codeHash", hash, "err", err) } } -// DeleteCodeToFetch removes the marker that the code corresponding to [hash] needs to be fetched. +// DeleteCodeToFetch removes the marker that the code corresponding to `hash` needs to be fetched. func DeleteCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) { if err := db.Delete(codeToFetchKey(hash)); err != nil { log.Crit("Failed to delete code to fetch", "codeHash", hash, "err", err) @@ -49,7 +50,7 @@ func DeleteCodeToFetch(db ethdb.KeyValueWriter, hash common.Hash) { // hashes that are pending syncing. It is the caller's responsibility to // unpack the key and call Release on the returned iterator. func NewCodeToFetchIterator(db ethdb.Iteratee) ethdb.Iterator { - return NewKeyLengthIterator( + return ethrawdb.NewKeyLengthIterator( db.NewIterator(CodeToFetchPrefix, nil), codeToFetchKeyLength, ) @@ -70,14 +71,14 @@ func NewSyncSegmentsIterator(db ethdb.Iteratee, root common.Hash) ethdb.Iterator copy(segmentsPrefix, syncSegmentsPrefix) copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:]) - return NewKeyLengthIterator( + return ethrawdb.NewKeyLengthIterator( db.NewIterator(segmentsPrefix, nil), syncSegmentsKeyLength, ) } // WriteSyncSegment adds a trie segment for root at the given start position. -func WriteSyncSegment(db ethdb.KeyValueWriter, root common.Hash, start []byte) error { +func WriteSyncSegment(db ethdb.KeyValueWriter, root common.Hash, start common.Hash) error { return db.Put(packSyncSegmentKey(root, start), []byte{0x01}) } @@ -86,12 +87,12 @@ func ClearSyncSegments(db ethdb.KeyValueStore, root common.Hash) error { segmentsPrefix := make([]byte, len(syncSegmentsPrefix)+common.HashLength) copy(segmentsPrefix, syncSegmentsPrefix) copy(segmentsPrefix[len(syncSegmentsPrefix):], root[:]) - return ClearPrefix(db, segmentsPrefix, syncSegmentsKeyLength) + return clearPrefix(db, segmentsPrefix, syncSegmentsKeyLength) } // ClearAllSyncSegments removes all segment markers from db func ClearAllSyncSegments(db ethdb.KeyValueStore) error { - return ClearPrefix(db, syncSegmentsPrefix, syncSegmentsKeyLength) + return clearPrefix(db, syncSegmentsPrefix, syncSegmentsKeyLength) } // UnpackSyncSegmentKey returns the root and start position for a trie segment @@ -104,11 +105,11 @@ func UnpackSyncSegmentKey(keyBytes []byte) (common.Hash, []byte) { } // packSyncSegmentKey packs root and account into a key for storage in db. -func packSyncSegmentKey(root common.Hash, start []byte) []byte { - bytes := make([]byte, len(syncSegmentsPrefix)+common.HashLength+len(start)) +func packSyncSegmentKey(root common.Hash, start common.Hash) []byte { + bytes := make([]byte, syncSegmentsKeyLength) copy(bytes, syncSegmentsPrefix) copy(bytes[len(syncSegmentsPrefix):], root[:]) - copy(bytes[len(syncSegmentsPrefix)+common.HashLength:], start) + copy(bytes[len(syncSegmentsPrefix)+common.HashLength:], start.Bytes()) return bytes } @@ -116,7 +117,7 @@ func packSyncSegmentKey(root common.Hash, start []byte) []byte { // added for syncing (beginning at seek). It is the caller's responsibility to unpack // the key and call Release on the returned iterator. func NewSyncStorageTriesIterator(db ethdb.Iteratee, seek []byte) ethdb.Iterator { - return NewKeyLengthIterator(db.NewIterator(syncStorageTriesPrefix, seek), syncStorageTriesKeyLength) + return ethrawdb.NewKeyLengthIterator(db.NewIterator(syncStorageTriesPrefix, seek), syncStorageTriesKeyLength) } // WriteSyncStorageTrie adds a storage trie for account (with the given root) to be synced. @@ -130,12 +131,12 @@ func ClearSyncStorageTrie(db ethdb.KeyValueStore, root common.Hash) error { accountsPrefix := make([]byte, len(syncStorageTriesPrefix)+common.HashLength) copy(accountsPrefix, syncStorageTriesPrefix) copy(accountsPrefix[len(syncStorageTriesPrefix):], root[:]) - return ClearPrefix(db, accountsPrefix, syncStorageTriesKeyLength) + return clearPrefix(db, accountsPrefix, syncStorageTriesKeyLength) } // ClearAllSyncStorageTries removes all storage tries added for syncing from db func ClearAllSyncStorageTries(db ethdb.KeyValueStore) error { - return ClearPrefix(db, syncStorageTriesPrefix, syncStorageTriesKeyLength) + return clearPrefix(db, syncStorageTriesPrefix, syncStorageTriesKeyLength) } // UnpackSyncStorageTrieKey returns the root and account for a storage trie @@ -156,7 +157,7 @@ func packSyncStorageTrieKey(root common.Hash, account common.Hash) []byte { return bytes } -// WriteSyncPerformed logs an entry in [db] indicating the VM state synced to [blockNumber]. +// WriteSyncPerformed logs an entry in `db` indicating the VM state synced to `blockNumber`. func WriteSyncPerformed(db ethdb.KeyValueWriter, blockNumber uint64) error { syncPerformedPrefixLen := len(syncPerformedPrefix) bytes := make([]byte, syncPerformedPrefixLen+wrappers.LongLen) @@ -168,7 +169,7 @@ func WriteSyncPerformed(db ethdb.KeyValueWriter, blockNumber uint64) error { // NewSyncPerformedIterator returns an iterator over all block numbers the VM // has state synced to. func NewSyncPerformedIterator(db ethdb.Iteratee) ethdb.Iterator { - return NewKeyLengthIterator(db.NewIterator(syncPerformedPrefix, nil), syncPerformedKeyLength) + return ethrawdb.NewKeyLengthIterator(db.NewIterator(syncPerformedPrefix, nil), syncPerformedKeyLength) } // UnpackSyncPerformedKey returns the block number from keys the iterator returned @@ -191,3 +192,31 @@ func GetLatestSyncPerformed(db ethdb.Iteratee) uint64 { } return latestSyncPerformed } + +// clearPrefix removes all keys in db that begin with prefix and match an +// expected key length. `keyLen` must include the length of the prefix. +func clearPrefix(db ethdb.KeyValueStore, prefix []byte, keyLen int) error { + it := db.NewIterator(prefix, nil) + defer it.Release() + + batch := db.NewBatch() + for it.Next() { + key := common.CopyBytes(it.Key()) + if len(key) != keyLen { + continue + } + if err := batch.Delete(key); err != nil { + return err + } + if batch.ValueSize() > ethdb.IdealBatchSize { + if err := batch.Write(); err != nil { + return err + } + batch.Reset() + } + } + if err := it.Error(); err != nil { + return err + } + return batch.Write() +} diff --git a/core/rawdb/accessors_state_sync_test.go b/plugin/evm/customrawdb/accessors_state_sync_test.go similarity index 86% rename from core/rawdb/accessors_state_sync_test.go rename to plugin/evm/customrawdb/accessors_state_sync_test.go index 506e843c8b..3b11f4366b 100644 --- a/core/rawdb/accessors_state_sync_test.go +++ b/plugin/evm/customrawdb/accessors_state_sync_test.go @@ -1,20 +1,21 @@ // (c) 2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package rawdb +package customrawdb import ( "testing" "github.com/ava-labs/libevm/common" + ethrawdb "github.com/ava-labs/libevm/core/rawdb" "github.com/stretchr/testify/require" ) func TestClearPrefix(t *testing.T) { require := require.New(t) - db := NewMemoryDatabase() + db := ethrawdb.NewMemoryDatabase() // add a key that should be cleared - require.NoError(WriteSyncSegment(db, common.Hash{1}, common.Hash{}.Bytes())) + require.NoError(WriteSyncSegment(db, common.Hash{1}, common.Hash{})) // add a key that should not be cleared key := append(syncSegmentsPrefix, []byte("foo")...) diff --git a/plugin/evm/customrawdb/database_ext.go b/plugin/evm/customrawdb/database_ext.go new file mode 100644 index 0000000000..f422ea89f6 --- /dev/null +++ b/plugin/evm/customrawdb/database_ext.go @@ -0,0 +1,64 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customrawdb + +import ( + "bytes" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/ethdb" +) + +// InspectDatabase traverses the entire database and checks the size +// of all different categories of data. +func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { + type stat = rawdb.DatabaseStat + stats := []struct { + name string + keyLen int + keyPrefix []byte + stat *stat + }{ + {"Trie segments", syncSegmentsKeyLength, syncSegmentsPrefix, &stat{}}, + {"Storage tries to fetch", syncStorageTriesKeyLength, syncStorageTriesPrefix, &stat{}}, + {"Code to fetch", codeToFetchKeyLength, CodeToFetchPrefix, &stat{}}, + {"Block numbers synced to", syncPerformedKeyLength, syncPerformedPrefix, &stat{}}, + } + + options := []rawdb.InspectDatabaseOption{ + rawdb.WithDatabaseMetadataKeys(func(key []byte) bool { + return bytes.Equal(key, snapshotBlockHashKey) || + bytes.Equal(key, syncRootKey) || + (bytes.HasPrefix(key, upgradeConfigPrefix) && len(key) == len(upgradeConfigPrefix)+common.HashLength) + }), + rawdb.WithDatabaseStatRecorder(func(key []byte, size common.StorageSize) bool { + for _, s := range stats { + if len(key) == s.keyLen && bytes.HasPrefix(key, s.keyPrefix) { + s.stat.Add(size) + return true + } + } + return false + }), + rawdb.WithDatabaseStatsTransformer(func(rows [][]string) [][]string { + newRows := make([][]string, 0, len(rows)) + for _, row := range rows { + switch db, cat := row[0], row[1]; { + // Discard rows specific to libevm (geth) but irrelevant to subnet-evm. + case db == "Key-Value store" && (cat == "Difficulties" || cat == "Beacon sync headers"): + case db == "Ancient store (Chain)": + default: + newRows = append(newRows, row) + } + } + for _, s := range stats { + newRows = append(newRows, []string{"State sync", s.name, s.stat.Size(), s.stat.Count()}) + } + return newRows + }), + } + + return rawdb.InspectDatabase(db, keyPrefix, keyStart, options...) +} diff --git a/plugin/evm/customrawdb/database_ext_test.go b/plugin/evm/customrawdb/database_ext_test.go new file mode 100644 index 0000000000..b3bdee03e0 --- /dev/null +++ b/plugin/evm/customrawdb/database_ext_test.go @@ -0,0 +1,135 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customrawdb + +import ( + "fmt" + + "github.com/ava-labs/libevm/common" + ethrawdb "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/ethdb" +) + +func ExampleInspectDatabase() { + db := &stubDatabase{ + iterator: &stubIterator{}, + } + + // Extra metadata keys: (17 + 32) + (12 + 32) = 93 bytes + WriteSnapshotBlockHash(db, common.Hash{}) + ethrawdb.WriteSnapshotRoot(db, common.Hash{}) + // Trie segments: (77 + 2) + 1 = 80 bytes + _ = WriteSyncSegment(db, common.Hash{}, common.Hash{}) + // Storage tries to fetch: 76 + 1 = 77 bytes + _ = WriteSyncStorageTrie(db, common.Hash{}, common.Hash{}) + // Code to fetch: 34 + 0 = 34 bytes + AddCodeToFetch(db, common.Hash{}) + // Block numbers synced to: 22 + 1 = 23 bytes + _ = WriteSyncPerformed(db, 0) + + keyPrefix := []byte(nil) + keyStart := []byte(nil) + + err := InspectDatabase(db, keyPrefix, keyStart) + if err != nil { + fmt.Println(err) + } + // Output: + // +-----------------+-------------------------+----------+-------+ + // | DATABASE | CATEGORY | SIZE | ITEMS | + // +-----------------+-------------------------+----------+-------+ + // | Key-Value store | Headers | 0.00 B | 0 | + // | Key-Value store | Bodies | 0.00 B | 0 | + // | Key-Value store | Receipt lists | 0.00 B | 0 | + // | Key-Value store | Block number->hash | 0.00 B | 0 | + // | Key-Value store | Block hash->number | 0.00 B | 0 | + // | Key-Value store | Transaction index | 0.00 B | 0 | + // | Key-Value store | Bloombit index | 0.00 B | 0 | + // | Key-Value store | Contract codes | 0.00 B | 0 | + // | Key-Value store | Hash trie nodes | 0.00 B | 0 | + // | Key-Value store | Path trie state lookups | 0.00 B | 0 | + // | Key-Value store | Path trie account nodes | 0.00 B | 0 | + // | Key-Value store | Path trie storage nodes | 0.00 B | 0 | + // | Key-Value store | Trie preimages | 0.00 B | 0 | + // | Key-Value store | Account snapshot | 0.00 B | 0 | + // | Key-Value store | Storage snapshot | 0.00 B | 0 | + // | Key-Value store | Clique snapshots | 0.00 B | 0 | + // | Key-Value store | Singleton metadata | 93.00 B | 2 | + // | Light client | CHT trie nodes | 0.00 B | 0 | + // | Light client | Bloom trie nodes | 0.00 B | 0 | + // | State sync | Trie segments | 78.00 B | 1 | + // | State sync | Storage tries to fetch | 77.00 B | 1 | + // | State sync | Code to fetch | 34.00 B | 1 | + // | State sync | Block numbers synced to | 23.00 B | 1 | + // +-----------------+-------------------------+----------+-------+ + // | TOTAL | 305.00 B | | + // +-----------------+-------------------------+----------+-------+ +} + +type stubDatabase struct { + ethdb.Database + iterator *stubIterator +} + +func (s *stubDatabase) NewIterator(keyPrefix, keyStart []byte) ethdb.Iterator { + return s.iterator +} + +// AncientSize is used in [InspectDatabase] to determine the ancient sizes. +func (s *stubDatabase) AncientSize(kind string) (uint64, error) { + return 0, nil +} + +func (s *stubDatabase) Ancients() (uint64, error) { + return 0, nil +} + +func (s *stubDatabase) Tail() (uint64, error) { + return 0, nil +} + +func (s *stubDatabase) Put(key, value []byte) error { + s.iterator.kvs = append(s.iterator.kvs, keyValue{key: key, value: value}) + return nil +} + +func (s *stubDatabase) Get(key []byte) ([]byte, error) { + return nil, nil +} + +func (s *stubDatabase) ReadAncients(fn func(ethdb.AncientReaderOp) error) error { + return nil +} + +type stubIterator struct { + ethdb.Iterator + i int // see [stubIterator.pos] + kvs []keyValue +} + +type keyValue struct { + key []byte + value []byte +} + +// pos returns the true iterator position, which is otherwise off by one because +// Next() is called _before_ usage. +func (s *stubIterator) pos() int { + return s.i - 1 +} + +func (s *stubIterator) Next() bool { + s.i++ + return s.pos() < len(s.kvs) +} + +func (s *stubIterator) Release() {} + +func (s *stubIterator) Key() []byte { + return s.kvs[s.pos()].key +} + +func (s *stubIterator) Value() []byte { + return s.kvs[s.pos()].value +} diff --git a/plugin/evm/customrawdb/schema_ext.go b/plugin/evm/customrawdb/schema_ext.go new file mode 100644 index 0000000000..4ef536a878 --- /dev/null +++ b/plugin/evm/customrawdb/schema_ext.go @@ -0,0 +1,60 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customrawdb + +import ( + "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ava-labs/libevm/common" +) + +var ( + // snapshotBlockHashKey tracks the block hash of the last snapshot. + snapshotBlockHashKey = []byte("SnapshotBlockHash") + // offlinePruningKey tracks runs of offline pruning + offlinePruningKey = []byte("OfflinePruning") + // populateMissingTriesKey tracks runs of trie backfills + populateMissingTriesKey = []byte("PopulateMissingTries") + // pruningDisabledKey tracks whether the node has ever run in archival mode + // to ensure that a user does not accidentally corrupt an archival node. + pruningDisabledKey = []byte("PruningDisabled") + // acceptorTipKey tracks the tip of the last accepted block that has been fully processed. + acceptorTipKey = []byte("AcceptorTipKey") + // upgradeConfigPrefix prefixes upgrade bytes passed to the chain + upgradeConfigPrefix = []byte("upgrade-config-") +) + +// State sync progress keys and prefixes +var ( + // syncRootKey indicates the root of the main account trie currently being synced + syncRootKey = []byte("sync_root") + // syncStorageTriesPrefix is the prefix for storage tries that need to be fetched. + // syncStorageTriesPrefix + trie root + account hash: indicates a storage trie must be fetched for the account + syncStorageTriesPrefix = []byte("sync_storage") + // syncSegmentsPrefix is the prefix for segments. + // syncSegmentsPrefix + trie root + 32-byte start key: indicates the trie at root has a segment starting at the specified key + syncSegmentsPrefix = []byte("sync_segments") + // CodeToFetchPrefix is the prefix for code hashes that need to be fetched. + // CodeToFetchPrefix + code hash -> empty value tracks the outstanding code hashes we need to fetch. + CodeToFetchPrefix = []byte("CP") +) + +// State sync progress key lengths +var ( + syncStorageTriesKeyLength = len(syncStorageTriesPrefix) + 2*common.HashLength + syncSegmentsKeyLength = len(syncSegmentsPrefix) + 2*common.HashLength + codeToFetchKeyLength = len(CodeToFetchPrefix) + common.HashLength +) + +// State sync metadata +var ( + syncPerformedPrefix = []byte("sync_performed") + // syncPerformedKeyLength is the length of the key for the sync performed metadata key, + // and is equal to [syncPerformedPrefix] + block number as uint64. + syncPerformedKeyLength = len(syncPerformedPrefix) + wrappers.LongLen +) + +// upgradeConfigKey = upgradeConfigPrefix + hash +func upgradeConfigKey(hash common.Hash) []byte { + return append(upgradeConfigPrefix, hash.Bytes()...) +} diff --git a/plugin/evm/customtypes/block_ext.go b/plugin/evm/customtypes/block_ext.go new file mode 100644 index 0000000000..fca4b02a2e --- /dev/null +++ b/plugin/evm/customtypes/block_ext.go @@ -0,0 +1,18 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ( + "math/big" + + ethtypes "github.com/ava-labs/libevm/core/types" +) + +func BlockGasCost(b *ethtypes.Block) *big.Int { + cost := GetHeaderExtra(b.Header()).BlockGasCost + if cost == nil { + return nil + } + return new(big.Int).Set(cost) +} diff --git a/plugin/evm/customtypes/block_ext_test.go b/plugin/evm/customtypes/block_ext_test.go new file mode 100644 index 0000000000..6662530ef9 --- /dev/null +++ b/plugin/evm/customtypes/block_ext_test.go @@ -0,0 +1,113 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ( + "math/big" + "reflect" + "testing" + "unsafe" + + "github.com/ava-labs/libevm/common" + "github.com/stretchr/testify/assert" + + // TODO(arr4n) These tests were originally part of the `subnet-evm/core/types` + // package so assume the presence of identifiers. A dot-import reduces PR + // noise during the refactoring. + . "github.com/ava-labs/libevm/core/types" +) + +func TestCopyHeader(t *testing.T) { + t.Parallel() + + t.Run("empty_header", func(t *testing.T) { + t.Parallel() + + empty := &Header{} + + headerExtra := &HeaderExtra{} + extras.Header.Set(empty, headerExtra) + + cpy := CopyHeader(empty) + + want := &Header{ + Difficulty: new(big.Int), + Number: new(big.Int), + } + + headerExtra = &HeaderExtra{} + extras.Header.Set(want, headerExtra) + + assert.Equal(t, want, cpy) + }) + + t.Run("filled_header", func(t *testing.T) { + t.Parallel() + + header, _ := headerWithNonZeroFields() // the header carries the [HeaderExtra] so we can ignore it + + gotHeader := CopyHeader(header) + gotExtra := GetHeaderExtra(gotHeader) + + wantHeader, wantExtra := headerWithNonZeroFields() + assert.Equal(t, wantHeader, gotHeader) + assert.Equal(t, wantExtra, gotExtra) + + exportedFieldsPointToDifferentMemory(t, header, gotHeader) + exportedFieldsPointToDifferentMemory(t, GetHeaderExtra(header), gotExtra) + }) +} + +func exportedFieldsPointToDifferentMemory[T interface { + Header | HeaderExtra +}](t *testing.T, original, cpy *T) { + t.Helper() + + v := reflect.ValueOf(*original) + typ := v.Type() + cp := reflect.ValueOf(*cpy) + for i := range v.NumField() { + field := typ.Field(i) + if !field.IsExported() { + continue + } + switch field.Type.Kind() { + case reflect.Array, reflect.Uint64: + // Not pointers, but using explicit Kinds for safety + continue + } + + t.Run(field.Name, func(t *testing.T) { + fieldCp := cp.Field(i).Interface() + switch f := v.Field(i).Interface().(type) { + case *big.Int: + assertDifferentPointers(t, f, fieldCp) + case *common.Hash: + assertDifferentPointers(t, f, fieldCp) + case *uint64: + assertDifferentPointers(t, f, fieldCp) + case []uint8: + assertDifferentPointers(t, unsafe.SliceData(f), unsafe.SliceData(fieldCp.([]uint8))) + default: + t.Errorf("field %q type %T needs to be added to switch cases of exportedFieldsDeepCopied", field.Name, f) + } + }) + } +} + +// assertDifferentPointers asserts that `a` and `b` are both non-nil +// pointers pointing to different memory locations. +func assertDifferentPointers[T any](t *testing.T, a *T, b any) { + t.Helper() + switch { + case a == nil: + t.Errorf("a (%T) cannot be nil", a) + case b == nil: + t.Errorf("b (%T) cannot be nil", b) + case a == b: + t.Errorf("pointers to same memory") + } + // Note: no need to check `b` is of the same type as `a`, otherwise + // the memory address would be different as well. +} diff --git a/core/types/block_test.go b/plugin/evm/customtypes/block_test.go similarity index 84% rename from core/types/block_test.go rename to plugin/evm/customtypes/block_test.go index 8a004c93be..1dfe4a1d58 100644 --- a/core/types/block_test.go +++ b/plugin/evm/customtypes/block_test.go @@ -24,7 +24,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types +package customtypes_test import ( "bytes" @@ -34,15 +34,21 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" - "github.com/ava-labs/libevm/params" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/subnet-evm/internal/blocktest" + "github.com/ava-labs/subnet-evm/params" + + // This test file has to be in package types_test to avoid a circular + // dependency when importing `params`. We dot-import the package to mimic + // regular same-package behaviour. + . "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" ) func TestBlockEncoding(t *testing.T) { blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0") - var block Block + var block types.Block if err := rlp.DecodeBytes(blockEnc, &block); err != nil { t.Fatal("decode error: ", err) } @@ -58,7 +64,7 @@ func TestBlockEncoding(t *testing.T) { check("Root", block.Root(), common.HexToHash("0xef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) check("TxHash", block.TxHash(), common.HexToHash("0x5fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67")) check("ReceiptHash", block.ReceiptHash(), common.HexToHash("0xbc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52")) - check("Bloom", block.Bloom(), BytesToBloom(common.FromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))) + check("Bloom", block.Bloom(), types.BytesToBloom(common.FromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))) check("Difficulty", block.Difficulty(), big.NewInt(131072)) check("BlockNumber", block.NumberU64(), uint64(1)) check("GasLimit", block.GasLimit(), uint64(3141592)) @@ -68,7 +74,7 @@ func TestBlockEncoding(t *testing.T) { check("MixDigest", block.MixDigest(), common.HexToHash("0xbd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) check("Nonce", block.Nonce(), uint64(11617697748499542468)) check("BaseFee", block.BaseFee(), (*big.Int)(nil)) - check("BlockGasCost", block.BlockGasCost(), (*big.Int)(nil)) + check("BlockGasCost", BlockGasCost(&block), (*big.Int)(nil)) check("Size", block.Size(), uint64(len(blockEnc))) check("BlockHash", block.Hash(), common.HexToHash("0x0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e")) @@ -87,7 +93,7 @@ func TestBlockEncoding(t *testing.T) { func TestEIP1559BlockEncoding(t *testing.T) { blockEnc := common.FromHex("f9030bf901fea083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4843b9aca00f90106f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b8a302f8a0018080843b9aca008301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0") - var block Block + var block types.Block if err := rlp.DecodeBytes(blockEnc, &block); err != nil { t.Fatal("decode error: ", err) } @@ -109,20 +115,20 @@ func TestEIP1559BlockEncoding(t *testing.T) { check("Time", block.Time(), uint64(1426516743)) check("Size", block.Size(), uint64(len(blockEnc))) check("BaseFee", block.BaseFee(), new(big.Int).SetUint64(1000000000)) - check("BlockGasCost", block.BlockGasCost(), (*big.Int)(nil)) + check("BlockGasCost", BlockGasCost(&block), (*big.Int)(nil)) - tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) - tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) + tx1 := types.NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) + tx1, _ = tx1.WithSignature(types.HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) addr := common.HexToAddress("0x0000000000000000000000000000000000000001") - accesses := AccessList{AccessTuple{ + accesses := types.AccessList{types.AccessTuple{ Address: addr, StorageKeys: []common.Hash{ {0}, }, }} to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - txdata := &DynamicFeeTx{ + txdata := &types.DynamicFeeTx{ ChainID: big.NewInt(1), Nonce: 0, To: &to, @@ -132,8 +138,8 @@ func TestEIP1559BlockEncoding(t *testing.T) { AccessList: accesses, Data: []byte{}, } - tx2 := NewTx(txdata) - tx2, err := tx2.WithSignature(LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800")) + tx2 := types.NewTx(txdata) + tx2, err := tx2.WithSignature(types.LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800")) if err != nil { t.Fatal("invalid signature error: ", err) } @@ -153,7 +159,7 @@ func TestEIP1559BlockEncoding(t *testing.T) { func TestEIP2718BlockEncoding(t *testing.T) { blockEnc := common.FromHex("f90319f90211a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a0e6e49996c7ec59f7a23d22b83239a60151512c65613bf84a0d7da336399ebc4aa0cafe75574d59780665a97fbfd11365c7545aa8f1abf4e5e12e8243334ef7286bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000820200832fefd882a410845506eb0796636f6f6c65737420626c6f636b206f6e20636861696ea0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f90101f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b89e01f89b01800a8301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000001a03dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335a0476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef14c0") - var block Block + var block types.Block if err := rlp.DecodeBytes(blockEnc, &block); err != nil { t.Fatal("decode error: ", err) } @@ -173,11 +179,11 @@ func TestEIP2718BlockEncoding(t *testing.T) { check("Time", block.Time(), uint64(1426516743)) check("Size", block.Size(), uint64(len(blockEnc))) check("BaseFee", block.BaseFee(), (*big.Int)(nil)) - check("BlockGasCost", block.BlockGasCost(), (*big.Int)(nil)) + check("BlockGasCost", BlockGasCost(&block), (*big.Int)(nil)) // Create legacy tx. to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - tx1 := NewTx(&LegacyTx{ + tx1 := types.NewTx(&types.LegacyTx{ Nonce: 0, To: &to, Value: big.NewInt(10), @@ -185,25 +191,25 @@ func TestEIP2718BlockEncoding(t *testing.T) { GasPrice: big.NewInt(10), }) sig := common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100") - tx1, _ = tx1.WithSignature(HomesteadSigner{}, sig) + tx1, _ = tx1.WithSignature(types.HomesteadSigner{}, sig) // Create ACL tx. addr := common.HexToAddress("0x0000000000000000000000000000000000000001") - tx2 := NewTx(&AccessListTx{ + tx2 := types.NewTx(&types.AccessListTx{ ChainID: big.NewInt(1), Nonce: 0, To: &to, Gas: 123457, GasPrice: big.NewInt(10), - AccessList: AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}}, + AccessList: types.AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}}, }) sig2 := common.Hex2Bytes("3dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef1401") - tx2, _ = tx2.WithSignature(NewEIP2930Signer(big.NewInt(1)), sig2) + tx2, _ = tx2.WithSignature(types.NewEIP2930Signer(big.NewInt(1)), sig2) check("len(Transactions)", len(block.Transactions()), 2) check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash()) check("Transactions[1].Hash", block.Transactions()[1].Hash(), tx2.Hash()) - check("Transactions[1].Type()", block.Transactions()[1].Type(), uint8(AccessListTxType)) + check("Transactions[1].Type()", block.Transactions()[1].Type(), uint8(types.AccessListTxType)) ourBlockEnc, err := rlp.EncodeToBytes(&block) if err != nil { @@ -215,8 +221,8 @@ func TestEIP2718BlockEncoding(t *testing.T) { } func TestUncleHash(t *testing.T) { - uncles := make([]*Header, 0) - h := CalcUncleHash(uncles) + uncles := make([]*types.Header, 0) + h := types.CalcUncleHash(uncles) exp := common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") if h != exp { t.Fatalf("empty uncle hash is wrong, got %x != %x", h, exp) @@ -237,15 +243,15 @@ func BenchmarkEncodeBlock(b *testing.B) { } } -func makeBenchBlock() *Block { +func makeBenchBlock() *types.Block { var ( key, _ = crypto.GenerateKey() - txs = make([]*Transaction, 70) - receipts = make([]*Receipt, len(txs)) - signer = LatestSigner(params.TestChainConfig) - uncles = make([]*Header, 3) + txs = make([]*types.Transaction, 70) + receipts = make([]*types.Receipt, len(txs)) + signer = types.LatestSigner(params.TestChainConfig) + uncles = make([]*types.Header, 3) ) - header := &Header{ + header := &types.Header{ Difficulty: math.BigPow(11, 11), Number: math.BigPow(2, 9), GasLimit: 12345678, @@ -257,16 +263,16 @@ func makeBenchBlock() *Block { amount := math.BigPow(2, int64(i)) price := big.NewInt(300000) data := make([]byte, 100) - tx := NewTransaction(uint64(i), common.Address{}, amount, 123457, price, data) - signedTx, err := SignTx(tx, signer, key) + tx := types.NewTransaction(uint64(i), common.Address{}, amount, 123457, price, data) + signedTx, err := types.SignTx(tx, signer, key) if err != nil { panic(err) } txs[i] = signedTx - receipts[i] = NewReceipt(make([]byte, 32), false, tx.Gas()) + receipts[i] = types.NewReceipt(make([]byte, 32), false, tx.Gas()) } for i := range uncles { - uncles[i] = &Header{ + uncles[i] = &types.Header{ Difficulty: math.BigPow(11, 11), Number: math.BigPow(2, 9), GasLimit: 12345678, @@ -275,13 +281,12 @@ func makeBenchBlock() *Block { Extra: []byte("benchmark uncle"), } } - return NewBlock(header, txs, uncles, receipts, blocktest.NewHasher()) + return types.NewBlock(header, txs, uncles, receipts, blocktest.NewHasher()) } func TestSubnetEVMBlockEncoding(t *testing.T) { blockEnc := common.FromHex("f9030ff90202a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4843b9aca00830186a0f90106f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b8a302f8a0018080843b9aca008301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0") - - var block Block + var block types.Block if err := rlp.DecodeBytes(blockEnc, &block); err != nil { t.Fatal("decode error: ", err) } @@ -303,20 +308,20 @@ func TestSubnetEVMBlockEncoding(t *testing.T) { check("Time", block.Time(), uint64(1426516743)) check("Size", block.Size(), uint64(len(blockEnc))) check("BaseFee", block.BaseFee(), big.NewInt(1_000_000_000)) - check("BlockGasCost", block.BlockGasCost(), big.NewInt(100_000)) + check("BlockGasCost", BlockGasCost(&block), big.NewInt(100_000)) - tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) - tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) + tx1 := types.NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) + tx1, _ = tx1.WithSignature(types.HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) addr := common.HexToAddress("0x0000000000000000000000000000000000000001") - accesses := AccessList{AccessTuple{ + accesses := types.AccessList{types.AccessTuple{ Address: addr, StorageKeys: []common.Hash{ {0}, }, }} to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - txdata := &DynamicFeeTx{ + txdata := &types.DynamicFeeTx{ ChainID: big.NewInt(1), Nonce: 0, To: &to, @@ -326,8 +331,8 @@ func TestSubnetEVMBlockEncoding(t *testing.T) { AccessList: accesses, Data: []byte{}, } - tx2 := NewTx(txdata) - tx2, err := tx2.WithSignature(LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800")) + tx2 := types.NewTx(txdata) + tx2, err := tx2.WithSignature(types.LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800")) if err != nil { t.Fatal("invalid signature error: ", err) } diff --git a/plugin/evm/customtypes/gen_header_serializable_json.go b/plugin/evm/customtypes/gen_header_serializable_json.go new file mode 100644 index 0000000000..9761af5d36 --- /dev/null +++ b/plugin/evm/customtypes/gen_header_serializable_json.go @@ -0,0 +1,169 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package customtypes + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/types" +) + +var _ = (*headerMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (h HeaderSerializable) MarshalJSON() ([]byte, error) { + type HeaderSerializable struct { + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom types.Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash"` + Nonce types.BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + BlockGasCost *hexutil.Big `json:"blockGasCost" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + Hash common.Hash `json:"hash"` + } + var enc HeaderSerializable + enc.ParentHash = h.ParentHash + enc.UncleHash = h.UncleHash + enc.Coinbase = h.Coinbase + enc.Root = h.Root + enc.TxHash = h.TxHash + enc.ReceiptHash = h.ReceiptHash + enc.Bloom = h.Bloom + enc.Difficulty = (*hexutil.Big)(h.Difficulty) + enc.Number = (*hexutil.Big)(h.Number) + enc.GasLimit = hexutil.Uint64(h.GasLimit) + enc.GasUsed = hexutil.Uint64(h.GasUsed) + enc.Time = hexutil.Uint64(h.Time) + enc.Extra = h.Extra + enc.MixDigest = h.MixDigest + enc.Nonce = h.Nonce + enc.BaseFee = (*hexutil.Big)(h.BaseFee) + enc.BlockGasCost = (*hexutil.Big)(h.BlockGasCost) + enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed) + enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas) + enc.ParentBeaconRoot = h.ParentBeaconRoot + enc.Hash = h.Hash() + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (h *HeaderSerializable) UnmarshalJSON(input []byte) error { + type HeaderSerializable struct { + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase *common.Address `json:"miner" gencodec:"required"` + Root *common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom *types.Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest *common.Hash `json:"mixHash"` + Nonce *types.BlockNonce `json:"nonce"` + BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` + BlockGasCost *hexutil.Big `json:"blockGasCost" rlp:"optional"` + BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` + ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + } + var dec HeaderSerializable + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.ParentHash == nil { + return errors.New("missing required field 'parentHash' for HeaderSerializable") + } + h.ParentHash = *dec.ParentHash + if dec.UncleHash == nil { + return errors.New("missing required field 'sha3Uncles' for HeaderSerializable") + } + h.UncleHash = *dec.UncleHash + if dec.Coinbase == nil { + return errors.New("missing required field 'miner' for HeaderSerializable") + } + h.Coinbase = *dec.Coinbase + if dec.Root == nil { + return errors.New("missing required field 'stateRoot' for HeaderSerializable") + } + h.Root = *dec.Root + if dec.TxHash == nil { + return errors.New("missing required field 'transactionsRoot' for HeaderSerializable") + } + h.TxHash = *dec.TxHash + if dec.ReceiptHash == nil { + return errors.New("missing required field 'receiptsRoot' for HeaderSerializable") + } + h.ReceiptHash = *dec.ReceiptHash + if dec.Bloom == nil { + return errors.New("missing required field 'logsBloom' for HeaderSerializable") + } + h.Bloom = *dec.Bloom + if dec.Difficulty == nil { + return errors.New("missing required field 'difficulty' for HeaderSerializable") + } + h.Difficulty = (*big.Int)(dec.Difficulty) + if dec.Number == nil { + return errors.New("missing required field 'number' for HeaderSerializable") + } + h.Number = (*big.Int)(dec.Number) + if dec.GasLimit == nil { + return errors.New("missing required field 'gasLimit' for HeaderSerializable") + } + h.GasLimit = uint64(*dec.GasLimit) + if dec.GasUsed == nil { + return errors.New("missing required field 'gasUsed' for HeaderSerializable") + } + h.GasUsed = uint64(*dec.GasUsed) + if dec.Time == nil { + return errors.New("missing required field 'timestamp' for HeaderSerializable") + } + h.Time = uint64(*dec.Time) + if dec.Extra == nil { + return errors.New("missing required field 'extraData' for HeaderSerializable") + } + h.Extra = *dec.Extra + if dec.MixDigest != nil { + h.MixDigest = *dec.MixDigest + } + if dec.Nonce != nil { + h.Nonce = *dec.Nonce + } + if dec.BaseFee != nil { + h.BaseFee = (*big.Int)(dec.BaseFee) + } + if dec.BlockGasCost != nil { + h.BlockGasCost = (*big.Int)(dec.BlockGasCost) + } + if dec.BlobGasUsed != nil { + h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) + } + if dec.ExcessBlobGas != nil { + h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) + } + if dec.ParentBeaconRoot != nil { + h.ParentBeaconRoot = dec.ParentBeaconRoot + } + return nil +} diff --git a/core/types/gen_header_rlp.go b/plugin/evm/customtypes/gen_header_serializable_rlp.go similarity index 95% rename from core/types/gen_header_rlp.go rename to plugin/evm/customtypes/gen_header_serializable_rlp.go index 8ad0c44146..1b1f887b02 100644 --- a/core/types/gen_header_rlp.go +++ b/plugin/evm/customtypes/gen_header_serializable_rlp.go @@ -1,11 +1,11 @@ // Code generated by rlpgen. DO NOT EDIT. -package types +package customtypes import "github.com/ava-labs/libevm/rlp" import "io" -func (obj *Header) EncodeRLP(_w io.Writer) error { +func (obj *HeaderSerializable) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) _tmp0 := w.List() w.WriteBytes(obj.ParentHash[:]) diff --git a/core/types/state_account.go b/plugin/evm/customtypes/hashing.go similarity index 67% rename from core/types/state_account.go rename to plugin/evm/customtypes/hashing.go index 20dd6a0f2d..d2141526d2 100644 --- a/core/types/state_account.go +++ b/plugin/evm/customtypes/hashing.go @@ -24,22 +24,28 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types +package customtypes import ( - ethtypes "github.com/ava-labs/libevm/core/types" -) + "sync" -type ( - // Import these types from the go-ethereum package - StateAccount = ethtypes.StateAccount - SlimAccount = ethtypes.SlimAccount + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/crypto" + "github.com/ava-labs/libevm/rlp" + "golang.org/x/crypto/sha3" ) -var ( - // Import these functions from the go-ethereum package - NewEmptyStateAccount = ethtypes.NewEmptyStateAccount - SlimAccountRLP = ethtypes.SlimAccountRLP - FullAccount = ethtypes.FullAccount - FullAccountRLP = ethtypes.FullAccountRLP -) +// hasherPool holds LegacyKeccak256 hashers for rlpHash. +var hasherPool = sync.Pool{ + New: func() interface{} { return sha3.NewLegacyKeccak256() }, +} + +// rlpHash encodes x and hashes the encoded bytes. +func rlpHash(x interface{}) (h common.Hash) { + sha := hasherPool.Get().(crypto.KeccakState) + defer hasherPool.Put(sha) + sha.Reset() + rlp.Encode(sha, x) + sha.Read(h[:]) + return h +} diff --git a/core/types/hashing_test.go b/plugin/evm/customtypes/hashing_test.go similarity index 98% rename from core/types/hashing_test.go rename to plugin/evm/customtypes/hashing_test.go index b299b7181c..31c15e2d61 100644 --- a/core/types/hashing_test.go +++ b/plugin/evm/customtypes/hashing_test.go @@ -24,7 +24,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types_test +package customtypes_test import ( "bytes" @@ -36,12 +36,12 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) func TestDeriveSha(t *testing.T) { diff --git a/plugin/evm/customtypes/header_ext.go b/plugin/evm/customtypes/header_ext.go new file mode 100644 index 0000000000..c47b13a4c0 --- /dev/null +++ b/plugin/evm/customtypes/header_ext.go @@ -0,0 +1,212 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ( + "io" + "math/big" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/common/hexutil" + ethtypes "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/rlp" +) + +// GetHeaderExtra returns the [HeaderExtra] from the given [Header]. +func GetHeaderExtra(h *ethtypes.Header) *HeaderExtra { + return extras.Header.Get(h) +} + +// SetHeaderExtra sets the given [HeaderExtra] on the [Header]. +func SetHeaderExtra(h *ethtypes.Header, extra *HeaderExtra) { + extras.Header.Set(h, extra) +} + +// WithHeaderExtra sets the given [HeaderExtra] on the [Header] +// and returns the [Header] for chaining. +func WithHeaderExtra(h *ethtypes.Header, extra *HeaderExtra) *ethtypes.Header { + SetHeaderExtra(h, extra) + return h +} + +// HeaderExtra is a struct that contains extra fields used by Subnet-EVM +// in the block header. +// This type uses [HeaderSerializable] to encode and decode the extra fields +// along with the upstream type for compatibility with existing network blocks. +type HeaderExtra struct { + BlockGasCost *big.Int +} + +// EncodeRLP RLP encodes the given [ethtypes.Header] and [HeaderExtra] together +// to the `writer`. It does merge both structs into a single [HeaderSerializable]. +func (h *HeaderExtra) EncodeRLP(eth *ethtypes.Header, writer io.Writer) error { + temp := new(HeaderSerializable) + + temp.updateFromEth(eth) + temp.updateFromExtras(h) + + return rlp.Encode(writer, temp) +} + +// DecodeRLP RLP decodes from the [*rlp.Stream] and writes the output to both the +// [ethtypes.Header] passed as argument and to the receiver [HeaderExtra]. +func (h *HeaderExtra) DecodeRLP(eth *ethtypes.Header, stream *rlp.Stream) error { + temp := new(HeaderSerializable) + if err := stream.Decode(temp); err != nil { + return err + } + + temp.updateToEth(eth) + temp.updateToExtras(h) + + return nil +} + +// EncodeJSON JSON encodes the given [ethtypes.Header] and [HeaderExtra] together +// to the `writer`. It does merge both structs into a single [HeaderSerializable]. +func (h *HeaderExtra) EncodeJSON(eth *ethtypes.Header) ([]byte, error) { + temp := new(HeaderSerializable) + + temp.updateFromEth(eth) + temp.updateFromExtras(h) + + return temp.MarshalJSON() +} + +// DecodeJSON JSON decodes from the `input` bytes and writes the output to both the +// [ethtypes.Header] passed as argument and to the receiver [HeaderExtra]. +func (h *HeaderExtra) DecodeJSON(eth *ethtypes.Header, input []byte) error { + temp := new(HeaderSerializable) + if err := temp.UnmarshalJSON(input); err != nil { + return err + } + + temp.updateToEth(eth) + temp.updateToExtras(h) + + return nil +} + +func (h *HeaderExtra) PostCopy(dst *ethtypes.Header) { + cp := &HeaderExtra{} + if h.BlockGasCost != nil { + cp.BlockGasCost = new(big.Int).Set(h.BlockGasCost) + } + SetHeaderExtra(dst, cp) +} + +func (h *HeaderSerializable) updateFromEth(eth *ethtypes.Header) { + h.ParentHash = eth.ParentHash + h.UncleHash = eth.UncleHash + h.Coinbase = eth.Coinbase + h.Root = eth.Root + h.TxHash = eth.TxHash + h.ReceiptHash = eth.ReceiptHash + h.Bloom = eth.Bloom + h.Difficulty = eth.Difficulty + h.Number = eth.Number + h.GasLimit = eth.GasLimit + h.GasUsed = eth.GasUsed + h.Time = eth.Time + h.Extra = eth.Extra + h.MixDigest = eth.MixDigest + h.Nonce = eth.Nonce + h.BaseFee = eth.BaseFee + h.BlobGasUsed = eth.BlobGasUsed + h.ExcessBlobGas = eth.ExcessBlobGas + h.ParentBeaconRoot = eth.ParentBeaconRoot +} + +func (h *HeaderSerializable) updateToEth(eth *ethtypes.Header) { + eth.ParentHash = h.ParentHash + eth.UncleHash = h.UncleHash + eth.Coinbase = h.Coinbase + eth.Root = h.Root + eth.TxHash = h.TxHash + eth.ReceiptHash = h.ReceiptHash + eth.Bloom = h.Bloom + eth.Difficulty = h.Difficulty + eth.Number = h.Number + eth.GasLimit = h.GasLimit + eth.GasUsed = h.GasUsed + eth.Time = h.Time + eth.Extra = h.Extra + eth.MixDigest = h.MixDigest + eth.Nonce = h.Nonce + eth.BaseFee = h.BaseFee + eth.BlobGasUsed = h.BlobGasUsed + eth.ExcessBlobGas = h.ExcessBlobGas + eth.ParentBeaconRoot = h.ParentBeaconRoot +} + +func (h *HeaderSerializable) updateFromExtras(extras *HeaderExtra) { + h.BlockGasCost = extras.BlockGasCost +} + +func (h *HeaderSerializable) updateToExtras(extras *HeaderExtra) { + extras.BlockGasCost = h.BlockGasCost +} + +//go:generate go run github.com/fjl/gencodec -type HeaderSerializable -field-override headerMarshaling -out gen_header_serializable_json.go +//go:generate go run github.com/ava-labs/libevm/rlp/rlpgen@739ba847f6f407f63fd6a24175b24e56fea583a1 -type HeaderSerializable -out gen_header_serializable_rlp.go + +// HeaderSerializable defines the header of a block in the Ethereum blockchain, +// as it is to be serialized into RLP and JSON. Note it must be exported so that +// rlpgen can generate the serialization code from it. +type HeaderSerializable struct { + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom ethtypes.Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *big.Int `json:"difficulty" gencodec:"required"` + Number *big.Int `json:"number" gencodec:"required"` + GasLimit uint64 `json:"gasLimit" gencodec:"required"` + GasUsed uint64 `json:"gasUsed" gencodec:"required"` + Time uint64 `json:"timestamp" gencodec:"required"` + Extra []byte `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash"` + Nonce ethtypes.BlockNonce `json:"nonce"` + + // BaseFee was added by EIP-1559 and is ignored in legacy headers. + BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` + + // BlockGasCost was added by SubnetEVM and is ignored in legacy + // headers. + BlockGasCost *big.Int `json:"blockGasCost" rlp:"optional"` + + // BlobGasUsed was added by EIP-4844 and is ignored in legacy headers. + BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` + + // ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers. + ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` + + // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. + ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` +} + +// field type overrides for gencodec +type headerMarshaling struct { + Difficulty *hexutil.Big + Number *hexutil.Big + GasLimit hexutil.Uint64 + GasUsed hexutil.Uint64 + Time hexutil.Uint64 + Extra hexutil.Bytes + BaseFee *hexutil.Big + BlockGasCost *hexutil.Big + Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON + BlobGasUsed *hexutil.Uint64 + ExcessBlobGas *hexutil.Uint64 +} + +// Hash returns the block hash of the header, which is simply the keccak256 hash of its +// RLP encoding. +// This function MUST be exported and is used in [HeaderSerializable.EncodeJSON] which is +// generated to the file gen_header_json.go. +func (h *HeaderSerializable) Hash() common.Hash { + return rlpHash(h) +} diff --git a/plugin/evm/customtypes/header_ext_test.go b/plugin/evm/customtypes/header_ext_test.go new file mode 100644 index 0000000000..1ddc3d80d3 --- /dev/null +++ b/plugin/evm/customtypes/header_ext_test.go @@ -0,0 +1,185 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ( + "encoding/hex" + "encoding/json" + "math/big" + "reflect" + "slices" + "testing" + "unsafe" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/rlp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + // TODO(arr4n) These tests were originally part of the `subnet-evm/core/types` + // package so assume the presence of identifiers. A dot-import reduces PR + // noise during the refactoring. + . "github.com/ava-labs/libevm/core/types" +) + +func TestHeaderRLP(t *testing.T) { + t.Parallel() + + got := testHeaderEncodeDecode(t, rlp.EncodeToBytes, rlp.DecodeBytes) + + // Golden data from original subnet-evm implementation, before integration of + // libevm. WARNING: changing these values can break backwards compatibility + // with extreme consequences as block-hash calculation may break. + const ( + wantHex = "f90212a00100000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000940300000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000b901000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008090a0b0c0da00e00000000000000000000000000000000000000000000000000000000000000880f0000000000000010151213a01400000000000000000000000000000000000000000000000000000000000000" + wantHashHex = "2453a240c1cfa4eca66bf39db950d5bd57f5e94ffabf9d800497ace33c2a5927" + ) + + assert.Equal(t, wantHex, hex.EncodeToString(got), "Header RLP") + + header, _ := headerWithNonZeroFields() + gotHashHex := header.Hash().Hex() + assert.Equal(t, "0x"+wantHashHex, gotHashHex, "Header.Hash()") +} + +func TestHeaderJSON(t *testing.T) { + t.Parallel() + + // Note we ignore the returned encoded bytes because we don't + // need to compare them to a JSON gold standard. + _ = testHeaderEncodeDecode(t, json.Marshal, json.Unmarshal) +} + +func testHeaderEncodeDecode( + t *testing.T, + encode func(any) ([]byte, error), + decode func([]byte, any) error, +) (encoded []byte) { + t.Helper() + + input, _ := headerWithNonZeroFields() // the Header carries the HeaderExtra so we can ignore it + encoded, err := encode(input) + require.NoError(t, err, "encode") + + gotHeader := new(Header) + err = decode(encoded, gotHeader) + require.NoError(t, err, "decode") + gotExtra := GetHeaderExtra(gotHeader) + + wantHeader, wantExtra := headerWithNonZeroFields() + wantHeader.WithdrawalsHash = nil + assert.Equal(t, wantHeader, gotHeader) + assert.Equal(t, wantExtra, gotExtra) + + return encoded +} + +func TestHeaderWithNonZeroFields(t *testing.T) { + t.Parallel() + + header, extra := headerWithNonZeroFields() + t.Run("Header", func(t *testing.T) { allFieldsSet(t, header, "extra") }) + t.Run("HeaderExtra", func(t *testing.T) { allFieldsSet(t, extra) }) +} + +// headerWithNonZeroFields returns a [Header] and a [HeaderExtra], +// each with all fields set to non-zero values. +// The [HeaderExtra] extra payload is set in the [Header] via [WithHeaderExtra]. +// +// NOTE: They can be used to demonstrate that RLP and JSON round-trip encoding +// can recover all fields, but not that the encoded format is correct. This is +// very important as the RLP encoding of a [Header] defines its hash. +func headerWithNonZeroFields() (*Header, *HeaderExtra) { + header := &Header{ + ParentHash: common.Hash{1}, + UncleHash: common.Hash{2}, + Coinbase: common.Address{3}, + Root: common.Hash{4}, + TxHash: common.Hash{5}, + ReceiptHash: common.Hash{6}, + Bloom: Bloom{7}, + Difficulty: big.NewInt(8), + Number: big.NewInt(9), + GasLimit: 10, + GasUsed: 11, + Time: 12, + Extra: []byte{13}, + MixDigest: common.Hash{14}, + Nonce: BlockNonce{15}, + BaseFee: big.NewInt(16), + WithdrawalsHash: &common.Hash{17}, + BlobGasUsed: ptrTo(uint64(18)), + ExcessBlobGas: ptrTo(uint64(19)), + ParentBeaconRoot: &common.Hash{20}, + } + extra := &HeaderExtra{ + BlockGasCost: big.NewInt(21), + } + return WithHeaderExtra(header, extra), extra +} + +func allFieldsSet[T interface { + Header | HeaderExtra +}](t *testing.T, x *T, ignoredFields ...string) { + // We don't test for nil pointers because we're only confirming that + // test-input data is well-formed. A panic due to a dereference will be + // reported anyway. + + v := reflect.ValueOf(x).Elem() + for i := range v.Type().NumField() { + field := v.Type().Field(i) + if slices.Contains(ignoredFields, field.Name) { + continue + } + + t.Run(field.Name, func(t *testing.T) { + fieldValue := v.Field(i) + if !field.IsExported() { + // Note: we need to check unexported fields especially for [Block]. + if fieldValue.Kind() == reflect.Ptr { + require.Falsef(t, fieldValue.IsNil(), "field %q is nil", field.Name) + } + fieldValue = reflect.NewAt(fieldValue.Type(), unsafe.Pointer(fieldValue.UnsafeAddr())).Elem() //nolint:gosec + } + + switch f := fieldValue.Interface().(type) { + case common.Hash: + assertNonZero(t, f) + case common.Address: + assertNonZero(t, f) + case BlockNonce: + assertNonZero(t, f) + case Bloom: + assertNonZero(t, f) + case uint64: + assertNonZero(t, f) + case *big.Int: + assertNonZero(t, f) + case *common.Hash: + assertNonZero(t, f) + case *uint64: + assertNonZero(t, f) + case []uint8: + assert.NotEmpty(t, f) + default: + t.Errorf("Field %q has unsupported type %T", field.Name, f) + } + }) + } +} + +func assertNonZero[T interface { + common.Hash | common.Address | BlockNonce | uint64 | Bloom | + *big.Int | *common.Hash | *uint64 +}](t *testing.T, v T) { + t.Helper() + var zero T + if v == zero { + t.Errorf("must not be zero value for %T", v) + } +} + +// Note [TestCopyHeader] tests the [HeaderExtra.PostCopy] method. + +func ptrTo[T any](x T) *T { return &x } diff --git a/plugin/evm/customtypes/libevm.go b/plugin/evm/customtypes/libevm.go new file mode 100644 index 0000000000..6aec45ed37 --- /dev/null +++ b/plugin/evm/customtypes/libevm.go @@ -0,0 +1,25 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ( + "io" + + ethtypes "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/rlp" +) + +var extras = ethtypes.RegisterExtras[ + HeaderExtra, *HeaderExtra, + ethtypes.NOOPBlockBodyHooks, *ethtypes.NOOPBlockBodyHooks, + noopStateAccountExtras, +]() + +type noopStateAccountExtras struct{} + +// EncodeRLP implements the [rlp.Encoder] interface. +func (noopStateAccountExtras) EncodeRLP(w io.Writer) error { return nil } + +// DecodeRLP implements the [rlp.Decoder] interface. +func (*noopStateAccountExtras) DecodeRLP(s *rlp.Stream) error { return nil } diff --git a/plugin/evm/customtypes/log_ext.go b/plugin/evm/customtypes/log_ext.go new file mode 100644 index 0000000000..4b92869fab --- /dev/null +++ b/plugin/evm/customtypes/log_ext.go @@ -0,0 +1,15 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package customtypes + +import ethtypes "github.com/ava-labs/libevm/core/types" + +// FlattenLogs converts a nested array of logs to a single array of logs. +func FlattenLogs(list [][]*ethtypes.Log) []*ethtypes.Log { + var flat []*ethtypes.Log + for _, logs := range list { + flat = append(flat, logs...) + } + return flat +} diff --git a/core/types/rlp_fuzzer_test.go b/plugin/evm/customtypes/rlp_fuzzer_test.go similarity index 92% rename from core/types/rlp_fuzzer_test.go rename to plugin/evm/customtypes/rlp_fuzzer_test.go index 4e3645874a..dcdbd6f1e7 100644 --- a/core/types/rlp_fuzzer_test.go +++ b/plugin/evm/customtypes/rlp_fuzzer_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types +package customtypes import ( "bytes" @@ -24,6 +24,11 @@ import ( "github.com/ava-labs/libevm/rlp" "github.com/holiman/uint256" + + // TODO(arr4n) These tests were originally part of the `subnet-evm/core/types` + // package so assume the presence of identifiers. A dot-import reduces PR + // noise during the refactoring. + . "github.com/ava-labs/libevm/core/types" ) func decodeEncode(input []byte, val interface{}) error { diff --git a/core/types/types_test.go b/plugin/evm/customtypes/types_test.go similarity index 93% rename from core/types/types_test.go rename to plugin/evm/customtypes/types_test.go index 7620aafb7f..1d0fde5342 100644 --- a/core/types/types_test.go +++ b/plugin/evm/customtypes/types_test.go @@ -24,7 +24,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package types +package customtypes import ( "math/big" @@ -33,6 +33,11 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" + + // TODO(arr4n) These tests were originally part of the `subnet-evm/core/types` + // package so assume the presence of identifiers. A dot-import reduces PR + // noise during the refactoring. + . "github.com/ava-labs/libevm/core/types" ) type devnull struct{ len int } diff --git a/plugin/evm/gossip.go b/plugin/evm/gossip.go index fab3332933..11e3d8ade9 100644 --- a/plugin/evm/gossip.go +++ b/plugin/evm/gossip.go @@ -20,9 +20,9 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth" ) diff --git a/plugin/evm/gossip_test.go b/plugin/evm/gossip_test.go index ec4063a664..ac32b357e0 100644 --- a/plugin/evm/gossip_test.go +++ b/plugin/evm/gossip_test.go @@ -11,14 +11,14 @@ import ( "github.com/ava-labs/avalanchego/network/p2p/gossip" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/txpool" "github.com/ava-labs/subnet-evm/core/txpool/legacypool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/utils" "github.com/prometheus/client_golang/prometheus" diff --git a/plugin/evm/gossiper_eth_gossiping_test.go b/plugin/evm/gossiper_eth_gossiping_test.go index e3ab49b323..21835a963d 100644 --- a/plugin/evm/gossiper_eth_gossiping_test.go +++ b/plugin/evm/gossiper_eth_gossiping_test.go @@ -23,8 +23,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/plugin/evm/header/base_fee.go b/plugin/evm/header/base_fee.go index b838069271..7f83800b93 100644 --- a/plugin/evm/header/base_fee.go +++ b/plugin/evm/header/base_fee.go @@ -7,8 +7,8 @@ import ( "errors" "math/big" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" ) diff --git a/plugin/evm/header/base_fee_test.go b/plugin/evm/header/base_fee_test.go index 29a93e0c62..8bac5fbdd4 100644 --- a/plugin/evm/header/base_fee_test.go +++ b/plugin/evm/header/base_fee_test.go @@ -8,8 +8,8 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/subnetevm" "github.com/ava-labs/subnet-evm/utils" diff --git a/plugin/evm/header/block_gas_cost.go b/plugin/evm/header/block_gas_cost.go index 49857edc1a..29d1b45770 100644 --- a/plugin/evm/header/block_gas_cost.go +++ b/plugin/evm/header/block_gas_cost.go @@ -8,10 +8,11 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/blockgascost" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" ) var ( @@ -43,7 +44,7 @@ func BlockGasCost( } return new(big.Int).SetUint64(BlockGasCostWithStep( feeConfig, - parent.BlockGasCost, + customtypes.GetHeaderExtra(parent).BlockGasCost, step, timeElapsed, )) @@ -87,12 +88,13 @@ func EstimateRequiredTip( config *extras.ChainConfig, header *types.Header, ) (*big.Int, error) { + extra := customtypes.GetHeaderExtra(header) switch { case !config.IsSubnetEVM(header.Time): return nil, nil case header.BaseFee == nil: return nil, errBaseFeeNil - case header.BlockGasCost == nil: + case extra.BlockGasCost == nil: return nil, errBlockGasCostNil } @@ -106,7 +108,7 @@ func EstimateRequiredTip( // We add totalGasUsed - 1 to ensure that the total required tips // calculation rounds up. totalRequiredTips := new(big.Int) - totalRequiredTips.Mul(header.BlockGasCost, header.BaseFee) + totalRequiredTips.Mul(extra.BlockGasCost, header.BaseFee) totalRequiredTips.Add(totalRequiredTips, totalGasUsed) totalRequiredTips.Sub(totalRequiredTips, common.Big1) diff --git a/plugin/evm/header/block_gas_cost_test.go b/plugin/evm/header/block_gas_cost_test.go index f5dc2fd279..4dbe9b2dea 100644 --- a/plugin/evm/header/block_gas_cost_test.go +++ b/plugin/evm/header/block_gas_cost_test.go @@ -7,9 +7,10 @@ import ( "math/big" "testing" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -94,10 +95,14 @@ func BlockGasCostTest(t *testing.T, feeConfig commontype.FeeConfig) { config := &extras.ChainConfig{ NetworkUpgrades: test.upgrades, } - parent := &types.Header{ - Time: test.parentTime, - BlockGasCost: test.parentCost, - } + parent := customtypes.WithHeaderExtra( + &types.Header{ + Time: test.parentTime, + }, + &customtypes.HeaderExtra{ + BlockGasCost: test.parentCost, + }, + ) assert.Equal(t, test.expected, BlockGasCost( config, @@ -226,9 +231,12 @@ func TestEstimateRequiredTip(t *testing.T) { { name: "nil_base_fee", subnetEVMTimestamp: utils.NewUint64(0), - header: &types.Header{ - BlockGasCost: big.NewInt(1), - }, + header: customtypes.WithHeaderExtra( + &types.Header{}, + &customtypes.HeaderExtra{ + BlockGasCost: big.NewInt(1), + }, + ), wantErr: errBaseFeeNil, }, { @@ -242,21 +250,29 @@ func TestEstimateRequiredTip(t *testing.T) { { name: "no_gas_used", subnetEVMTimestamp: utils.NewUint64(0), - header: &types.Header{ - GasUsed: 0, - BaseFee: big.NewInt(1), - BlockGasCost: big.NewInt(1), - }, + header: customtypes.WithHeaderExtra( + &types.Header{ + GasUsed: 0, + BaseFee: big.NewInt(1), + }, + &customtypes.HeaderExtra{ + BlockGasCost: big.NewInt(1), + }, + ), wantErr: errNoGasUsed, }, { name: "success", subnetEVMTimestamp: utils.NewUint64(0), - header: &types.Header{ - GasUsed: 912, - BaseFee: big.NewInt(456), - BlockGasCost: big.NewInt(101112), - }, + header: customtypes.WithHeaderExtra( + &types.Header{ + GasUsed: 912, + BaseFee: big.NewInt(456), + }, + &customtypes.HeaderExtra{ + BlockGasCost: big.NewInt(101112), + }, + ), // totalRequiredTips = BlockGasCost * BaseFee // estimatedTip = totalRequiredTips / GasUsed want: big.NewInt((101112 * 456) / (912)), @@ -264,11 +280,15 @@ func TestEstimateRequiredTip(t *testing.T) { { name: "success_rounds_up", subnetEVMTimestamp: utils.NewUint64(0), - header: &types.Header{ - GasUsed: 124, - BaseFee: big.NewInt(456), - BlockGasCost: big.NewInt(101112), - }, + header: customtypes.WithHeaderExtra( + &types.Header{ + GasUsed: 124, + BaseFee: big.NewInt(456), + }, + &customtypes.HeaderExtra{ + BlockGasCost: big.NewInt(101112), + }, + ), // totalGasUsed = GasUsed + ExtDataGasUsed // totalRequiredTips = BlockGasCost * BaseFee // estimatedTip = totalRequiredTips / totalGasUsed diff --git a/plugin/evm/header/dynamic_fee_windower.go b/plugin/evm/header/dynamic_fee_windower.go index d304f31846..35bf8dd361 100644 --- a/plugin/evm/header/dynamic_fee_windower.go +++ b/plugin/evm/header/dynamic_fee_windower.go @@ -10,8 +10,8 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/subnetevm" ) diff --git a/plugin/evm/header/extra.go b/plugin/evm/header/extra.go index 594a4a3971..e136c004df 100644 --- a/plugin/evm/header/extra.go +++ b/plugin/evm/header/extra.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/subnetevm" ) @@ -122,8 +122,10 @@ func SetPredicateBytesInExtra(extra []byte, predicateBytes []byte) []byte { if len(extra) < offset { // pad extra with zeros extra = append(extra, make([]byte, offset-len(extra))...) + } else { + // truncate extra to the offset + extra = extra[:offset] } - extra = extra[:offset] // truncate extra to the offset extra = append(extra, predicateBytes...) return extra } diff --git a/plugin/evm/header/extra_test.go b/plugin/evm/header/extra_test.go index 8e7e57616f..fd042c9f2d 100644 --- a/plugin/evm/header/extra_test.go +++ b/plugin/evm/header/extra_test.go @@ -7,8 +7,9 @@ import ( "math/big" "testing" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/subnetevm" "github.com/ava-labs/subnet-evm/utils" "github.com/stretchr/testify/require" @@ -82,14 +83,18 @@ func TestExtraPrefix(t *testing.T) { { name: "subnet_evm_normal", upgrades: extras.TestSubnetEVMChainConfig.NetworkUpgrades, - parent: &types.Header{ - Number: big.NewInt(1), - GasUsed: targetGas, - Extra: (&subnetevm.Window{ - 1, 2, 3, 4, - }).Bytes(), - BlockGasCost: big.NewInt(blockGas), - }, + parent: customtypes.WithHeaderExtra( + &types.Header{ + Number: big.NewInt(1), + GasUsed: targetGas, + Extra: (&subnetevm.Window{ + 1, 2, 3, 4, + }).Bytes(), + }, + &customtypes.HeaderExtra{ + BlockGasCost: big.NewInt(blockGas), + }, + ), header: &types.Header{ Time: 1, }, @@ -248,6 +253,82 @@ func TestVerifyExtra(t *testing.T) { } } +func TestPredicateBytesFromExtra(t *testing.T) { + tests := []struct { + name string + extra []byte + expected []byte + }{ + { + name: "empty_extra", + extra: nil, + expected: nil, + }, + { + name: "too_short", + extra: make([]byte, subnetevm.WindowSize-1), + expected: nil, + }, + { + name: "empty_predicate", + extra: make([]byte, subnetevm.WindowSize), + expected: nil, + }, + { + name: "non_empty_predicate", + extra: []byte{ + subnetevm.WindowSize: 5, + }, + expected: []byte{5}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := PredicateBytesFromExtra(test.extra) + require.Equal(t, test.expected, got) + }) + } +} + +func TestSetPredicateBytesInExtra(t *testing.T) { + tests := []struct { + name string + extra []byte + predicate []byte + want []byte + }{ + { + name: "empty_extra_predicate", + want: make([]byte, subnetevm.WindowSize), + }, + { + name: "extra_too_short", + extra: []byte{1}, + predicate: []byte{2}, + want: []byte{ + 0: 1, + subnetevm.WindowSize: 2, + }, + }, + { + name: "extra_too_long", + extra: []byte{ + subnetevm.WindowSize: 1, + }, + predicate: []byte{2}, + want: []byte{ + subnetevm.WindowSize: 2, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := SetPredicateBytesInExtra(test.extra, test.predicate) + require.Equal(t, test.want, got) + }) + } +} + func TestPredicateBytesExtra(t *testing.T) { tests := []struct { name string diff --git a/plugin/evm/header/gas_limit.go b/plugin/evm/header/gas_limit.go index 0c4b92ee0f..3b62e0ecc1 100644 --- a/plugin/evm/header/gas_limit.go +++ b/plugin/evm/header/gas_limit.go @@ -8,8 +8,8 @@ import ( "fmt" "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" ) diff --git a/plugin/evm/header/gas_limit_test.go b/plugin/evm/header/gas_limit_test.go index b4c6eeca39..20aee06d8b 100644 --- a/plugin/evm/header/gas_limit_test.go +++ b/plugin/evm/header/gas_limit_test.go @@ -6,8 +6,8 @@ package header import ( "testing" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" "github.com/stretchr/testify/require" ) diff --git a/plugin/evm/static_service_test.go b/plugin/evm/static_service_test.go index 94bf218870..de94041cb9 100644 --- a/plugin/evm/static_service_test.go +++ b/plugin/evm/static_service_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/ava-labs/avalanchego/utils/formatting" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/stretchr/testify/assert" ) diff --git a/plugin/evm/syncervm_client.go b/plugin/evm/syncervm_client.go index 2b52fc697b..fb48cf224e 100644 --- a/plugin/evm/syncervm_client.go +++ b/plugin/evm/syncervm_client.go @@ -15,9 +15,9 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/vms/components/chain" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" "github.com/ava-labs/subnet-evm/eth" "github.com/ava-labs/subnet-evm/params" diff --git a/plugin/evm/syncervm_test.go b/plugin/evm/syncervm_test.go index fb69bd76e7..7aac4fbdcf 100644 --- a/plugin/evm/syncervm_test.go +++ b/plugin/evm/syncervm_test.go @@ -26,6 +26,8 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" @@ -34,9 +36,8 @@ import ( "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/constants" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/plugin/evm/database" "github.com/ava-labs/subnet-evm/predicate" statesyncclient "github.com/ava-labs/subnet-evm/sync/client" @@ -592,12 +593,12 @@ func generateAndAcceptBlocks(t *testing.T, vm *VM, numBlocks int, gen func(int, // assertSyncPerformedHeights iterates over all heights the VM has synced to and // verifies it matches [expected]. func assertSyncPerformedHeights(t *testing.T, db ethdb.Iteratee, expected map[uint64]struct{}) { - it := rawdb.NewSyncPerformedIterator(db) + it := customrawdb.NewSyncPerformedIterator(db) defer it.Release() found := make(map[uint64]struct{}, len(expected)) for it.Next() { - found[rawdb.UnpackSyncPerformedKey(it.Key())] = struct{}{} + found[customrawdb.UnpackSyncPerformedKey(it.Key())] = struct{}{} } require.NoError(t, it.Error()) require.Equal(t, expected, found) diff --git a/plugin/evm/tx_gossip_test.go b/plugin/evm/tx_gossip_test.go index 0eaaa63e6d..319ad4e3bd 100644 --- a/plugin/evm/tx_gossip_test.go +++ b/plugin/evm/tx_gossip_test.go @@ -28,7 +28,7 @@ import ( "google.golang.org/protobuf/proto" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/utils" ) diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index d3f46614ca..c7177e37ab 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -23,15 +23,16 @@ import ( "github.com/ava-labs/avalanchego/network/p2p/gossip" "github.com/prometheus/client_golang/prometheus" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/metrics" + ethparams "github.com/ava-labs/libevm/params" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/constants" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth" "github.com/ava-labs/subnet-evm/eth/ethconfig" subnetevmprometheus "github.com/ava-labs/subnet-evm/metrics/prometheus" @@ -312,7 +313,7 @@ func (vm *VM) Initialize( } vm.logger = subnetEVMLogger - log.Info("Initializing Subnet EVM VM", "Version", Version, "Config", vm.config) + log.Info("Initializing Subnet EVM VM", "Version", Version, "libevm version", ethparams.LibEVMVersion, "Config", vm.config) if deprecateMsg != "" { log.Warn("Deprecation Warning", "msg", deprecateMsg) @@ -1158,11 +1159,15 @@ func (vm *VM) chainConfigExtra() *extras.ChainConfig { return params.GetExtra(vm.chainConfig) } +func (vm *VM) rules(number *big.Int, time uint64) extras.Rules { + ethrules := vm.chainConfig.Rules(number, params.IsMergeTODO, time) + return *params.GetRulesExtra(ethrules) +} + // currentRules returns the chain rules for the current block. func (vm *VM) currentRules() extras.Rules { header := vm.eth.APIBackend.CurrentHeader() - rules := vm.chainConfig.Rules(header.Number, params.IsMergeTODO, header.Time) - return *params.GetRulesExtra(rules) + return vm.rules(header.Number, header.Time) } // requirePrimaryNetworkSigners returns true if warp messages from the primary diff --git a/plugin/evm/vm_database.go b/plugin/evm/vm_database.go index f2e2d1b56f..f9d152dcf3 100644 --- a/plugin/evm/vm_database.go +++ b/plugin/evm/vm_database.go @@ -16,8 +16,8 @@ import ( "github.com/ava-labs/avalanchego/database/versiondb" avalancheconstants "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/plugin/evm/config" "github.com/ava-labs/subnet-evm/plugin/evm/database" ) diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 51f90e25d5..c51c269b0d 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -6,7 +6,6 @@ package evm import ( "context" "crypto/ecdsa" - "crypto/rand" "encoding/json" "errors" "fmt" @@ -18,6 +17,7 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" @@ -43,12 +43,13 @@ import ( "github.com/ava-labs/subnet-evm/constants" "github.com/ava-labs/subnet-evm/core" "github.com/ava-labs/subnet-evm/core/txpool" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" "github.com/ava-labs/subnet-evm/plugin/evm/config" + "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" "github.com/ava-labs/subnet-evm/plugin/evm/header" + "github.com/ava-labs/subnet-evm/plugin/evm/vmerrors" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist" "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" @@ -56,7 +57,6 @@ import ( "github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist" "github.com/ava-labs/subnet-evm/rpc" "github.com/ava-labs/subnet-evm/utils" - "github.com/ava-labs/subnet-evm/vmerrs" avagoconstants "github.com/ava-labs/avalanchego/utils/constants" ) @@ -361,10 +361,7 @@ func TestBuildEthTxBlock(t *testing.T) { newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1) vm.txPool.SubscribeNewReorgEvent(newTxPoolHeadChan) - key, err := utils.NewKey(rand.Reader) - if err != nil { - t.Fatal(err) - } + key := utils.NewKey(t) tx := types.NewTransaction(uint64(0), key.Address, firstTxAmount, 21000, big.NewInt(testMinGasPrice), nil) signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0]) @@ -1984,8 +1981,8 @@ func TestBuildSubnetEVMBlock(t *testing.T) { blk = issueAndAccept(t, issuer, vm) ethBlk := blk.(*chain.BlockWrapper).Block.(*Block).ethBlock - if ethBlk.BlockGasCost() == nil || ethBlk.BlockGasCost().Cmp(big.NewInt(100)) < 0 { - t.Fatalf("expected blockGasCost to be at least 100 but got %d", ethBlk.BlockGasCost()) + if customtypes.BlockGasCost(ethBlk) == nil || customtypes.BlockGasCost(ethBlk).Cmp(big.NewInt(100)) < 0 { + t.Fatalf("expected blockGasCost to be at least 100 but got %d", customtypes.BlockGasCost(ethBlk)) } chainConfig := params.GetExtra(vm.chainConfig) minRequiredTip, err := header.EstimateRequiredTip(chainConfig, ethBlk.Header()) @@ -2163,7 +2160,7 @@ func TestTxAllowListSuccessfulTx(t *testing.T) { } errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1}) - if err := errs[0]; !errors.Is(err, vmerrs.ErrSenderAddressNotAllowListed) { + if err := errs[0]; !errors.Is(err, vmerrors.ErrSenderAddressNotAllowListed) { t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err) } @@ -2173,7 +2170,7 @@ func TestTxAllowListSuccessfulTx(t *testing.T) { require.NoError(t, err) errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx2}) - require.ErrorIs(t, errs[0], vmerrs.ErrSenderAddressNotAllowListed) + require.ErrorIs(t, errs[0], vmerrors.ErrSenderAddressNotAllowListed) blk := issueAndAccept(t, issuer, vm) newHead := <-newTxPoolHeadChan @@ -2377,7 +2374,7 @@ func TestTxAllowListDisablePrecompile(t *testing.T) { } errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1}) - if err := errs[0]; !errors.Is(err, vmerrs.ErrSenderAddressNotAllowListed) { + if err := errs[0]; !errors.Is(err, vmerrors.ErrSenderAddressNotAllowListed) { t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err) } @@ -2597,7 +2594,7 @@ func TestAllowFeeRecipientDisabled(t *testing.T) { modifiedBlk := vm.newBlock(modifiedBlock) - require.ErrorIs(t, modifiedBlk.Verify(context.Background()), vmerrs.ErrInvalidCoinbase) + require.ErrorIs(t, modifiedBlk.Verify(context.Background()), vmerrors.ErrInvalidCoinbase) } func TestAllowFeeRecipientEnabled(t *testing.T) { @@ -2950,10 +2947,7 @@ func TestSkipChainConfigCheckCompatible(t *testing.T) { newTxPoolHeadChan := make(chan core.NewTxPoolReorgEvent, 1) vm.txPool.SubscribeNewReorgEvent(newTxPoolHeadChan) - key, err := utils.NewKey(rand.Reader) - if err != nil { - t.Fatal(err) - } + key := utils.NewKey(t) tx := types.NewTransaction(uint64(0), key.Address, firstTxAmount, 21000, big.NewInt(testMinGasPrice), nil) signedTx, err := types.SignTx(tx, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0]) diff --git a/plugin/evm/vm_upgrade_bytes_test.go b/plugin/evm/vm_upgrade_bytes_test.go index 22e529f21a..9b504805de 100644 --- a/plugin/evm/vm_upgrade_bytes_test.go +++ b/plugin/evm/vm_upgrade_bytes_test.go @@ -21,13 +21,13 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params/extras" + "github.com/ava-labs/subnet-evm/plugin/evm/vmerrors" "github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist" "github.com/ava-labs/subnet-evm/utils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/holiman/uint256" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -71,7 +71,7 @@ func TestVMUpgradeBytesPrecompile(t *testing.T) { t.Fatal(err) } errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1}) - if err := errs[0]; !errors.Is(err, vmerrs.ErrSenderAddressNotAllowListed) { + if err := errs[0]; !errors.Is(err, vmerrors.ErrSenderAddressNotAllowListed) { t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err) } @@ -128,7 +128,7 @@ func TestVMUpgradeBytesPrecompile(t *testing.T) { // Submit a rejected transaction, should throw an error errs = vm.txPool.AddRemotesSync([]*types.Transaction{signedTx1}) - if err := errs[0]; !errors.Is(err, vmerrs.ErrSenderAddressNotAllowListed) { + if err := errs[0]; !errors.Is(err, vmerrors.ErrSenderAddressNotAllowListed) { t.Fatalf("expected ErrSenderAddressNotAllowListed, got: %s", err) } diff --git a/plugin/evm/vm_warp_test.go b/plugin/evm/vm_warp_test.go index bdf4ad03b4..b3499cf004 100644 --- a/plugin/evm/vm_warp_test.go +++ b/plugin/evm/vm_warp_test.go @@ -28,10 +28,10 @@ import ( avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/eth/tracers" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/params/extras" @@ -676,7 +676,6 @@ func testReceiveWarpMessage( // Require the block was built with a successful predicate result ethBlock := block2.(*chain.BlockWrapper).Block.(*Block).ethBlock headerPredicateResultsBytes := customheader.PredicateBytesFromExtra(ethBlock.Extra()) - require.NotEmpty(headerPredicateResultsBytes) results, err := predicate.ParseResults(headerPredicateResultsBytes) require.NoError(err) diff --git a/plugin/evm/vmerrors/errors.go b/plugin/evm/vmerrors/errors.go new file mode 100644 index 0000000000..3d33159741 --- /dev/null +++ b/plugin/evm/vmerrors/errors.go @@ -0,0 +1,11 @@ +// (c) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package vmerrors + +import "errors" + +var ( + ErrInvalidCoinbase = errors.New("invalid coinbase") + ErrSenderAddressNotAllowListed = errors.New("cannot issue transaction from non-allow listed address") +) diff --git a/precompile/allowlist/allowlist.go b/precompile/allowlist/allowlist.go index 81fc965ff0..e443f4a204 100644 --- a/precompile/allowlist/allowlist.go +++ b/precompile/allowlist/allowlist.go @@ -10,8 +10,9 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" ) // AllowList is an abstraction that allows other precompiles to manage @@ -97,7 +98,7 @@ func createAllowListRoleSetter(precompileAddr common.Address, role Role) contrac } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } stateDB := evm.GetStateDB() @@ -117,7 +118,7 @@ func createAllowListRoleSetter(precompileAddr common.Address, role Role) contrac if err != nil { return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: precompileAddr, Topics: topics, Data: data, diff --git a/precompile/allowlist/test_allowlist.go b/precompile/allowlist/test_allowlist.go index 21d3951165..86cde28b7d 100644 --- a/precompile/allowlist/test_allowlist.go +++ b/precompile/allowlist/test_allowlist.go @@ -7,11 +7,11 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/modules" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) @@ -473,7 +473,7 @@ func AllowListTests(t testing.TB, module modules.Module) map[string]testutils.Pr }, SuppliedGas: ModifyAllowListGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "admin set no role insufficient gas": { Caller: TestAdminAddr, @@ -486,7 +486,7 @@ func AllowListTests(t testing.TB, module modules.Module) map[string]testutils.Pr }, SuppliedGas: ModifyAllowListGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "no role read allow list": { Caller: TestNoRoleAddr, @@ -535,7 +535,7 @@ func AllowListTests(t testing.TB, module modules.Module) map[string]testutils.Pr return input }, SuppliedGas: ReadAllowListGasCost - 1, ReadOnly: true, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "initial config sets admins": { Config: mkConfigWithAllowList( diff --git a/precompile/contract/interfaces.go b/precompile/contract/interfaces.go index a4174fb5a4..6892b7961a 100644 --- a/precompile/contract/interfaces.go +++ b/precompile/contract/interfaces.go @@ -14,8 +14,6 @@ import ( "github.com/holiman/uint256" ) -type Log = ethtypes.Log - // StatefulPrecompiledContract is the interface for executing a precompiled contract type StatefulPrecompiledContract interface { // Run executes the precompiled contract. @@ -40,7 +38,7 @@ type StateDB interface { CreateAccount(common.Address) Exist(common.Address) bool - AddLog(*Log) + AddLog(*ethtypes.Log) GetLogData() (topics [][]common.Hash, data [][]byte) GetPredicateStorageSlots(address common.Address, index int) ([]byte, bool) SetPredicateStorageSlots(address common.Address, predicates [][]byte) diff --git a/precompile/contract/mocks.go b/precompile/contract/mocks.go index c911743118..eb8d371e75 100644 --- a/precompile/contract/mocks.go +++ b/precompile/contract/mocks.go @@ -15,6 +15,7 @@ import ( snow "github.com/ava-labs/avalanchego/snow" common "github.com/ava-labs/libevm/common" + types "github.com/ava-labs/libevm/core/types" precompileconfig "github.com/ava-labs/subnet-evm/precompile/precompileconfig" uint256 "github.com/holiman/uint256" gomock "go.uber.org/mock/gomock" @@ -203,7 +204,7 @@ func (mr *MockStateDBMockRecorder) AddBalance(arg0, arg1 any) *gomock.Call { } // AddLog mocks base method. -func (m *MockStateDB) AddLog(arg0 *Log) { +func (m *MockStateDB) AddLog(arg0 *types.Log) { m.ctrl.T.Helper() m.ctrl.Call(m, "AddLog", arg0) } diff --git a/precompile/contract/utils.go b/precompile/contract/utils.go index 5a8fb39c40..bb87635f7e 100644 --- a/precompile/contract/utils.go +++ b/precompile/contract/utils.go @@ -8,9 +8,9 @@ import ( "regexp" "strings" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/subnet-evm/accounts/abi" - "github.com/ava-labs/subnet-evm/vmerrs" ) // Gas costs for stateful precompiles @@ -43,7 +43,7 @@ func CalculateFunctionSelector(functionSignature string) []byte { // DeductGas checks if [suppliedGas] is sufficient against [requiredGas] and deducts [requiredGas] from [suppliedGas]. func DeductGas(suppliedGas uint64, requiredGas uint64) (uint64, error) { if suppliedGas < requiredGas { - return 0, vmerrs.ErrOutOfGas + return 0, vm.ErrOutOfGas } return suppliedGas - requiredGas, nil } diff --git a/precompile/contracts/feemanager/contract.go b/precompile/contracts/feemanager/contract.go index ac46e568ef..9d1d73d542 100644 --- a/precompile/contracts/feemanager/contract.go +++ b/precompile/contracts/feemanager/contract.go @@ -10,11 +10,12 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" ) const ( @@ -210,7 +211,7 @@ func setFeeConfig(accessibleState contract.AccessibleState, caller common.Addres } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } // do not use strict mode after Durango @@ -241,7 +242,7 @@ func setFeeConfig(accessibleState contract.AccessibleState, caller common.Addres return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, diff --git a/precompile/contracts/feemanager/contract_test.go b/precompile/contracts/feemanager/contract_test.go index 01382383be..815cbba077 100644 --- a/precompile/contracts/feemanager/contract_test.go +++ b/precompile/contracts/feemanager/contract_test.go @@ -8,13 +8,13 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/core/extstate" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) @@ -260,7 +260,7 @@ var ( }, SuppliedGas: SetFeeConfigGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "readOnly setFeeConfig with allow role fails": { Caller: allowlist.TestEnabledAddr, @@ -273,7 +273,7 @@ var ( }, SuppliedGas: SetFeeConfigGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "readOnly setFeeConfig with admin role fails": { Caller: allowlist.TestAdminAddr, @@ -286,7 +286,7 @@ var ( }, SuppliedGas: SetFeeConfigGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "insufficient gas setFeeConfig from admin": { Caller: allowlist.TestAdminAddr, @@ -299,7 +299,7 @@ var ( }, SuppliedGas: SetFeeConfigGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "set config with extra padded bytes should fail before Durango": { Caller: allowlist.TestEnabledAddr, diff --git a/precompile/contracts/nativeminter/contract.go b/precompile/contracts/nativeminter/contract.go index b11c384f82..3be488f367 100644 --- a/precompile/contracts/nativeminter/contract.go +++ b/precompile/contracts/nativeminter/contract.go @@ -10,9 +10,10 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/holiman/uint256" ) @@ -82,7 +83,7 @@ func mintNativeCoin(accessibleState contract.AccessibleState, caller common.Addr } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } useStrictMode := !contract.IsDurangoActivated(accessibleState) @@ -106,7 +107,7 @@ func mintNativeCoin(accessibleState contract.AccessibleState, caller common.Addr if err != nil { return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, diff --git a/precompile/contracts/nativeminter/contract_test.go b/precompile/contracts/nativeminter/contract_test.go index d06cce76ec..c6498155db 100644 --- a/precompile/contracts/nativeminter/contract_test.go +++ b/precompile/contracts/nativeminter/contract_test.go @@ -9,12 +9,12 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/core/extstate" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/holiman/uint256" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -139,7 +139,7 @@ var ( }, SuppliedGas: MintGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "readOnly mint with allow role fails": { Caller: allowlist.TestEnabledAddr, @@ -152,7 +152,7 @@ var ( }, SuppliedGas: MintGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "readOnly mint with admin role fails": { Caller: allowlist.TestAdminAddr, @@ -165,7 +165,7 @@ var ( }, SuppliedGas: MintGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "insufficient gas mint from admin": { Caller: allowlist.TestAdminAddr, @@ -178,7 +178,7 @@ var ( }, SuppliedGas: MintGasCost + NativeCoinMintedEventGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "mint doesn't log pre-Durango": { Caller: allowlist.TestEnabledAddr, diff --git a/precompile/contracts/rewardmanager/contract.go b/precompile/contracts/rewardmanager/contract.go index 4296120197..6af586f0d7 100644 --- a/precompile/contracts/rewardmanager/contract.go +++ b/precompile/contracts/rewardmanager/contract.go @@ -11,13 +11,14 @@ import ( "errors" "fmt" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/constants" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" ) const ( @@ -82,7 +83,7 @@ func allowFeeRecipients(accessibleState contract.AccessibleState, caller common. return nil, 0, err } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } // no input provided for this function @@ -105,7 +106,7 @@ func allowFeeRecipients(accessibleState contract.AccessibleState, caller common. if err != nil { return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, @@ -196,7 +197,7 @@ func setRewardAddress(accessibleState contract.AccessibleState, caller common.Ad return nil, 0, err } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } // attempts to unpack [input] into the arguments to the SetRewardAddressInput. // Assumes that [input] does not include selector @@ -233,7 +234,7 @@ func setRewardAddress(accessibleState contract.AccessibleState, caller common.Ad if err != nil { return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, @@ -273,7 +274,7 @@ func disableRewards(accessibleState contract.AccessibleState, caller common.Addr return nil, 0, err } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } // no input provided for this function @@ -296,7 +297,7 @@ func disableRewards(accessibleState contract.AccessibleState, caller common.Addr if err != nil { return nil, remainingGas, err } - stateDB.AddLog(&contract.Log{ + stateDB.AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, diff --git a/precompile/contracts/rewardmanager/contract_test.go b/precompile/contracts/rewardmanager/contract_test.go index b34e5076ff..1c79ff96d3 100644 --- a/precompile/contracts/rewardmanager/contract_test.go +++ b/precompile/contracts/rewardmanager/contract_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -17,7 +18,6 @@ import ( "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" - "github.com/ava-labs/subnet-evm/vmerrs" ) var ( @@ -364,7 +364,7 @@ var ( }, SuppliedGas: AllowFeeRecipientsGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "readOnly set reward address with allowed role fails": { Caller: allowlist.TestEnabledAddr, @@ -377,7 +377,7 @@ var ( }, SuppliedGas: SetRewardAddressGasCost, ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "insufficient gas set reward address from allowed role": { Caller: allowlist.TestEnabledAddr, @@ -390,7 +390,7 @@ var ( }, SuppliedGas: SetRewardAddressGasCost + RewardAddressChangedEventGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "insufficient gas allow fee recipients from allowed role": { Caller: allowlist.TestEnabledAddr, @@ -403,7 +403,7 @@ var ( }, SuppliedGas: AllowFeeRecipientsGasCost + FeeRecipientsAllowedEventGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "insufficient gas read current reward address from allowed role": { Caller: allowlist.TestEnabledAddr, @@ -416,7 +416,7 @@ var ( }, SuppliedGas: CurrentRewardAddressGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "insufficient gas are fee recipients allowed from allowed role": { Caller: allowlist.TestEnabledAddr, @@ -429,7 +429,7 @@ var ( }, SuppliedGas: AreFeeRecipientsAllowedGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, } ) diff --git a/precompile/contracts/warp/config.go b/precompile/contracts/warp/config.go index b4a87e5fe8..fff3adfecf 100644 --- a/precompile/contracts/warp/config.go +++ b/precompile/contracts/warp/config.go @@ -84,7 +84,7 @@ func NewDisableConfig(blockTimestamp *uint64) *Config { func (*Config) Key() string { return ConfigKey } // Verify tries to verify Config and returns an error accordingly. -func (c Config) Verify(chainConfig precompileconfig.ChainConfig) error { +func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { if c.Timestamp() != nil { // If Warp attempts to activate before Durango, fail verification timestamp := *c.Timestamp() diff --git a/precompile/contracts/warp/contract.go b/precompile/contracts/warp/contract.go index bf1236b8a4..4b2ea4877f 100644 --- a/precompile/contracts/warp/contract.go +++ b/precompile/contracts/warp/contract.go @@ -4,19 +4,18 @@ package warp import ( + _ "embed" "errors" "fmt" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" - "github.com/ava-labs/subnet-evm/accounts/abi" - "github.com/ava-labs/subnet-evm/precompile/contract" - "github.com/ava-labs/subnet-evm/vmerrs" - - _ "embed" - "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/core/vm" + "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/precompile/contract" ) const ( @@ -236,13 +235,13 @@ func sendWarpMessage(accessibleState contract.AccessibleState, caller common.Add // This ensures that we charge gas before we unpack the variable sized input. payloadGas, overflow := math.SafeMul(SendWarpMessageGasCostPerByte, uint64(len(input))) if overflow { - return nil, 0, vmerrs.ErrOutOfGas + return nil, 0, vm.ErrOutOfGas } if remainingGas, err = contract.DeductGas(remainingGas, payloadGas); err != nil { return nil, 0, err } if readOnly { - return nil, remainingGas, vmerrs.ErrWriteProtection + return nil, remainingGas, vm.ErrWriteProtection } // unpack the arguments payloadData, err := UnpackSendWarpMessageInput(input) @@ -280,7 +279,7 @@ func sendWarpMessage(accessibleState contract.AccessibleState, caller common.Add if err != nil { return nil, remainingGas, err } - accessibleState.GetStateDB().AddLog(&contract.Log{ + accessibleState.GetStateDB().AddLog(&types.Log{ Address: ContractAddress, Topics: topics, Data: data, diff --git a/precompile/contracts/warp/contract_test.go b/precompile/contracts/warp/contract_test.go index 27e2cb6ec2..300ced1e13 100644 --- a/precompile/contracts/warp/contract_test.go +++ b/precompile/contracts/warp/contract_test.go @@ -14,12 +14,12 @@ import ( avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/core/extstate" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ava-labs/subnet-evm/predicate" "github.com/ava-labs/subnet-evm/utils" - "github.com/ava-labs/subnet-evm/vmerrs" "github.com/stretchr/testify/require" ) @@ -74,7 +74,7 @@ func TestGetBlockchainID(t *testing.T) { }, SuppliedGas: GetBlockchainIDGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, } @@ -108,21 +108,21 @@ func TestSendWarpMessage(t *testing.T) { InputFn: func(t testing.TB) []byte { return sendWarpMessageInput }, SuppliedGas: SendWarpMessageGasCost + uint64(len(sendWarpMessageInput[4:])*int(SendWarpMessageGasCostPerByte)), ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + ExpectedErr: vm.ErrWriteProtection.Error(), }, "send warp message insufficient gas for first step": { Caller: callerAddr, InputFn: func(t testing.TB) []byte { return sendWarpMessageInput }, SuppliedGas: SendWarpMessageGasCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "send warp message insufficient gas for payload bytes": { Caller: callerAddr, InputFn: func(t testing.TB) []byte { return sendWarpMessageInput }, SuppliedGas: SendWarpMessageGasCost + uint64(len(sendWarpMessageInput[4:])*int(SendWarpMessageGasCostPerByte)) - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "send warp message invalid input": { Caller: callerAddr, @@ -361,7 +361,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) { }, SuppliedGas: GetVerifiedWarpMessageBaseCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "get message out of gas": { Caller: callerAddr, @@ -374,7 +374,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) { }, SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)) - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "get message invalid predicate packing": { Caller: callerAddr, @@ -639,7 +639,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) { }, SuppliedGas: GetVerifiedWarpMessageBaseCost - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "get message out of gas": { Caller: callerAddr, @@ -652,7 +652,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) { }, SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)) - 1, ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + ExpectedErr: vm.ErrOutOfGas.Error(), }, "get message invalid predicate packing": { Caller: callerAddr, diff --git a/precompile/contracts/warp/contract_warp_handler.go b/precompile/contracts/warp/contract_warp_handler.go index 8b03f03c7c..b13b0c8cc1 100644 --- a/precompile/contracts/warp/contract_warp_handler.go +++ b/precompile/contracts/warp/contract_warp_handler.go @@ -11,9 +11,9 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/predicate" - "github.com/ava-labs/subnet-evm/vmerrs" ) var ( @@ -61,8 +61,8 @@ func handleWarpMessage(accessibleState contract.AccessibleState, input []byte, s warpIndex := int(warpIndexInput) // This conversion is safe even if int is 32 bits because we checked above. state := accessibleState.GetStateDB() predicateBytes, exists := state.GetPredicateStorageSlots(ContractAddress, warpIndex) - result := accessibleState.GetBlockContext().GetPredicateResults(state.GetTxHash(), ContractAddress) - valid := exists && !set.BitsFromBytes(result).Contains(warpIndex) + predicateResults := accessibleState.GetBlockContext().GetPredicateResults(state.GetTxHash(), ContractAddress) + valid := exists && !set.BitsFromBytes(predicateResults).Contains(warpIndex) if !valid { return handler.packFailed(), remainingGas, nil } @@ -71,7 +71,7 @@ func handleWarpMessage(accessibleState contract.AccessibleState, input []byte, s // EVM execution because each execution incurs an additional read cost. msgBytesGas, overflow := math.SafeMul(GasCostPerWarpMessageBytes, uint64(len(predicateBytes))) if overflow { - return nil, 0, vmerrs.ErrOutOfGas + return nil, 0, vm.ErrOutOfGas } if remainingGas, err = contract.DeductGas(remainingGas, msgBytesGas); err != nil { return nil, 0, err diff --git a/predicate/predicate_bytes.go b/predicate/predicate_bytes.go index 08332583b6..9d5766b4f3 100644 --- a/predicate/predicate_bytes.go +++ b/predicate/predicate_bytes.go @@ -9,10 +9,6 @@ import ( "github.com/ava-labs/libevm/common" ) -// DynamicFeeExtraDataSize is defined in the predicate package to avoid a circular dependency. -// After Durango, the extra data past the dynamic fee rollup window represents predicate results. -const DynamicFeeExtraDataSize = 80 - // EndByte is used as a delimiter for the bytes packed into a precompile predicate. // Precompile predicates are encoded in the Access List of transactions in the access tuples // which means that its length must be a multiple of 32 (common.HashLength). diff --git a/predicate/predicate_results.go b/predicate/predicate_results.go index a79417329c..2d8eeea5ca 100644 --- a/predicate/predicate_results.go +++ b/predicate/predicate_results.go @@ -45,11 +45,11 @@ type Results struct { } func (r Results) GetPredicateResults(txHash common.Hash, address common.Address) []byte { - tx, ok := r.Results[txHash] + results, ok := r.Results[txHash] if !ok { return nil } - return tx[address] + return results[address] } // NewResults returns an empty predicate results. diff --git a/predicate/predicate_slots.go b/predicate/predicate_slots.go index 722a787353..e13e401da6 100644 --- a/predicate/predicate_slots.go +++ b/predicate/predicate_slots.go @@ -5,11 +5,11 @@ package predicate import ( "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/utils" ) -type predicaters interface { +type PredicaterExistChecker interface { PredicaterExists(common.Address) bool } @@ -17,7 +17,7 @@ type predicaters interface { // Note: if an address is specified multiple times in the access list, each storage slot for that address is // appended to a slice of byte slices. Each byte slice represents a predicate, making it a slice of predicates // for each access list address, and every predicate in the slice goes through verification. -func PreparePredicateStorageSlots(rules predicaters, list types.AccessList) map[common.Address][][]byte { +func PreparePredicateStorageSlots(rules PredicaterExistChecker, list types.AccessList) map[common.Address][][]byte { predicateStorageSlots := make(map[common.Address][][]byte) for _, el := range list { if !rules.PredicaterExists(el.Address) { diff --git a/predicate/predicate_tx.go b/predicate/predicate_tx.go index b5c00787df..73d48a6956 100644 --- a/predicate/predicate_tx.go +++ b/predicate/predicate_tx.go @@ -7,7 +7,7 @@ import ( "math/big" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/utils" ) diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go index 3a90a5a238..125a1472c4 100644 --- a/rpc/subscription_test.go +++ b/rpc/subscription_test.go @@ -39,7 +39,10 @@ import ( "time" "github.com/ava-labs/libevm/common" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" + + // Side effect: registration of libevm extras. + _ "github.com/ava-labs/subnet-evm/plugin/evm/customtypes" ) func TestNewID(t *testing.T) { diff --git a/scripts/eth-allowed-packages.txt b/scripts/eth-allowed-packages.txt index 98fb94b34c..e8d62708db 100644 --- a/scripts/eth-allowed-packages.txt +++ b/scripts/eth-allowed-packages.txt @@ -10,6 +10,8 @@ "github.com/ava-labs/libevm/common/math" "github.com/ava-labs/libevm/common/prque" "github.com/ava-labs/libevm/core/asm" +"github.com/ava-labs/libevm/core/rawdb" +"github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/crypto/blake2b" @@ -29,7 +31,6 @@ "github.com/ava-labs/libevm/libevm/stateconf" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" -"github.com/ava-labs/libevm/params" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/trie/testutil" diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index c2215fc407..325f5f72a5 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -34,7 +34,7 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/libevm/core/types" ) type ValidationInfo struct { diff --git a/sync/client/client.go b/sync/client/client.go index 5e46430a5f..85a6927445 100644 --- a/sync/client/client.go +++ b/sync/client/client.go @@ -23,10 +23,10 @@ import ( "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/peer" "github.com/ava-labs/subnet-evm/plugin/evm/message" ) diff --git a/sync/client/client_test.go b/sync/client/client_test.go index ef04df144b..08e59a865c 100644 --- a/sync/client/client_test.go +++ b/sync/client/client_test.go @@ -16,12 +16,12 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/message" clientstats "github.com/ava-labs/subnet-evm/sync/client/stats" @@ -266,7 +266,7 @@ func TestGetBlocks(t *testing.T) { return responseBytes }, - expectedErr: "failed to unmarshal response: rlp: expected input list for types.extblock", + expectedErr: "failed to unmarshal response: rlp: expected List", }, "incorrect starting point": { request: message.BlockRequest{ @@ -381,7 +381,7 @@ func TestGetBlocks(t *testing.T) { if err == nil { t.Fatalf("Expected error: %s, but found no error", test.expectedErr) } - assert.True(t, strings.Contains(err.Error(), test.expectedErr), "expected error to contain [%s], but found [%s]", test.expectedErr, err) + assert.ErrorContains(t, err, test.expectedErr) return } if err != nil { diff --git a/sync/client/mock_client.go b/sync/client/mock_client.go index 8c0026e3d1..16d74d35ee 100644 --- a/sync/client/mock_client.go +++ b/sync/client/mock_client.go @@ -11,8 +11,8 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers" ) diff --git a/sync/handlers/block_request_test.go b/sync/handlers/block_request_test.go index cb581b9321..53012afd6a 100644 --- a/sync/handlers/block_request_test.go +++ b/sync/handlers/block_request_test.go @@ -11,13 +11,13 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers/stats" diff --git a/sync/handlers/code_request.go b/sync/handlers/code_request.go index 23f3c3f584..0f606ab9d6 100644 --- a/sync/handlers/code_request.go +++ b/sync/handlers/code_request.go @@ -11,9 +11,9 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers/stats" ) diff --git a/sync/handlers/code_request_test.go b/sync/handlers/code_request_test.go index ff94863be6..df6e336144 100644 --- a/sync/handlers/code_request_test.go +++ b/sync/handlers/code_request_test.go @@ -12,9 +12,9 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb/memorydb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers/stats" "github.com/stretchr/testify/assert" diff --git a/sync/handlers/handler.go b/sync/handlers/handler.go index bfaa7ac716..641121c9e3 100644 --- a/sync/handlers/handler.go +++ b/sync/handlers/handler.go @@ -5,8 +5,8 @@ package handlers import ( "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" ) type BlockProvider interface { diff --git a/sync/handlers/leafs_request.go b/sync/handlers/leafs_request.go index 8c6f3aff60..5246596911 100644 --- a/sync/handlers/leafs_request.go +++ b/sync/handlers/leafs_request.go @@ -12,13 +12,13 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/ethdb/memorydb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers/stats" "github.com/ava-labs/subnet-evm/sync/syncutils" diff --git a/sync/handlers/leafs_request_test.go b/sync/handlers/leafs_request_test.go index 8e22cefd49..692c667cef 100644 --- a/sync/handlers/leafs_request_test.go +++ b/sync/handlers/leafs_request_test.go @@ -11,13 +11,13 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/plugin/evm/message" "github.com/ava-labs/subnet-evm/sync/handlers/stats" "github.com/ava-labs/subnet-evm/sync/syncutils" diff --git a/sync/handlers/test_providers.go b/sync/handlers/test_providers.go index 4d78206ff6..6c418acc9d 100644 --- a/sync/handlers/test_providers.go +++ b/sync/handlers/test_providers.go @@ -5,8 +5,8 @@ package handlers import ( "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" ) var ( diff --git a/sync/statesync/code_syncer.go b/sync/statesync/code_syncer.go index 9f1dfc6cdf..e08a74bc20 100644 --- a/sync/statesync/code_syncer.go +++ b/sync/statesync/code_syncer.go @@ -12,8 +12,9 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/plugin/evm/message" statesyncclient "github.com/ava-labs/subnet-evm/sync/client" ) @@ -104,16 +105,16 @@ func (c *codeSyncer) start(ctx context.Context) { // Clean out any codeToFetch markers from the database that are no longer needed and // add any outstanding markers to the queue. func (c *codeSyncer) addCodeToFetchFromDBToQueue() error { - it := rawdb.NewCodeToFetchIterator(c.DB) + it := customrawdb.NewCodeToFetchIterator(c.DB) defer it.Release() batch := c.DB.NewBatch() codeHashes := make([]common.Hash, 0) for it.Next() { - codeHash := common.BytesToHash(it.Key()[len(rawdb.CodeToFetchPrefix):]) + codeHash := common.BytesToHash(it.Key()[len(customrawdb.CodeToFetchPrefix):]) // If we already have the codeHash, delete the marker from the database and continue if rawdb.HasCode(c.DB, codeHash) { - rawdb.DeleteCodeToFetch(batch, codeHash) + customrawdb.DeleteCodeToFetch(batch, codeHash) // Write the batch to disk if it has reached the ideal batch size. if batch.ValueSize() > ethdb.IdealBatchSize { if err := batch.Write(); err != nil { @@ -186,7 +187,7 @@ func (c *codeSyncer) fulfillCodeRequest(ctx context.Context, codeHashes []common c.lock.Lock() batch := c.DB.NewBatch() for i, codeHash := range codeHashes { - rawdb.DeleteCodeToFetch(batch, codeHash) + customrawdb.DeleteCodeToFetch(batch, codeHash) c.outstandingCodeHashes.Remove(ids.ID(codeHash)) rawdb.WriteCode(batch, codeHash, codeByteSlices[i]) } @@ -211,7 +212,7 @@ func (c *codeSyncer) addCode(codeHashes []common.Hash) error { if !c.outstandingCodeHashes.Contains(ids.ID(codeHash)) && !rawdb.HasCode(c.DB, codeHash) { selectedCodeHashes = append(selectedCodeHashes, codeHash) c.outstandingCodeHashes.Add(ids.ID(codeHash)) - rawdb.AddCodeToFetch(batch, codeHash) + customrawdb.AddCodeToFetch(batch, codeHash) } } c.lock.Unlock() diff --git a/sync/statesync/code_syncer_test.go b/sync/statesync/code_syncer_test.go index be23eb2b27..620a694a38 100644 --- a/sync/statesync/code_syncer_test.go +++ b/sync/statesync/code_syncer_test.go @@ -10,9 +10,10 @@ import ( "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb/memorydb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/plugin/evm/message" statesyncclient "github.com/ava-labs/subnet-evm/sync/client" "github.com/ava-labs/subnet-evm/sync/handlers" @@ -134,7 +135,7 @@ func TestCodeSyncerAddsInProgressCodeHashes(t *testing.T) { codeHash := crypto.Keccak256Hash(codeBytes) testCodeSyncer(t, codeSyncerTest{ setupCodeSyncer: func(c *codeSyncer) { - rawdb.AddCodeToFetch(c.DB, codeHash) + customrawdb.AddCodeToFetch(c.DB, codeHash) }, codeRequestHashes: nil, codeByteSlices: [][]byte{codeBytes}, @@ -155,7 +156,7 @@ func TestCodeSyncerAddsMoreInProgressThanQueueSize(t *testing.T) { testCodeSyncer(t, codeSyncerTest{ setupCodeSyncer: func(c *codeSyncer) { for _, codeHash := range codeHashes { - rawdb.AddCodeToFetch(c.DB, codeHash) + customrawdb.AddCodeToFetch(c.DB, codeHash) } c.codeHashes = make(chan common.Hash, numCodeSlices/2) }, diff --git a/sync/statesync/sync_helpers.go b/sync/statesync/sync_helpers.go index d285d90232..2d506cf17e 100644 --- a/sync/statesync/sync_helpers.go +++ b/sync/statesync/sync_helpers.go @@ -5,10 +5,10 @@ package statesync import ( "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) // writeAccountSnapshot stores the account represented by [acc] to the snapshot at [accHash], using diff --git a/sync/statesync/sync_test.go b/sync/statesync/sync_test.go index 33da3d82ea..38dbec5975 100644 --- a/sync/statesync/sync_test.go +++ b/sync/statesync/sync_test.go @@ -14,14 +14,14 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/plugin/evm/message" statesyncclient "github.com/ava-labs/subnet-evm/sync/client" "github.com/ava-labs/subnet-evm/sync/handlers" diff --git a/sync/statesync/test_sync.go b/sync/statesync/test_sync.go index 5c218d95d5..ed3bbf587c 100644 --- a/sync/statesync/test_sync.go +++ b/sync/statesync/test_sync.go @@ -9,12 +9,13 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" "github.com/ava-labs/subnet-evm/sync/syncutils" "github.com/ava-labs/subnet-evm/utils" "github.com/stretchr/testify/assert" @@ -25,7 +26,7 @@ import ( // Also verifies any code referenced by the EVM state is present in [clientTrieDB] and the hash is correct. func assertDBConsistency(t testing.TB, root common.Hash, clientDB ethdb.Database, serverTrieDB, clientTrieDB *triedb.Database) { numSnapshotAccounts := 0 - accountIt := rawdb.IterateAccountSnapshots(clientDB) + accountIt := customrawdb.IterateAccountSnapshots(clientDB) defer accountIt.Release() for accountIt.Next() { if !bytes.HasPrefix(accountIt.Key(), rawdb.SnapshotAccountPrefix) || len(accountIt.Key()) != len(rawdb.SnapshotAccountPrefix)+common.HashLength { diff --git a/sync/statesync/trie_queue.go b/sync/statesync/trie_queue.go index 905cbb8844..5ab4aaac7d 100644 --- a/sync/statesync/trie_queue.go +++ b/sync/statesync/trie_queue.go @@ -6,7 +6,7 @@ package statesync import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/ethdb" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" ) // trieQueue persists storage trie roots with their associated @@ -26,21 +26,21 @@ func NewTrieQueue(db ethdb.Database) *trieQueue { // clearIfRootDoesNotMatch clears progress and segment markers if // the persisted root does not match the root we are syncing to. func (t *trieQueue) clearIfRootDoesNotMatch(root common.Hash) error { - persistedRoot, err := rawdb.ReadSyncRoot(t.db) + persistedRoot, err := customrawdb.ReadSyncRoot(t.db) if err != nil { return err } if persistedRoot != (common.Hash{}) && persistedRoot != root { // if not resuming, clear all progress markers - if err := rawdb.ClearAllSyncStorageTries(t.db); err != nil { + if err := customrawdb.ClearAllSyncStorageTries(t.db); err != nil { return err } - if err := rawdb.ClearAllSyncSegments(t.db); err != nil { + if err := customrawdb.ClearAllSyncSegments(t.db); err != nil { return err } } - return rawdb.WriteSyncRoot(t.db, root) + return customrawdb.WriteSyncRoot(t.db, root) } // RegisterStorageTrie is called by the main trie's leaf handling callbacks @@ -48,13 +48,13 @@ func (t *trieQueue) clearIfRootDoesNotMatch(root common.Hash) error { // getNextTrie iterates this prefix to find storage tries and accounts // associated with them. func (t *trieQueue) RegisterStorageTrie(root common.Hash, account common.Hash) error { - return rawdb.WriteSyncStorageTrie(t.db, root, account) + return customrawdb.WriteSyncStorageTrie(t.db, root, account) } // StorageTrieDone is called when a storage trie has completed syncing. // This removes any progress markers for the trie. func (t *trieQueue) StorageTrieDone(root common.Hash) error { - return rawdb.ClearSyncStorageTrie(t.db, root) + return customrawdb.ClearSyncStorageTrie(t.db, root) } // getNextTrie returns the next storage trie to sync, along with a slice @@ -63,7 +63,7 @@ func (t *trieQueue) StorageTrieDone(root common.Hash) error { // Note: if a non-nil root is returned, getNextTrie guarantees that there will be at least // one account hash in the returned slice. func (t *trieQueue) getNextTrie() (common.Hash, []common.Hash, bool, error) { - it := rawdb.NewSyncStorageTriesIterator(t.db, t.nextStorageRoot) + it := customrawdb.NewSyncStorageTriesIterator(t.db, t.nextStorageRoot) defer it.Release() var ( @@ -75,7 +75,7 @@ func (t *trieQueue) getNextTrie() (common.Hash, []common.Hash, bool, error) { // Iterate over the keys to find the next storage trie root and all of the account hashes that contain the same storage root. for it.Next() { // Unpack the state root and account hash from the current key - nextRoot, nextAccount := rawdb.UnpackSyncStorageTrieKey(it.Key()) + nextRoot, nextAccount := customrawdb.UnpackSyncStorageTrieKey(it.Key()) // Set the root for the first pass if root == (common.Hash{}) { root = nextRoot @@ -95,7 +95,7 @@ func (t *trieQueue) getNextTrie() (common.Hash, []common.Hash, bool, error) { } func (t *trieQueue) countTries() (int, error) { - it := rawdb.NewSyncStorageTriesIterator(t.db, nil) + it := customrawdb.NewSyncStorageTriesIterator(t.db, nil) defer it.Release() var ( @@ -104,7 +104,7 @@ func (t *trieQueue) countTries() (int, error) { ) for it.Next() { - nextRoot, _ := rawdb.UnpackSyncStorageTrieKey(it.Key()) + nextRoot, _ := customrawdb.UnpackSyncStorageTrieKey(it.Key()) if root == (common.Hash{}) || root != nextRoot { root = nextRoot tries++ diff --git a/sync/statesync/trie_segments.go b/sync/statesync/trie_segments.go index 4a524dc9fd..cbeb5744ca 100644 --- a/sync/statesync/trie_segments.go +++ b/sync/statesync/trie_segments.go @@ -12,10 +12,11 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" + "github.com/ava-labs/subnet-evm/plugin/evm/customrawdb" syncclient "github.com/ava-labs/subnet-evm/sync/client" "github.com/ava-labs/subnet-evm/utils" ) @@ -85,7 +86,7 @@ func (t *trieToSync) loadSegments() error { // Get an iterator for segments for t.root and see if we find anything. // This lets us check if this trie was previously segmented, in which // case we need to restore the same segments on resume. - it := rawdb.NewSyncSegmentsIterator(t.sync.db, t.root) + it := customrawdb.NewSyncSegmentsIterator(t.sync.db, t.root) defer it.Release() // Track the previously added segment as we loop over persisted values. @@ -98,7 +99,7 @@ func (t *trieToSync) loadSegments() error { // key immediately prior to the segment we found on disk. // This is because we do not persist the beginning of // the first segment. - _, segmentStart := rawdb.UnpackSyncSegmentKey(it.Key()) + _, segmentStart := customrawdb.UnpackSyncSegmentKey(it.Key()) segmentStartPos := binary.BigEndian.Uint16(segmentStart[:wrappers.ShortLen]) t.addSegment(prevSegmentStart, addPadding(segmentStartPos-1, 0xff)) @@ -231,7 +232,7 @@ func (t *trieToSync) segmentFinished(ctx context.Context, idx int) error { } // remove all segments for this root from persistent storage - if err := rawdb.ClearSyncSegments(t.sync.db, t.root); err != nil { + if err := customrawdb.ClearSyncSegments(t.sync.db, t.root); err != nil { return err } return t.task.OnFinish() @@ -300,7 +301,7 @@ func (t *trieToSync) createSegments(numSegments int) error { // create the segments segment := t.addSegment(startBytes, endBytes) - if err := rawdb.WriteSyncSegment(t.sync.db, t.root, segment.start); err != nil { + if err := customrawdb.WriteSyncSegment(t.sync.db, t.root, common.BytesToHash(segment.start)); err != nil { return err } } diff --git a/sync/statesync/trie_sync_tasks.go b/sync/statesync/trie_sync_tasks.go index 5d925f523d..e5d47a7f45 100644 --- a/sync/statesync/trie_sync_tasks.go +++ b/sync/statesync/trie_sync_tasks.go @@ -7,12 +7,12 @@ import ( "fmt" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/sync/syncutils" ) diff --git a/sync/syncutils/iterators.go b/sync/syncutils/iterators.go index a30564eed8..c634f742ea 100644 --- a/sync/syncutils/iterators.go +++ b/sync/syncutils/iterators.go @@ -4,9 +4,9 @@ package syncutils import ( + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" ) var ( diff --git a/sync/syncutils/test_trie.go b/sync/syncutils/test_trie.go index 7662d4acf3..0dbb027e58 100644 --- a/sync/syncutils/test_trie.go +++ b/sync/syncutils/test_trie.go @@ -4,16 +4,15 @@ package syncutils import ( - cryptoRand "crypto/rand" "encoding/binary" "math/rand" "testing" "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/triedb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/utils" "github.com/holiman/uint256" @@ -176,10 +175,7 @@ func FillAccounts( t.Fatalf("failed to rlp encode account: %v", err) } - key, err := utils.NewKey(cryptoRand.Reader) - if err != nil { - t.Fatal(err) - } + key := utils.NewKey(t) tr.MustUpdate(key.Address[:], accBytes) accounts[key] = &acc } diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go index 4a93a1c3db..b6f68c21a6 100644 --- a/tests/antithesis/main.go +++ b/tests/antithesis/main.go @@ -24,8 +24,8 @@ import ( "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/tests" diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go new file mode 100644 index 0000000000..7a98bd6476 --- /dev/null +++ b/tests/gen_sttransaction.go @@ -0,0 +1,120 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package tests + +import ( + "encoding/json" + "math/big" + + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/common/hexutil" + "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/types" +) + +var _ = (*stTransactionMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (s stTransaction) MarshalJSON() ([]byte, error) { + type stTransaction struct { + GasPrice *math.HexOrDecimal256 `json:"gasPrice"` + MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` + MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + Nonce math.HexOrDecimal64 `json:"nonce"` + To string `json:"to"` + Data []string `json:"data"` + AccessLists []*types.AccessList `json:"accessLists,omitempty"` + GasLimit []math.HexOrDecimal64 `json:"gasLimit"` + Value []string `json:"value"` + PrivateKey hexutil.Bytes `json:"secretKey"` + Sender *common.Address `json:"sender"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"` + } + var enc stTransaction + enc.GasPrice = (*math.HexOrDecimal256)(s.GasPrice) + enc.MaxFeePerGas = (*math.HexOrDecimal256)(s.MaxFeePerGas) + enc.MaxPriorityFeePerGas = (*math.HexOrDecimal256)(s.MaxPriorityFeePerGas) + enc.Nonce = math.HexOrDecimal64(s.Nonce) + enc.To = s.To + enc.Data = s.Data + enc.AccessLists = s.AccessLists + if s.GasLimit != nil { + enc.GasLimit = make([]math.HexOrDecimal64, len(s.GasLimit)) + for k, v := range s.GasLimit { + enc.GasLimit[k] = math.HexOrDecimal64(v) + } + } + enc.Value = s.Value + enc.PrivateKey = s.PrivateKey + enc.Sender = s.Sender + enc.BlobVersionedHashes = s.BlobVersionedHashes + enc.BlobGasFeeCap = (*math.HexOrDecimal256)(s.BlobGasFeeCap) + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (s *stTransaction) UnmarshalJSON(input []byte) error { + type stTransaction struct { + GasPrice *math.HexOrDecimal256 `json:"gasPrice"` + MaxFeePerGas *math.HexOrDecimal256 `json:"maxFeePerGas"` + MaxPriorityFeePerGas *math.HexOrDecimal256 `json:"maxPriorityFeePerGas"` + Nonce *math.HexOrDecimal64 `json:"nonce"` + To *string `json:"to"` + Data []string `json:"data"` + AccessLists []*types.AccessList `json:"accessLists,omitempty"` + GasLimit []math.HexOrDecimal64 `json:"gasLimit"` + Value []string `json:"value"` + PrivateKey *hexutil.Bytes `json:"secretKey"` + Sender *common.Address `json:"sender"` + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"` + } + var dec stTransaction + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.GasPrice != nil { + s.GasPrice = (*big.Int)(dec.GasPrice) + } + if dec.MaxFeePerGas != nil { + s.MaxFeePerGas = (*big.Int)(dec.MaxFeePerGas) + } + if dec.MaxPriorityFeePerGas != nil { + s.MaxPriorityFeePerGas = (*big.Int)(dec.MaxPriorityFeePerGas) + } + if dec.Nonce != nil { + s.Nonce = uint64(*dec.Nonce) + } + if dec.To != nil { + s.To = *dec.To + } + if dec.Data != nil { + s.Data = dec.Data + } + if dec.AccessLists != nil { + s.AccessLists = dec.AccessLists + } + if dec.GasLimit != nil { + s.GasLimit = make([]uint64, len(dec.GasLimit)) + for k, v := range dec.GasLimit { + s.GasLimit[k] = uint64(v) + } + } + if dec.Value != nil { + s.Value = dec.Value + } + if dec.PrivateKey != nil { + s.PrivateKey = *dec.PrivateKey + } + if dec.Sender != nil { + s.Sender = dec.Sender + } + if dec.BlobVersionedHashes != nil { + s.BlobVersionedHashes = dec.BlobVersionedHashes + } + if dec.BlobGasFeeCap != nil { + s.BlobGasFeeCap = (*big.Int)(dec.BlobGasFeeCap) + } + return nil +} diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 9d70f10da4..f143bc7352 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -38,6 +38,8 @@ import ( "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/common/hexutil" "github.com/ava-labs/libevm/common/math" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/core/vm" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" @@ -45,10 +47,8 @@ import ( "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/subnet-evm/consensus/misc/eip4844" "github.com/ava-labs/subnet-evm/core" - "github.com/ava-labs/subnet-evm/core/rawdb" "github.com/ava-labs/subnet-evm/core/state" "github.com/ava-labs/subnet-evm/core/state/snapshot" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/triedb/hashdb" "github.com/ava-labs/subnet-evm/triedb/pathdb" diff --git a/tests/utils/proposervm.go b/tests/utils/proposervm.go index d3fcaf6ab2..d6888f018b 100644 --- a/tests/utils/proposervm.go +++ b/tests/utils/proposervm.go @@ -9,9 +9,9 @@ import ( "math/big" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/plugin/evm/upgrade/legacy" diff --git a/tests/warp/warp_test.go b/tests/warp/warp_test.go index 09d10e8d08..8741b548f1 100644 --- a/tests/warp/warp_test.go +++ b/tests/warp/warp_test.go @@ -35,13 +35,13 @@ import ( avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + ethereum "github.com/ava-labs/libevm" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/subnet-evm/cmd/simulator/key" "github.com/ava-labs/subnet-evm/cmd/simulator/load" "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" - "github.com/ava-labs/subnet-evm/interfaces" "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contracts/warp" "github.com/ava-labs/subnet-evm/predicate" @@ -345,7 +345,7 @@ func (w *warpTest) sendMessageFromSendingSubnet() { require.NoError(err) log.Info("Fetching relevant warp logs from the newly produced block") - logs, err := client.FilterLogs(ctx, interfaces.FilterQuery{ + logs, err := client.FilterLogs(ctx, ethereum.FilterQuery{ BlockHash: &blockHash, Addresses: []common.Address{warp.Module.Address}, }) @@ -507,7 +507,7 @@ func (w *warpTest) deliverAddressedCallToReceivingSubnet() { blockHash, _ := w.getBlockHashAndNumberFromTxReceipt(receiptCtx, client, signedTx) log.Info("Fetching relevant warp logs and receipts from new block") - logs, err := client.FilterLogs(ctx, interfaces.FilterQuery{ + logs, err := client.FilterLogs(ctx, ethereum.FilterQuery{ BlockHash: &blockHash, Addresses: []common.Address{warp.Module.Address}, }) @@ -562,7 +562,7 @@ func (w *warpTest) deliverBlockHashPayload() { defer cancel() blockHash, _ := w.getBlockHashAndNumberFromTxReceipt(receiptCtx, client, signedTx) log.Info("Fetching relevant warp logs and receipts from new block") - logs, err := client.FilterLogs(ctx, interfaces.FilterQuery{ + logs, err := client.FilterLogs(ctx, ethereum.FilterQuery{ BlockHash: &blockHash, Addresses: []common.Address{warp.Module.Address}, }) @@ -639,7 +639,7 @@ func (w *warpTest) warpLoad() { log.Info("Subscribing to warp send events on sending subnet") logs := make(chan types.Log, numWorkers*int(txsPerWorker)) - sub, err := sendingClient.SubscribeFilterLogs(ctx, interfaces.FilterQuery{ + sub, err := sendingClient.SubscribeFilterLogs(ctx, ethereum.FilterQuery{ Addresses: []common.Address{warp.Module.Address}, }, logs) require.NoError(err) diff --git a/tools.go b/tools.go index 312a2d6302..9b4ad3062b 100644 --- a/tools.go +++ b/tools.go @@ -1,8 +1,11 @@ // (c) 2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. +//go:build tools + package subnetevm import ( + _ "github.com/fjl/gencodec" _ "golang.org/x/mod/modfile" // golang.org/x/mod to satisfy requirement for go.uber.org/mock/mockgen@v0.4 ) diff --git a/triedb/hashdb/database.go b/triedb/hashdb/database.go index 3080af13b8..2a3bd11a16 100644 --- a/triedb/hashdb/database.go +++ b/triedb/hashdb/database.go @@ -34,6 +34,8 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/metrics" @@ -43,8 +45,6 @@ import ( "github.com/ava-labs/libevm/trie/triestate" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/libevm/triedb/database" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/utils" // Force libevm metrics of the same name to be registered first. diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index d761b97343..f4fcdede6a 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -33,14 +33,14 @@ import ( "sync" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" "github.com/ava-labs/libevm/triedb" "github.com/ava-labs/libevm/triedb/database" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/params" ) diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go index c8d527c509..8479d05b83 100644 --- a/triedb/pathdb/database_test.go +++ b/triedb/pathdb/database_test.go @@ -34,13 +34,13 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie/testutil" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) diff --git a/triedb/pathdb/difflayer_test.go b/triedb/pathdb/difflayer_test.go index d0c8d51728..1acccfe9be 100644 --- a/triedb/pathdb/difflayer_test.go +++ b/triedb/pathdb/difflayer_test.go @@ -31,9 +31,9 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/trie/testutil" "github.com/ava-labs/libevm/trie/trienode" - "github.com/ava-labs/subnet-evm/core/rawdb" ) func emptyLayer() *diskLayer { diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index 0bddd25165..ab8e19d10e 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -33,11 +33,11 @@ import ( "github.com/VictoriaMetrics/fastcache" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/rawdb" "golang.org/x/crypto/sha3" ) diff --git a/triedb/pathdb/history_test.go b/triedb/pathdb/history_test.go index d001e4e894..b034326b68 100644 --- a/triedb/pathdb/history_test.go +++ b/triedb/pathdb/history_test.go @@ -32,10 +32,10 @@ import ( "testing" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie/testutil" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/types" ) // randomStateSet generates a random state change set. diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 678354aba5..3d4d4ae6c7 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -34,13 +34,13 @@ import ( "time" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/rlp" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/rawdb" - "github.com/ava-labs/subnet-evm/core/types" ) var ( diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go index 71eff3dba5..3fc904cdcf 100644 --- a/triedb/pathdb/layertree.go +++ b/triedb/pathdb/layertree.go @@ -32,9 +32,9 @@ import ( "sync" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/types" ) // layerTree is a group of state layers identified by the state root. diff --git a/triedb/pathdb/nodebuffer.go b/triedb/pathdb/nodebuffer.go index 80617916fc..54466cc51f 100644 --- a/triedb/pathdb/nodebuffer.go +++ b/triedb/pathdb/nodebuffer.go @@ -32,11 +32,11 @@ import ( "github.com/VictoriaMetrics/fastcache" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/ethdb" "github.com/ava-labs/libevm/log" "github.com/ava-labs/libevm/trie/trienode" - "github.com/ava-labs/subnet-evm/core/rawdb" ) // nodebuffer is a collection of modified trie nodes to aggregate the disk diff --git a/triedb/pathdb/testutils.go b/triedb/pathdb/testutils.go index bdf1e6374a..2e2ef3f96c 100644 --- a/triedb/pathdb/testutils.go +++ b/triedb/pathdb/testutils.go @@ -31,10 +31,10 @@ import ( "fmt" "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/trie/trienode" "github.com/ava-labs/libevm/trie/triestate" - "github.com/ava-labs/subnet-evm/core/types" "golang.org/x/exp/slices" ) diff --git a/utils/key.go b/utils/key.go index ab4db85b94..cc4efa6751 100644 --- a/utils/key.go +++ b/utils/key.go @@ -1,30 +1,30 @@ -// (c) 2021-2022, Ava Labs, Inc. All rights reserved. +// (c) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package utils import ( "crypto/ecdsa" - "io" + "crypto/rand" + "testing" "github.com/ava-labs/libevm/common" "github.com/ava-labs/libevm/crypto" + "github.com/stretchr/testify/require" ) +// Key contains an ecdsa private key field as well as an address field +// obtained from converting the ecdsa public key. type Key struct { Address common.Address PrivateKey *ecdsa.PrivateKey } -func NewKey(rand io.Reader) (*Key, error) { - privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand) - if err != nil { - return nil, err - } - return NewKeyFromECDSA(privateKeyECDSA), nil -} - -func NewKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key { +// NewKey generates a new key pair and returns a pointer to a [Key]. +func NewKey(t *testing.T) *Key { + t.Helper() + privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) + require.NoError(t, err) return &Key{ Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey), PrivateKey: privateKeyECDSA, diff --git a/vmerrs/vmerrs.go b/vmerrs/vmerrs.go deleted file mode 100644 index 77d9c0b56f..0000000000 --- a/vmerrs/vmerrs.go +++ /dev/null @@ -1,54 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package vmerrs - -import ( - "errors" - - "github.com/ava-labs/libevm/core/vm" -) - -// List evm execution errors -var ( - ErrOutOfGas = vm.ErrOutOfGas - ErrCodeStoreOutOfGas = vm.ErrCodeStoreOutOfGas - ErrDepth = vm.ErrDepth - ErrInsufficientBalance = vm.ErrInsufficientBalance - ErrContractAddressCollision = vm.ErrContractAddressCollision - ErrExecutionReverted = vm.ErrExecutionReverted - ErrMaxInitCodeSizeExceeded = vm.ErrMaxInitCodeSizeExceeded - ErrMaxCodeSizeExceeded = vm.ErrMaxCodeSizeExceeded - ErrInvalidJump = vm.ErrInvalidJump - ErrWriteProtection = vm.ErrWriteProtection - ErrReturnDataOutOfBounds = vm.ErrReturnDataOutOfBounds - ErrGasUintOverflow = vm.ErrGasUintOverflow - ErrInvalidCode = vm.ErrInvalidCode - ErrNonceUintOverflow = vm.ErrNonceUintOverflow - ErrAddrProhibited = errors.New("prohibited address cannot be sender or created contract address") - ErrInvalidCoinbase = errors.New("invalid coinbase") - ErrSenderAddressNotAllowListed = errors.New("cannot issue transaction from non-allow listed address") -)