Skip to content

Commit

Permalink
Merge pull request #1686 from bnb-chain/refactor-eip3529-tests
Browse files Browse the repository at this point in the history
eip3529tests: refactor tests
  • Loading branch information
Mister-EA authored Jun 12, 2023
2 parents a97f713 + b1fbb29 commit 4a467ec
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 168 deletions.
Original file line number Diff line number Diff line change
@@ -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"
)

Expand All @@ -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),
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -83,21 +79,21 @@ 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),
}
// 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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),
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -89,21 +79,21 @@ 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),
}
// 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
}
Loading

0 comments on commit 4a467ec

Please sign in to comment.