From f316b1d08687a41048d6e501b4718546930d15ed Mon Sep 17 00:00:00 2001 From: Mister-EA Date: Wed, 7 Jun 2023 14:10:00 +0200 Subject: [PATCH 1/4] params: introduce ParliaTestChainConfig --- params/config.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/params/config.go b/params/config.go index ff14a4add1..3cf11ea5fd 100644 --- a/params/config.go +++ b/params/config.go @@ -274,6 +274,42 @@ var ( }, } + ParliaTestChainConfig = &ChainConfig{ + ChainID: big.NewInt(2), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + RamanujanBlock: big.NewInt(0), + NielsBlock: big.NewInt(0), + MirrorSyncBlock: big.NewInt(0), + BrunoBlock: big.NewInt(0), + EulerBlock: big.NewInt(0), + NanoBlock: big.NewInt(0), + MoranBlock: big.NewInt(0), + GibbsBlock: big.NewInt(0), + PlanckBlock: big.NewInt(0), + + // TODO modify blockNumber, make sure the blockNumber is not an integer multiple of 200 (epoch number) + // TODO Caution !!! it should be very careful !!! + LubanBlock: big.NewInt(0), + PlatoBlock: big.NewInt(0), + // TODO modify blockNumber, make sure HertzBlock=BerlinBlock=LondonBlock to enable Berlin and London EIPs + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + HertzBlock: big.NewInt(0), + + Parlia: &ParliaConfig{ + Period: 3, + Epoch: 200, + }, + } + // AllEthashProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Ethash consensus. // From 4afd224350d6dd51a1a6137da0aafbff42241577 Mon Sep 17 00:00:00 2001 From: Mister-EA Date: Wed, 7 Jun 2023 14:16:01 +0200 Subject: [PATCH 2/4] core: add eip3529 tests for parlia config --- core/blockchain_eip3529_test.go | 41 +++- core/parlia_tests/blockchain_eip_3529_test.go | 210 ++++++++++++++++++ 2 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 core/parlia_tests/blockchain_eip_3529_test.go diff --git a/core/blockchain_eip3529_test.go b/core/blockchain_eip3529_test.go index 25e91469a0..8175fbd8f4 100644 --- a/core/blockchain_eip3529_test.go +++ b/core/blockchain_eip3529_test.go @@ -39,13 +39,49 @@ func TestSelfDestructGasPreEIP3529(t *testing.T) { testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } +func TestSstoreModifyGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x3, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 3 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) + // i.e. no refund + expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) + testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) +} + +func TestSstoreClearGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x0, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 0 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + + // Expected gas is (intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) ) / 2 + // The refund of params.SstoreClearsScheduleRefundEIP2200 is not applied because of the refund cap to half the gas cost. + expectedGasUsage := (params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929)) / 2 + testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) +} + func TestSstoreGasPreEIP3529(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x3, // location byte(vm.SSTORE), // Set slot[3] = 3 } - // // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas + // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas + // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } @@ -56,6 +92,7 @@ func TestSelfDestructGasPostEIP3529(t *testing.T) { byte(vm.SELFDESTRUCT), } // Expected gas is intrinsic + pc + cold load (due to legacy tx) + SelfDestructGas + // i.e. No refund expectedGasUsed := params.TxGas + vm.GasQuickStep + params.ColdAccountAccessCostEIP2929 + params.SelfdestructGasEIP150 testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } @@ -67,6 +104,7 @@ func TestSstoreGasPostEIP3529(t *testing.T) { byte(vm.SSTORE), // Set slot[3] = 3 } // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas + // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } @@ -83,6 +121,7 @@ func TestSstoreModifyGasPostEIP3529(t *testing.T) { initialStorage[common.HexToHash("01")] = common.HexToHash("01") initialStorage[common.HexToHash("02")] = common.HexToHash("02") // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) + // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) } diff --git a/core/parlia_tests/blockchain_eip_3529_test.go b/core/parlia_tests/blockchain_eip_3529_test.go new file mode 100644 index 0000000000..2a910fbca2 --- /dev/null +++ b/core/parlia_tests/blockchain_eip_3529_test.go @@ -0,0 +1,210 @@ +package parlia_tests + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +func newGwei(n int64) *big.Int { + return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei)) +} + +func postHertzConfig() *params.ChainConfig { + config := *params.ParliaTestChainConfig + return &config +} + +func preHertzConfig() *params.ChainConfig { + config := *params.ParliaTestChainConfig + config.LondonBlock = nil + config.BerlinBlock = nil + config.HertzBlock = nil + return &config +} + +func TestSelfDestructGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PC), + byte(vm.SELFDESTRUCT), + } + + // Expected gas is (intrinsic + selfdestruct cost ) / 2 + // The refund of 24000 gas (i.e. params.SelfdestructRefundGas) is not applied since refunds pre-EIP3529 are + // capped to half of the transaction's gas. + expectedGasUsed := (params.TxGas + vm.GasQuickStep + params.SelfdestructGasEIP150) / 2 + testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) +} + +func TestSstoreClearGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x0, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 0 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + + // Expected gas is (intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) ) / 2 + // The refund of params.SstoreClearsScheduleRefundEIP2200 is not applied because of the refund cap to half the gas cost. + expectedGasUsage := (params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200) / 2 + testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) +} + +func TestSstoreModifyGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x3, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 3 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + // Expected gas is intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) + // i.e. no refund + expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 + testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) +} + +func TestSstoreGasPreEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x3, // value + byte(vm.PUSH1), 0x3, // location + byte(vm.SSTORE), // Set slot[3] = 3 + } + // Expected gas is intrinsic + 2*pushGas + SstoreGas + // i.e. No refund + expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreSetGasEIP2200 + testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) +} + +func TestSelfDestructGasPostEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PC), + byte(vm.SELFDESTRUCT), + } + // Expected gas is intrinsic + pc + cold load (due to legacy tx) + SelfDestructGas + // i.e. No refund + expectedGasUsed := params.TxGas + vm.GasQuickStep + params.ColdAccountAccessCostEIP2929 + params.SelfdestructGasEIP150 + testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) +} + +func TestSstoreGasPostEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x3, // value + byte(vm.PUSH1), 0x3, // location + byte(vm.SSTORE), // Set slot[3] = 3 + } + // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas + // i.e. No refund + expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 + testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) +} + +func TestSstoreModifyGasPostEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x3, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 3 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) + // i.e. No refund + expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 + testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) +} + +func TestSstoreClearGasPostEIP3529(t *testing.T) { + bytecode := []byte{ + byte(vm.PUSH1), 0x0, // value + byte(vm.PUSH1), 0x1, // location + byte(vm.SSTORE), // Set slot[1] = 0 + } + // initialize contract storage + initialStorage := make(map[common.Hash]common.Hash) + // Populate two slots + initialStorage[common.HexToHash("01")] = common.HexToHash("01") + initialStorage[common.HexToHash("02")] = common.HexToHash("02") + + // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) - sstoreClearGasRefund + expectedGasUsage := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 - params.SstoreClearsScheduleRefundEIP3529 + testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) +} + +// Test the gas used by running a transaction sent to a smart contract with given bytecode and storage. +func testGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Engine, bytecode []byte, initialStorage map[common.Hash]common.Hash, initialGas, expectedGasUsed uint64) { + var ( + aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") + + // Generate a canonical chain to act as the main dataset + db = rawdb.NewMemoryDatabase() + + // A sender who makes transactions, has some funds + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + balanceBefore = big.NewInt(1000000000000000) + gspec = &core.Genesis{ + Config: config, + Alloc: core.GenesisAlloc{ + address: {Balance: balanceBefore}, + aa: { + Code: bytecode, + Storage: initialStorage, + Nonce: 0, + Balance: big.NewInt(0), + }, + }, + } + genesis = gspec.MustCommit(db) + ) + + blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) { + b.SetCoinbase(common.Address{1}) + + // One transaction to 0xAAAA + signer := types.LatestSigner(gspec.Config) + tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: 0, + To: &aa, + Gas: initialGas, + GasPrice: newGwei(5), + }) + b.AddTx(tx) + }) + + // Import the canonical chain + diskdb := rawdb.NewMemoryDatabase() + gspec.MustCommit(diskdb) + + chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + if n, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", n, err) + } + + block := chain.GetBlockByNumber(1) + + if block.GasUsed() != expectedGasUsed { + t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGasUsed, block.GasUsed()) + } +} From a97f71328622eb3084f996c1ffc18d0a3758c962 Mon Sep 17 00:00:00 2001 From: Mister-EA Date: Wed, 7 Jun 2023 16:11:30 +0200 Subject: [PATCH 3/4] parlia_tests: update comment --- core/parlia_tests/blockchain_eip_3529_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/parlia_tests/blockchain_eip_3529_test.go b/core/parlia_tests/blockchain_eip_3529_test.go index 2a910fbca2..7270ba39c3 100644 --- a/core/parlia_tests/blockchain_eip_3529_test.go +++ b/core/parlia_tests/blockchain_eip_3529_test.go @@ -144,7 +144,7 @@ func TestSstoreClearGasPostEIP3529(t *testing.T) { initialStorage[common.HexToHash("01")] = common.HexToHash("01") initialStorage[common.HexToHash("02")] = common.HexToHash("02") - // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) - sstoreClearGasRefund + // Expected gas is intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) - sstoreClearGasRefund expectedGasUsage := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 - params.SstoreClearsScheduleRefundEIP3529 testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) } From b1fbb294ea0f3288704defc08aec88cd9ce8d0a7 Mon Sep 17 00:00:00 2001 From: Mister-EA Date: Fri, 9 Jun 2023 12:27:31 +0200 Subject: [PATCH 4/4] eip3529tests: refactor tests --- .../eip3529_ethash_test.go} | 98 +++-------------- .../eip3529_parlia_test.go} | 104 +++--------------- core/eip3529tests/eip3529_test_util.go | 79 +++++++++++++ 3 files changed, 113 insertions(+), 168 deletions(-) rename core/{blockchain_eip3529_test.go => eip3529tests/eip3529_ethash_test.go} (62%) rename core/{parlia_tests/blockchain_eip_3529_test.go => eip3529tests/eip3529_parlia_test.go} (58%) create mode 100644 core/eip3529tests/eip3529_test_util.go diff --git a/core/blockchain_eip3529_test.go b/core/eip3529tests/eip3529_ethash_test.go similarity index 62% rename from core/blockchain_eip3529_test.go rename to core/eip3529tests/eip3529_ethash_test.go index 8175fbd8f4..f58afad1f4 100644 --- a/core/blockchain_eip3529_test.go +++ b/core/eip3529tests/eip3529_ethash_test.go @@ -1,16 +1,12 @@ -package core +package eip3529tests import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) @@ -26,7 +22,7 @@ func preLondonConfig() *params.ChainConfig { return &config } -func TestSelfDestructGasPreEIP3529(t *testing.T) { +func TestSelfDestructGasPreLondon(t *testing.T) { bytecode := []byte{ byte(vm.PC), byte(vm.SELFDESTRUCT), @@ -36,10 +32,10 @@ func TestSelfDestructGasPreEIP3529(t *testing.T) { // The refund of 24000 gas (i.e. params.SelfdestructRefundGas) is not applied since refunds pre-EIP3529 are // capped to half of the transaction's gas. expectedGasUsed := (params.TxGas + vm.GasQuickStep + params.ColdAccountAccessCostEIP2929 + params.SelfdestructGasEIP150) / 2 - testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreModifyGasPreEIP3529(t *testing.T) { +func TestSstoreModifyGasPreLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x1, // location @@ -53,10 +49,10 @@ func TestSstoreModifyGasPreEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) // i.e. no refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) + TestGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) } -func TestSstoreClearGasPreEIP3529(t *testing.T) { +func TestSstoreClearGasPreLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x0, // value byte(vm.PUSH1), 0x1, // location @@ -71,10 +67,10 @@ func TestSstoreClearGasPreEIP3529(t *testing.T) { // Expected gas is (intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) ) / 2 // The refund of params.SstoreClearsScheduleRefundEIP2200 is not applied because of the refund cap to half the gas cost. expectedGasUsage := (params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929)) / 2 - testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) + TestGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) } -func TestSstoreGasPreEIP3529(t *testing.T) { +func TestSstoreGasPreLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x3, // location @@ -83,10 +79,10 @@ func TestSstoreGasPreEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 - testGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, preLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSelfDestructGasPostEIP3529(t *testing.T) { +func TestSelfDestructGasPostLondon(t *testing.T) { bytecode := []byte{ byte(vm.PC), byte(vm.SELFDESTRUCT), @@ -94,10 +90,10 @@ func TestSelfDestructGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + pc + cold load (due to legacy tx) + SelfDestructGas // i.e. No refund expectedGasUsed := params.TxGas + vm.GasQuickStep + params.ColdAccountAccessCostEIP2929 + params.SelfdestructGasEIP150 - testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreGasPostEIP3529(t *testing.T) { +func TestSstoreGasPostLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x3, // location @@ -106,10 +102,10 @@ func TestSstoreGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 - testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreModifyGasPostEIP3529(t *testing.T) { +func TestSstoreModifyGasPostLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x1, // location @@ -123,10 +119,10 @@ func TestSstoreModifyGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) + TestGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) } -func TestSstoreClearGasPostEIP3529(t *testing.T) { +func TestSstoreClearGasPostLondon(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x0, // value byte(vm.PUSH1), 0x1, // location @@ -140,65 +136,5 @@ func TestSstoreClearGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) - sstoreClearGasRefund expectedGasUsage := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - params.SstoreClearsScheduleRefundEIP3529 - testGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) -} - -// Test the gas used by running a transaction sent to a smart contract with given bytecode and storage. -func testGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Engine, bytecode []byte, initialStorage map[common.Hash]common.Hash, initialGas, expectedGasUsed uint64) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - - // Generate a canonical chain to act as the main dataset - db = rawdb.NewMemoryDatabase() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - balanceBefore = big.NewInt(1000000000000000) - gspec = &Genesis{ - Config: config, - Alloc: GenesisAlloc{ - address: {Balance: balanceBefore}, - aa: { - Code: bytecode, - Storage: initialStorage, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - genesis = gspec.MustCommit(db) - ) - - blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - - // One transaction to 0xAAAA - signer := types.LatestSigner(gspec.Config) - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: 0, - To: &aa, - Gas: initialGas, - GasPrice: newGwei(5), - }) - b.AddTx(tx) - }) - - // Import the canonical chain - diskdb := rawdb.NewMemoryDatabase() - gspec.MustCommit(diskdb) - - chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block := chain.GetBlockByNumber(1) - - if block.GasUsed() != expectedGasUsed { - t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGasUsed, block.GasUsed()) - } + TestGasUsage(t, postLondonConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) } diff --git a/core/parlia_tests/blockchain_eip_3529_test.go b/core/eip3529tests/eip3529_parlia_test.go similarity index 58% rename from core/parlia_tests/blockchain_eip_3529_test.go rename to core/eip3529tests/eip3529_parlia_test.go index 7270ba39c3..f759a8f880 100644 --- a/core/parlia_tests/blockchain_eip_3529_test.go +++ b/core/eip3529tests/eip3529_parlia_test.go @@ -1,24 +1,14 @@ -package parlia_tests +package eip3529tests import ( - "math/big" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) -func newGwei(n int64) *big.Int { - return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei)) -} - func postHertzConfig() *params.ChainConfig { config := *params.ParliaTestChainConfig return &config @@ -32,7 +22,7 @@ func preHertzConfig() *params.ChainConfig { return &config } -func TestSelfDestructGasPreEIP3529(t *testing.T) { +func TestSelfDestructGasPreHertz(t *testing.T) { bytecode := []byte{ byte(vm.PC), byte(vm.SELFDESTRUCT), @@ -42,10 +32,10 @@ func TestSelfDestructGasPreEIP3529(t *testing.T) { // The refund of 24000 gas (i.e. params.SelfdestructRefundGas) is not applied since refunds pre-EIP3529 are // capped to half of the transaction's gas. expectedGasUsed := (params.TxGas + vm.GasQuickStep + params.SelfdestructGasEIP150) / 2 - testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreClearGasPreEIP3529(t *testing.T) { +func TestSstoreClearGasPreHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x0, // value byte(vm.PUSH1), 0x1, // location @@ -60,10 +50,10 @@ func TestSstoreClearGasPreEIP3529(t *testing.T) { // Expected gas is (intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) ) / 2 // The refund of params.SstoreClearsScheduleRefundEIP2200 is not applied because of the refund cap to half the gas cost. expectedGasUsage := (params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200) / 2 - testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) + TestGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) } -func TestSstoreModifyGasPreEIP3529(t *testing.T) { +func TestSstoreModifyGasPreHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x1, // location @@ -77,10 +67,10 @@ func TestSstoreModifyGasPreEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) // i.e. no refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 - testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) + TestGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) } -func TestSstoreGasPreEIP3529(t *testing.T) { +func TestSstoreGasPreHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x3, // location @@ -89,10 +79,10 @@ func TestSstoreGasPreEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + SstoreGas // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreSetGasEIP2200 - testGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, preHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSelfDestructGasPostEIP3529(t *testing.T) { +func TestSelfDestructGasPostHertz(t *testing.T) { bytecode := []byte{ byte(vm.PC), byte(vm.SELFDESTRUCT), @@ -100,10 +90,10 @@ func TestSelfDestructGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + pc + cold load (due to legacy tx) + SelfDestructGas // i.e. No refund expectedGasUsed := params.TxGas + vm.GasQuickStep + params.ColdAccountAccessCostEIP2929 + params.SelfdestructGasEIP150 - testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreGasPostEIP3529(t *testing.T) { +func TestSstoreGasPostHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x3, // location @@ -112,10 +102,10 @@ func TestSstoreGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreGas // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.ColdSloadCostEIP2929 + params.SstoreSetGasEIP2200 - testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) + TestGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, nil, 60_000, expectedGasUsed) } -func TestSstoreModifyGasPostEIP3529(t *testing.T) { +func TestSstoreModifyGasPostHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x3, // value byte(vm.PUSH1), 0x1, // location @@ -129,10 +119,10 @@ func TestSstoreModifyGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + cold load (due to legacy tx) + SstoreReset (a->b such that a!=0) // i.e. No refund expectedGasUsed := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 - testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) + TestGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsed) } -func TestSstoreClearGasPostEIP3529(t *testing.T) { +func TestSstoreClearGasPostHertz(t *testing.T) { bytecode := []byte{ byte(vm.PUSH1), 0x0, // value byte(vm.PUSH1), 0x1, // location @@ -146,65 +136,5 @@ func TestSstoreClearGasPostEIP3529(t *testing.T) { // Expected gas is intrinsic + 2*pushGas + SstoreReset (a->b such that a!=0) - sstoreClearGasRefund expectedGasUsage := params.TxGas + 2*vm.GasFastestStep + params.SstoreResetGasEIP2200 - params.SstoreClearsScheduleRefundEIP3529 - testGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) -} - -// Test the gas used by running a transaction sent to a smart contract with given bytecode and storage. -func testGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Engine, bytecode []byte, initialStorage map[common.Hash]common.Hash, initialGas, expectedGasUsed uint64) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - - // Generate a canonical chain to act as the main dataset - db = rawdb.NewMemoryDatabase() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - balanceBefore = big.NewInt(1000000000000000) - gspec = &core.Genesis{ - Config: config, - Alloc: core.GenesisAlloc{ - address: {Balance: balanceBefore}, - aa: { - Code: bytecode, - Storage: initialStorage, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - genesis = gspec.MustCommit(db) - ) - - blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) { - b.SetCoinbase(common.Address{1}) - - // One transaction to 0xAAAA - signer := types.LatestSigner(gspec.Config) - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: 0, - To: &aa, - Gas: initialGas, - GasPrice: newGwei(5), - }) - b.AddTx(tx) - }) - - // Import the canonical chain - diskdb := rawdb.NewMemoryDatabase() - gspec.MustCommit(diskdb) - - chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block := chain.GetBlockByNumber(1) - - if block.GasUsed() != expectedGasUsed { - t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGasUsed, block.GasUsed()) - } + TestGasUsage(t, postHertzConfig(), ethash.NewFaker(), bytecode, initialStorage, 60_000, expectedGasUsage) } diff --git a/core/eip3529tests/eip3529_test_util.go b/core/eip3529tests/eip3529_test_util.go new file mode 100644 index 0000000000..2ca1ebf777 --- /dev/null +++ b/core/eip3529tests/eip3529_test_util.go @@ -0,0 +1,79 @@ +package eip3529tests + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +func newGwei(n int64) *big.Int { + return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei)) +} + +// Test the gas used by running a transaction sent to a smart contract with given bytecode and storage. +func TestGasUsage(t *testing.T, config *params.ChainConfig, engine consensus.Engine, bytecode []byte, initialStorage map[common.Hash]common.Hash, initialGas, expectedGasUsed uint64) { + var ( + aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") + + // Generate a canonical chain to act as the main dataset + db = rawdb.NewMemoryDatabase() + + // A sender who makes transactions, has some funds + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + balanceBefore = big.NewInt(1000000000000000) + gspec = &core.Genesis{ + Config: config, + Alloc: core.GenesisAlloc{ + address: {Balance: balanceBefore}, + aa: { + Code: bytecode, + Storage: initialStorage, + Nonce: 0, + Balance: big.NewInt(0), + }, + }, + } + genesis = gspec.MustCommit(db) + ) + + blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) { + b.SetCoinbase(common.Address{1}) + + // One transaction to 0xAAAA + signer := types.LatestSigner(gspec.Config) + tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ + Nonce: 0, + To: &aa, + Gas: initialGas, + GasPrice: newGwei(5), + }) + b.AddTx(tx) + }) + + // Import the canonical chain + diskdb := rawdb.NewMemoryDatabase() + gspec.MustCommit(diskdb) + + chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + if n, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", n, err) + } + + block := chain.GetBlockByNumber(1) + + if block.GasUsed() != expectedGasUsed { + t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGasUsed, block.GasUsed()) + } +}