From 94f614a7b6fbfb2fe81d91f16983092fc1f2632a Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 19:04:25 +0900 Subject: [PATCH 01/15] Enable Cancun EIPs test and add expected data of Prague --- build/checksums.txt | 6 +++--- tests/state_test.go | 8 ++++++-- tests/state_test_util.go | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build/checksums.txt b/build/checksums.txt index 29a3f7c6a..8619a6950 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -1,6 +1,6 @@ # This file contains sha256 checksums of optional build dependencies. -# version:spec-tests 2.1.0 +# version:spec-tests 3.0.0 # https://github.com/ethereum/execution-spec-tests/releases -# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/ -ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz +# https://github.com/ethereum/execution-spec-tests/releases/download/v3.0.0/ +4a750a0554158b4a47def19aa1409f5f75ccbebad223d41a2148790b06399528 fixtures_develop.tar.gz diff --git a/tests/state_test.go b/tests/state_test.go index e35c60b58..84102248e 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -91,9 +91,13 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { st.skipLoad(`^frontier\/`) st.skipLoad(`^homestead\/`) st.skipLoad(`^byzantium\/`) + st.skipLoad(`^constantinople\/`) st.skipLoad(`^istanbul\/`) st.skipLoad(`^berlin\/`) - st.skipLoad(`^cancun\/`) + st.skipLoad(`^prague\/`) + + // tests to skip + st.skipLoad(`^cancun\/eip4844_blobs\/`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { execStateTest(t, st, test, name, []string{ @@ -105,7 +109,7 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { "Istanbul", "Berlin", "London", - "Merge", + "Merge", "Paris", "Shanghai", // "Cancun", // "Prague", diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 535f01134..838f30bc4 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -192,6 +192,9 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutio } blockContext := blockchain.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase) blockContext.GetHash = vmTestBlockHash + if isTestExecutionSpecState { + blockContext.GasLimit = t.json.Env.GasLimit + } evm := vm.NewEVM(blockContext, txContext, statedb, config, &vmconfig) if isTestExecutionSpecState { From 4946a7f31d873c3c3b937dd3ce9889af279317af Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 19:27:05 +0900 Subject: [PATCH 02/15] Add downloading Prague tests --- build/checksums.txt | 1 + build/ci.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/build/checksums.txt b/build/checksums.txt index 8619a6950..71f7ef2ce 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -4,3 +4,4 @@ # https://github.com/ethereum/execution-spec-tests/releases # https://github.com/ethereum/execution-spec-tests/releases/download/v3.0.0/ 4a750a0554158b4a47def19aa1409f5f75ccbebad223d41a2148790b06399528 fixtures_develop.tar.gz +9d12f331d21cdc580f658a9891133ac26da703351d2585077935e6abde72851d fixtures_pectra-devnet-4.tar.gz \ No newline at end of file diff --git a/build/ci.go b/build/ci.go index 4f420baf5..fc3f65108 100644 --- a/build/ci.go +++ b/build/ci.go @@ -275,6 +275,8 @@ func doTest(cmdline []string) { // Get test fixtures. csdb := build.MustLoadChecksums("build/checksums.txt") downloadSpecTestFixtures(csdb, *cachedir) + downloadPragueSpecTestFixtures(csdb, *cachedir) + return packages := []string{"./..."} if len(flag.CommandLine.Args()) > 0 { @@ -317,6 +319,27 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string { return filepath.Join(cachedir, base) } +// downloadPragueSpecTestFixtures downloads and extracts the execution-spec-tests fixtures for Prague. +func downloadPragueSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string { + // remove prague of v3 + os.RemoveAll(executionSpecTestsDir + "/fixtures/blockchain_tests/prague") + os.RemoveAll(executionSpecTestsDir + "/fixtures/blockchain_tests_engine/prague") + os.RemoveAll(executionSpecTestsDir + "/fixtures/state_tests/prague") + + executionSpecTestsVersion := "pectra-devnet-4@v1.0.1" + ext := ".tar.gz" + base := "fixtures_pectra-devnet-4" + url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/%s/%s%s", executionSpecTestsVersion, base, ext) + archivePath := filepath.Join(cachedir, base+ext) + if err := csdb.DownloadFile(url, archivePath); err != nil { + log.Fatal(err) + } + if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil { + log.Fatal(err) + } + return filepath.Join(cachedir, base) +} + func doCover(cmdline []string) { var ( parallel = flag.Int("p", 0, "The number of parallel coverage test executions (default: the number of CPUs available)") From 091b8ddb50fc1fb5fa3585271542f51b15542363 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 19:40:40 +0900 Subject: [PATCH 03/15] Update run function --- tests/state_test.go | 2 +- tests/state_test_util.go | 119 ++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index 84102248e..72599de43 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -133,7 +133,7 @@ func execStateTest(t *testing.T, st *testMatcher, test *StateTest, name string, } } withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { - _, err := test.Run(subtest, vmconfig, isTestExecutionSpecState) + err := test.Run(subtest, vmconfig, isTestExecutionSpecState) return st.checkFailure(t, name, err) }) }) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 838f30bc4..f946e9c39 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -70,9 +70,11 @@ type stJSON struct { } type stPostState struct { - Root common.UnprefixedHash `json:"hash"` - Logs common.UnprefixedHash `json:"logs"` - Indexes struct { + Root common.UnprefixedHash `json:"hash"` + Logs common.UnprefixedHash `json:"logs"` + TxBytes hexutil.Bytes `json:"txbytes"` + ExpectException string `json:"expectException"` + Indexes struct { Data int `json:"data"` Gas int `json:"gas"` Value int `json:"value"` @@ -156,11 +158,64 @@ func (t *StateTest) Subtests() []StateSubtest { return sub } -// Run executes a specific subtest. -func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutionSpecState bool) (*state.StateDB, error) { +// checkError checks if the error returned by the state transition matches any expected error. +// A failing expectation returns a wrapped version of the original error, if any, +// or a new error detailing the failing expectation. +// This function does not return or modify the original error, it only evaluates and returns expectations for the error. +func (t *StateTest) checkError(subtest StateSubtest, err error) error { + expectedError := t.json.Post[subtest.Fork][subtest.Index].ExpectException + if err == nil && expectedError == "" { + return nil + } + if err == nil && expectedError != "" { + return fmt.Errorf("expected error %q, got no error", expectedError) + } + if err != nil && expectedError == "" { + return fmt.Errorf("unexpected error: %w", err) + } + if err != nil && expectedError != "" { + // Ignore expected errors (TODO MariusVanDerWijden check error string) + return nil + } + return nil +} + +func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutionSpecState bool) (result error) { + st, root, err := t.RunNoVerify(subtest, vmconfig, isTestExecutionSpecState) + + // kaia-core-tests doesn't support ExpectException + if isTestExecutionSpecState { + checkedErr := t.checkError(subtest, err) + if checkedErr != nil { + return checkedErr + } + } + + // The error has been checked; if it was unexpected, it's already returned. + if err != nil { + // Here, an error exists but it was expected. + // We do not check the post state or logs. + return nil + } + post := t.json.Post[subtest.Fork][subtest.Index] + // N.B: We need to do this in a two-step process, because the first Commit takes care + // of self-destructs, and we need to touch the coinbase _after_ it has potentially self-destructed. + if root != common.Hash(post.Root) { + return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root) + } + if logs := rlpHash(st.Logs()); logs != common.Hash(post.Logs) { + return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs) + } + st, _ = state.New(root, st.Database(), nil, nil) + return nil +} + +// RunNoVerify runs a specific subtest and returns the statedb and post-state root. +// Remember to call state.Close after verifying the test result! +func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTestExecutionSpecState bool) (st *state.StateDB, root common.Hash, err error) { config, eips, err := getVMConfig(subtest.Fork) if err != nil { - return nil, UnsupportedForkError{subtest.Fork} + return st, common.Hash{}, UnsupportedForkError{subtest.Fork} } if isTestExecutionSpecState { @@ -175,19 +230,36 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutio blockchain.InitDeriveSha(config) block := t.genesis(config).ToBlock(common.Hash{}, nil) memDBManager := database.NewMemoryDBManager() - statedb := MakePreState(memDBManager, t.json.Pre) + st = MakePreState(memDBManager, t.json.Pre) post := t.json.Post[subtest.Fork][subtest.Index] rules := config.Rules(block.Number()) msg, err := t.json.Tx.toMessage(post, rules, isTestExecutionSpecState) if err != nil { - return nil, err + return st, common.Hash{}, err + } + + // Try to recover tx with current signer + if len(post.TxBytes) != 0 { + var ttx types.Transaction + txBytes := post.TxBytes + if post.TxBytes[0] <= 4 { + txBytes = append([]byte{byte(types.EthereumTxTypeEnvelope)}, txBytes...) + } + err = ttx.UnmarshalBinary(txBytes) + if err != nil { + return st, common.Hash{}, err + } + if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil { + return st, common.Hash{}, err + } } + txContext := blockchain.NewEVMTxContext(msg, block.Header(), config) if isTestExecutionSpecState { txContext.GasPrice, err = useEthGasPrice(rules, &t.json) if err != nil { - return nil, err + return st, common.Hash{}, err } } blockContext := blockchain.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase) @@ -195,46 +267,39 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutio if isTestExecutionSpecState { blockContext.GasLimit = t.json.Env.GasLimit } - evm := vm.NewEVM(blockContext, txContext, statedb, config, &vmconfig) + evm := vm.NewEVM(blockContext, txContext, st, config, &vmconfig) if isTestExecutionSpecState { useEthOpCodeGas(rules, evm) } - snapshot := statedb.Snapshot() + snapshot := st.Snapshot() result, err := blockchain.ApplyMessage(evm, msg) if err != nil { - statedb.RevertToSnapshot(snapshot) + st.RevertToSnapshot(snapshot) } if isTestExecutionSpecState && err == nil { - useEthMiningReward(statedb, evm, &t.json.Tx, t.json.Env.BaseFee, result.UsedGas, txContext.GasPrice) - } - - if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) { - return statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs) + useEthMiningReward(st, evm, &t.json.Tx, t.json.Env.BaseFee, result.UsedGas, txContext.GasPrice) } - root, _ := statedb.Commit(true) + root, _ = st.Commit(true) // Add 0-value mining reward. This only makes a difference in the cases // where // - the coinbase self-destructed, or // - there are only 'bad' transactions, which aren't executed. In those cases, // the coinbase gets no txfee, so isn't created, and thus needs to be touched - statedb.AddBalance(block.Rewardbase(), new(big.Int)) + st.AddBalance(block.Rewardbase(), new(big.Int)) // And _now_ get the state root - root = statedb.IntermediateRoot(true) + root = st.IntermediateRoot(true) - if isTestExecutionSpecState { - root, err = useEthStateRoot(statedb) + if err == nil && isTestExecutionSpecState { + root, err = useEthStateRoot(st) if err != nil { - return nil, err + return st, common.Hash{}, err } } - if root != common.Hash(post.Root) { - return statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root) - } - return statedb, nil + return st, root, err } func (t *StateTest) gasLimit(subtest StateSubtest) uint64 { From a12cc3390d4c510674aaa04175254ac94d378d64 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 19:52:23 +0900 Subject: [PATCH 04/15] Enable Prague EIPs tests --- tests/state_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index 72599de43..60a4e57cc 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -94,10 +94,10 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { st.skipLoad(`^constantinople\/`) st.skipLoad(`^istanbul\/`) st.skipLoad(`^berlin\/`) - st.skipLoad(`^prague\/`) - // tests to skip + // tests to skip due to unsupported EIPs st.skipLoad(`^cancun\/eip4844_blobs\/`) + st.skipLoad(`^prague\/eip7702_set_code_tx\/`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { execStateTest(t, st, test, name, []string{ From 8cd9f9927d1acdc39eb44473baf85fb73bfe1908 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 19:56:06 +0900 Subject: [PATCH 05/15] Fix --- build/checksums.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/checksums.txt b/build/checksums.txt index 71f7ef2ce..9caabe80a 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -4,4 +4,4 @@ # https://github.com/ethereum/execution-spec-tests/releases # https://github.com/ethereum/execution-spec-tests/releases/download/v3.0.0/ 4a750a0554158b4a47def19aa1409f5f75ccbebad223d41a2148790b06399528 fixtures_develop.tar.gz -9d12f331d21cdc580f658a9891133ac26da703351d2585077935e6abde72851d fixtures_pectra-devnet-4.tar.gz \ No newline at end of file +9d12f331d21cdc580f658a9891133ac26da703351d2585077935e6abde72851d fixtures_pectra-devnet-4.tar.gz From b699a25908582b3bb143e6e67e9f47c0043e1f80 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Thu, 28 Nov 2024 20:00:11 +0900 Subject: [PATCH 06/15] Disable Prague EIP tests --- tests/state_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/state_test.go b/tests/state_test.go index 60a4e57cc..3b4370418 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -94,10 +94,10 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { st.skipLoad(`^constantinople\/`) st.skipLoad(`^istanbul\/`) st.skipLoad(`^berlin\/`) + st.skipLoad(`^prague\/`) // tests to skip due to unsupported EIPs st.skipLoad(`^cancun\/eip4844_blobs\/`) - st.skipLoad(`^prague\/eip7702_set_code_tx\/`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { execStateTest(t, st, test, name, []string{ From 5e0d4794838b6fbbeec21f0e2dfd71aaf85850ef Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Fri, 29 Nov 2024 15:25:17 +0900 Subject: [PATCH 07/15] Fix --- blockchain/vm/contracts.go | 13 +++++++------ common/types.go | 6 +++++- tests/state_test.go | 2 +- tests/state_test_util.go | 1 + 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/blockchain/vm/contracts.go b/blockchain/vm/contracts.go index 23f6cf9ab..587930a1e 100644 --- a/blockchain/vm/contracts.go +++ b/blockchain/vm/contracts.go @@ -208,12 +208,13 @@ func ActivePrecompiles(rules params.Rules) []common.Address { // After istanbulCompatible hf, need to support for vmversion0 contracts, too. // VmVersion0 contracts are deployed before istanbulCompatible and they use byzantiumCompatible precompiled contracts. // VmVersion0 contracts are the contracts deployed before istanbulCompatible hf. - if rules.IsIstanbul { - return append(precompiledContractAddrs, - []common.Address{common.BytesToAddress([]byte{10}), common.BytesToAddress([]byte{11})}...) - } else { - return precompiledContractAddrs - } + // if rules.IsIstanbul { + // return append(precompiledContractAddrs, + // []common.Address{common.BytesToAddress([]byte{10}), common.BytesToAddress([]byte{11})}...) + // } else { + // return precompiledContractAddrs + // } + return precompiledContractAddrs } // RunPrecompiledContract runs and evaluates the output of a precompiled contract. diff --git a/common/types.go b/common/types.go index 2ce443105..c279768ac 100644 --- a/common/types.go +++ b/common/types.go @@ -358,7 +358,11 @@ var relaxPrecompileRangeForTest bool // IsPrecompiledContractAddress returns true if the input address is in the range of precompiled contract addresses. func IsPrecompiledContractAddress(addr Address) bool { if relaxPrecompileRangeForTest { - return false + // TODO-kaia: should use precompile address list to check it for before_fork tests + UnderFF := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000000ff")) <= 0 + above03f0 := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000003f0")) >= 0 + Under03ff := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000003ff")) <= 0 + return UnderFF || (above03f0 && Under03ff) // (addr in [0, 0xff]) or (addr in [0x3f0, 0x3ff]) } if bytes.Compare(addr.Bytes(), lastPrecompiledContractAddressHex) > 0 || addr == (Address{}) { return false diff --git a/tests/state_test.go b/tests/state_test.go index 3b4370418..60a4e57cc 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -94,10 +94,10 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { st.skipLoad(`^constantinople\/`) st.skipLoad(`^istanbul\/`) st.skipLoad(`^berlin\/`) - st.skipLoad(`^prague\/`) // tests to skip due to unsupported EIPs st.skipLoad(`^cancun\/eip4844_blobs\/`) + st.skipLoad(`^prague\/eip7702_set_code_tx\/`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { execStateTest(t, st, test, name, []string{ diff --git a/tests/state_test_util.go b/tests/state_test_util.go index f946e9c39..2240018ba 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -311,6 +311,7 @@ func MakePreState(db database.DBManager, accounts blockchain.GenesisAlloc) *stat statedb, _ := state.New(common.Hash{}, sdb, nil, nil) for addr, a := range accounts { if len(a.Code) != 0 { + statedb.CreateSmartContractAccount(addr, params.CodeFormatEVM, params.Rules{IsIstanbul: true}) statedb.SetCode(addr, a.Code) } for k, v := range a.Storage { From ae1553cf50de6290861ba21d2536c4d3c9ac6ca9 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Mon, 2 Dec 2024 15:58:23 +0900 Subject: [PATCH 08/15] Check active precompiled contract --- blockchain/vm/contracts.go | 36 +++++++++++++++++++++++++++++------- blockchain/vm/evm.go | 4 ++-- common/types.go | 12 ------------ tests/state_test.go | 6 ++++-- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/blockchain/vm/contracts.go b/blockchain/vm/contracts.go index 587930a1e..4dccba46e 100644 --- a/blockchain/vm/contracts.go +++ b/blockchain/vm/contracts.go @@ -23,6 +23,7 @@ package vm import ( + "bytes" "crypto/ecdsa" "crypto/sha256" "encoding/binary" @@ -208,13 +209,34 @@ func ActivePrecompiles(rules params.Rules) []common.Address { // After istanbulCompatible hf, need to support for vmversion0 contracts, too. // VmVersion0 contracts are deployed before istanbulCompatible and they use byzantiumCompatible precompiled contracts. // VmVersion0 contracts are the contracts deployed before istanbulCompatible hf. - // if rules.IsIstanbul { - // return append(precompiledContractAddrs, - // []common.Address{common.BytesToAddress([]byte{10}), common.BytesToAddress([]byte{11})}...) - // } else { - // return precompiledContractAddrs - // } - return precompiledContractAddrs + if rules.IsIstanbul { + return append(precompiledContractAddrs, + []common.Address{common.BytesToAddress([]byte{10}), common.BytesToAddress([]byte{11})}...) + } else { + return precompiledContractAddrs + } +} + +// IsPrecompiledContractAddress returns true if this is used for TestExecutionSpecState and the input address is one of precompiled contract addresses. +func IsPrecompiledContractAddress(addr common.Address, rules params.Rules) bool { + if relaxPrecompileRangeForTest { + rules.IsIstanbul = false + activePrecompiles := ActivePrecompiles(rules) + for _, pre := range activePrecompiles { + if bytes.Compare(pre.Bytes(), addr.Bytes()) == 0 { + return true + } + } + return false + } + return common.IsPrecompiledContractAddress(addr) +} + +var relaxPrecompileRangeForTest bool + +// Only for testing. Make sure to reset (false) after test. +func RelaxPrecompileRangeForTest(enable bool) { + relaxPrecompileRangeForTest = enable } // RunPrecompiledContract runs and evaluates the output of a precompiled contract. diff --git a/blockchain/vm/evm.go b/blockchain/vm/evm.go index 3db826e82..9d32b340d 100644 --- a/blockchain/vm/evm.go +++ b/blockchain/vm/evm.go @@ -256,7 +256,7 @@ func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte ) // Filter out invalid precompiled address calls, and create a precompiled contract object if it is not exist. - if common.IsPrecompiledContractAddress(addr) { + if IsPrecompiledContractAddress(addr, evm.chainRules) { precompiles := evm.GetPrecompiledContractMap(caller.Address()) if precompiles[addr] == nil || value.Sign() != 0 { // Return an error if an enabled precompiled address is called or a value is transferred to a precompiled address. @@ -527,7 +527,7 @@ func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas u return nil, common.Address{}, 0, ErrContractAddressCollision } - if common.IsPrecompiledContractAddress(address) { + if IsPrecompiledContractAddress(address, evm.chainRules) { return nil, common.Address{}, gas, kerrors.ErrPrecompiledContractAddress } diff --git a/common/types.go b/common/types.go index c279768ac..707ae85a7 100644 --- a/common/types.go +++ b/common/types.go @@ -357,24 +357,12 @@ var relaxPrecompileRangeForTest bool // IsPrecompiledContractAddress returns true if the input address is in the range of precompiled contract addresses. func IsPrecompiledContractAddress(addr Address) bool { - if relaxPrecompileRangeForTest { - // TODO-kaia: should use precompile address list to check it for before_fork tests - UnderFF := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000000ff")) <= 0 - above03f0 := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000003f0")) >= 0 - Under03ff := bytes.Compare(addr.Bytes(), hexutil.MustDecode("0x00000000000000000000000000000000000003ff")) <= 0 - return UnderFF || (above03f0 && Under03ff) // (addr in [0, 0xff]) or (addr in [0x3f0, 0x3ff]) - } if bytes.Compare(addr.Bytes(), lastPrecompiledContractAddressHex) > 0 || addr == (Address{}) { return false } return true } -// Only for testing. Make sure to reset (false) after test. -func RelaxPrecompileRangeForTest(enable bool) { - relaxPrecompileRangeForTest = enable -} - // IsHexAddress verifies whether a string can represent a valid hex-encoded // Kaia address or not. func IsHexAddress(s string) bool { diff --git a/tests/state_test.go b/tests/state_test.go index 60a4e57cc..9a894d38e 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -72,11 +72,11 @@ type ExecutionSpecStateTestSuite struct { } func (suite *ExecutionSpecStateTestSuite) SetupSuite() { - common.RelaxPrecompileRangeForTest(true) + vm.RelaxPrecompileRangeForTest(true) } func (suite *ExecutionSpecStateTestSuite) TearDownSuite() { - common.RelaxPrecompileRangeForTest(false) + vm.RelaxPrecompileRangeForTest(false) } func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { @@ -98,6 +98,8 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { // tests to skip due to unsupported EIPs st.skipLoad(`^cancun\/eip4844_blobs\/`) st.skipLoad(`^prague\/eip7702_set_code_tx\/`) + // Kaia set access list in preparation of tx execution ActivePrecompiles + st.skipLoad(`^prague\/eip2537_bls_12_381_precompiles\/bls12_precompiles_before_fork\/precompile_before_fork.json\/tests\/prague\/eip2537_bls_12_381_precompiles\/test_bls12_precompiles_before_fork.py::test_precompile_before_fork`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { execStateTest(t, st, test, name, []string{ From acb34de13dbef4d6dbb6f0d2d8000304170c6787 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Mon, 2 Dec 2024 16:05:04 +0900 Subject: [PATCH 09/15] Fix commnets --- tests/state_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index 9a894d38e..ee39b7b66 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -95,10 +95,11 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { st.skipLoad(`^istanbul\/`) st.skipLoad(`^berlin\/`) - // tests to skip due to unsupported EIPs + // tests to skip + // unsupported EIPs st.skipLoad(`^cancun\/eip4844_blobs\/`) st.skipLoad(`^prague\/eip7702_set_code_tx\/`) - // Kaia set access list in preparation of tx execution ActivePrecompiles + // calculate the different consumed gas because 0x0a and 0x0b contract is set to access list by ActivePrecompiles in Cancun st.skipLoad(`^prague\/eip2537_bls_12_381_precompiles\/bls12_precompiles_before_fork\/precompile_before_fork.json\/tests\/prague\/eip2537_bls_12_381_precompiles\/test_bls12_precompiles_before_fork.py::test_precompile_before_fork`) st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) { From f4ee655aa1b81ed0941aa6380dcce25845697cae Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Mon, 2 Dec 2024 17:20:42 +0900 Subject: [PATCH 10/15] Skip 0x0a and 0x0b --- blockchain/vm/contracts.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/blockchain/vm/contracts.go b/blockchain/vm/contracts.go index 4dccba46e..1e19a3c9a 100644 --- a/blockchain/vm/contracts.go +++ b/blockchain/vm/contracts.go @@ -220,9 +220,12 @@ func ActivePrecompiles(rules params.Rules) []common.Address { // IsPrecompiledContractAddress returns true if this is used for TestExecutionSpecState and the input address is one of precompiled contract addresses. func IsPrecompiledContractAddress(addr common.Address, rules params.Rules) bool { if relaxPrecompileRangeForTest { - rules.IsIstanbul = false activePrecompiles := ActivePrecompiles(rules) for _, pre := range activePrecompiles { + // skip 0x0a and 0x0b if before Prague + if !rules.IsPrague && (bytes.Compare(pre.Bytes(), []byte{10}) == 0 || bytes.Compare(pre.Bytes(), []byte{11}) == 0) { + continue + } if bytes.Compare(pre.Bytes(), addr.Bytes()) == 0 { return true } From 1ecd4230cb128c84eb1d69b728e9ae8cbf8c55aa Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Mon, 2 Dec 2024 17:42:21 +0900 Subject: [PATCH 11/15] Return early --- tests/state_test_util.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 2240018ba..a3f964638 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -277,9 +277,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTest result, err := blockchain.ApplyMessage(evm, msg) if err != nil { st.RevertToSnapshot(snapshot) + return st, common.Hash{}, err } - if isTestExecutionSpecState && err == nil { + if isTestExecutionSpecState { useEthMiningReward(st, evm, &t.json.Tx, t.json.Env.BaseFee, result.UsedGas, txContext.GasPrice) } @@ -293,7 +294,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTest // And _now_ get the state root root = st.IntermediateRoot(true) - if err == nil && isTestExecutionSpecState { + if isTestExecutionSpecState { root, err = useEthStateRoot(st) if err != nil { return st, common.Hash{}, err From 7bbda61ea872ac2ba7e57233c3022be123a162b9 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Tue, 3 Dec 2024 11:03:37 +0900 Subject: [PATCH 12/15] Remove return --- build/ci.go | 1 - 1 file changed, 1 deletion(-) diff --git a/build/ci.go b/build/ci.go index fc3f65108..c9c5c3c82 100644 --- a/build/ci.go +++ b/build/ci.go @@ -276,7 +276,6 @@ func doTest(cmdline []string) { csdb := build.MustLoadChecksums("build/checksums.txt") downloadSpecTestFixtures(csdb, *cachedir) downloadPragueSpecTestFixtures(csdb, *cachedir) - return packages := []string{"./..."} if len(flag.CommandLine.Args()) > 0 { From cba0db14b97cd1673236616c08b8f7ac0d0aef97 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Tue, 3 Dec 2024 13:10:31 +0900 Subject: [PATCH 13/15] Skip tests --- tests/state_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/state_test.go b/tests/state_test.go index ee39b7b66..f6bd0edba 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -97,6 +97,7 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { // tests to skip // unsupported EIPs + st.skipLoad(`^cancun\/eip4788_beacon_root\/`) st.skipLoad(`^cancun\/eip4844_blobs\/`) st.skipLoad(`^prague\/eip7702_set_code_tx\/`) // calculate the different consumed gas because 0x0a and 0x0b contract is set to access list by ActivePrecompiles in Cancun From 8fb0914a0b9175fc78baabd544c722afd4868ffc Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Tue, 3 Dec 2024 13:45:53 +0900 Subject: [PATCH 14/15] Update tests/state_test.go Co-authored-by: Chihyun Song --- tests/state_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/state_test.go b/tests/state_test.go index f6bd0edba..657661adc 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -113,7 +113,8 @@ func (suite *ExecutionSpecStateTestSuite) TestExecutionSpecState() { "Istanbul", "Berlin", "London", - "Merge", "Paris", + "Merge", + "Paris", "Shanghai", // "Cancun", // "Prague", From 6037526d8081af69a8dbe462b94c65e2cea61893 Mon Sep 17 00:00:00 2001 From: Shogo Hyodo Date: Tue, 3 Dec 2024 15:28:20 +0900 Subject: [PATCH 15/15] Revert --- node/cn/tracers/tracers_test.go | 2 +- tests/state_test_util.go | 26 ++++++++++++++------------ tests/vm_test_util.go | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/node/cn/tracers/tracers_test.go b/node/cn/tracers/tracers_test.go index 319b23f82..c442b89b2 100644 --- a/node/cn/tracers/tracers_test.go +++ b/node/cn/tracers/tracers_test.go @@ -152,7 +152,7 @@ func runTracer(t *testing.T, tc *tracerTestdata, tracer vm.Tracer) (*types.Trans signer = types.MakeSigner(config, header.Number) blockContext = blockchain.NewEVMBlockContext(header, nil, &common.Address{}) // stub author (COINBASE) to 0x0 txContext = blockchain.NewEVMTxContext(tx, header, config) - statedb = tests.MakePreState(database.NewMemoryDBManager(), alloc) + statedb = tests.MakePreState(database.NewMemoryDBManager(), alloc, false) evm = vm.NewEVM(blockContext, txContext, statedb, config, &vm.Config{Debug: true, Tracer: tracer}) ) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index a3f964638..bb1882497 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -189,14 +189,15 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, isTestExecutio if checkedErr != nil { return checkedErr } - } - // The error has been checked; if it was unexpected, it's already returned. - if err != nil { - // Here, an error exists but it was expected. - // We do not check the post state or logs. - return nil + // The error has been checked; if it was unexpected, it's already returned. + if err != nil { + // Here, an error exists but it was expected. + // We do not check the post state or logs. + return nil + } } + post := t.json.Post[subtest.Fork][subtest.Index] // N.B: We need to do this in a two-step process, because the first Commit takes care // of self-destructs, and we need to touch the coinbase _after_ it has potentially self-destructed. @@ -230,7 +231,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTest blockchain.InitDeriveSha(config) block := t.genesis(config).ToBlock(common.Hash{}, nil) memDBManager := database.NewMemoryDBManager() - st = MakePreState(memDBManager, t.json.Pre) + st = MakePreState(memDBManager, t.json.Pre, isTestExecutionSpecState) post := t.json.Post[subtest.Fork][subtest.Index] rules := config.Rules(block.Number()) @@ -277,10 +278,9 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTest result, err := blockchain.ApplyMessage(evm, msg) if err != nil { st.RevertToSnapshot(snapshot) - return st, common.Hash{}, err } - if isTestExecutionSpecState { + if err == nil && isTestExecutionSpecState { useEthMiningReward(st, evm, &t.json.Tx, t.json.Env.BaseFee, result.UsedGas, txContext.GasPrice) } @@ -294,7 +294,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, isTest // And _now_ get the state root root = st.IntermediateRoot(true) - if isTestExecutionSpecState { + if err == nil && isTestExecutionSpecState { root, err = useEthStateRoot(st) if err != nil { return st, common.Hash{}, err @@ -307,12 +307,14 @@ func (t *StateTest) gasLimit(subtest StateSubtest) uint64 { return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas] } -func MakePreState(db database.DBManager, accounts blockchain.GenesisAlloc) *state.StateDB { +func MakePreState(db database.DBManager, accounts blockchain.GenesisAlloc, isTestExecutionSpecState bool) *state.StateDB { sdb := state.NewDatabase(db) statedb, _ := state.New(common.Hash{}, sdb, nil, nil) for addr, a := range accounts { if len(a.Code) != 0 { - statedb.CreateSmartContractAccount(addr, params.CodeFormatEVM, params.Rules{IsIstanbul: true}) + if isTestExecutionSpecState { + statedb.CreateSmartContractAccount(addr, params.CodeFormatEVM, params.Rules{IsIstanbul: true}) + } statedb.SetCode(addr, a.Code) } for k, v := range a.Storage { diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 03d386958..75af32a51 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -86,7 +86,7 @@ type vmExecMarshaling struct { func (t *VMTest) Run(vmconfig vm.Config) error { memDBManager := database.NewMemoryDBManager() - statedb := MakePreState(memDBManager, t.json.Pre) + statedb := MakePreState(memDBManager, t.json.Pre, false) ret, gasRemaining, err := t.exec(statedb, vmconfig) if t.json.GasRemaining == nil {