From 3caec6f93eb1a2ea84f448bfe7aa80f95becda9a Mon Sep 17 00:00:00 2001 From: buddh0 Date: Fri, 3 Nov 2023 17:17:41 +0800 Subject: [PATCH] core: enable Shanghai EIPs --- consensus/misc/eip1559/eip1559.go | 44 ++++++++++++++++++++++++++++++- core/genesis.go | 2 +- core/vm/jump_table.go | 2 +- tests/block_test.go | 5 +++- tests/init_test.go | 13 ++++++--- tests/state_test.go | 2 ++ tests/state_test_util.go | 2 +- trie/triedb/pathdb/database.go | 2 +- 8 files changed, 63 insertions(+), 9 deletions(-) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 77f4e4dbaa..e87c5ab23b 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -21,6 +21,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) @@ -45,5 +47,45 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade // CalcBaseFee calculates the basefee of the header. func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { - return new(big.Int).SetUint64(params.InitialBaseFee) + if config.Parlia != nil { + return new(big.Int).SetUint64(params.InitialBaseFee) + } + + // If the current block is the first EIP-1559 block, return the InitialBaseFee. + if !config.IsLondon(parent.Number) { + return new(big.Int).SetUint64(params.InitialBaseFee) + } + + parentGasTarget := parent.GasLimit / config.ElasticityMultiplier() + // If the parent gasUsed is the same as the target, the baseFee remains unchanged. + if parent.GasUsed == parentGasTarget { + return new(big.Int).Set(parent.BaseFee) + } + + var ( + num = new(big.Int) + denom = new(big.Int) + ) + + if parent.GasUsed > parentGasTarget { + // If the parent block used more gas than its target, the baseFee should increase. + // max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) + num.SetUint64(parent.GasUsed - parentGasTarget) + num.Mul(num, parent.BaseFee) + num.Div(num, denom.SetUint64(parentGasTarget)) + num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) + baseFeeDelta := math.BigMax(num, common.Big1) + + return num.Add(parent.BaseFee, baseFeeDelta) + } else { + // Otherwise if the parent block used less gas than its target, the baseFee should decrease. + // max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) + num.SetUint64(parentGasTarget - parent.GasUsed) + num.Mul(num, parent.BaseFee) + num.Div(num, denom.SetUint64(parentGasTarget)) + num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) + baseFee := num.Sub(parent.BaseFee, num) + + return math.BigMax(baseFee, common.Big0) + } } diff --git a/core/genesis.go b/core/genesis.go index 8fa107ac66..1929805da6 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -534,7 +534,7 @@ func (g *Genesis) ToBlock() *types.Block { var withdrawals []*types.Withdrawal if conf := g.Config; conf != nil { num := big.NewInt(int64(g.Number)) - if conf.IsShanghai(num, g.Timestamp) { + if conf.Parlia == nil && conf.IsShanghai(num, g.Timestamp) { head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 702b186615..38a0a76539 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -90,7 +90,7 @@ func newCancunInstructionSet() JumpTable { } func newShanghaiInstructionSet() JumpTable { - instructionSet := newMergeInstructionSet() + instructionSet := newLondonInstructionSet() enable3855(&instructionSet) // PUSH0 instruction enable3860(&instructionSet) // Limit and meter initcode diff --git a/tests/block_test.go b/tests/block_test.go index ad522ad653..1989c26816 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -30,7 +30,7 @@ func TestBlockchain(t *testing.T) { // For speedier CI-runs, the line below can be uncommented, so those are skipped. // For now, in hardfork-times (Berlin), we run the tests both as StateTests and // as blockchain tests, since the latter also covers things like receipt root - bt.skipLoad(`^GeneralStateTests/`) + // bt.skipLoad(`^GeneralStateTests/`) // Skip random failures due to selfish mining test bt.skipLoad(`.*bcForgedTest/bcForkUncle\.json`) @@ -49,6 +49,9 @@ func TestBlockchain(t *testing.T) { // using 4.6 TGas bt.skipLoad(`.*randomStatetest94.json.*`) + bt.runonly(`^GeneralStateTests/Shanghai`) + bt.runonly(`^Pyspecs/shanghai/eip3.*`) + bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) { if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil)); err != nil { t.Errorf("test in hash mode without snapshotter failed: %v", err) diff --git a/tests/init_test.go b/tests/init_test.go index 7d8743efcc..46a0a86089 100644 --- a/tests/init_test.go +++ b/tests/init_test.go @@ -93,7 +93,7 @@ type testMatcher struct { failpat []testFailure skiploadpat []*regexp.Regexp slowpat []*regexp.Regexp - runonlylistpat *regexp.Regexp + runonlylistpat []*regexp.Regexp } type testConfig struct { @@ -127,7 +127,7 @@ func (tm *testMatcher) fails(pattern string, reason string) { } func (tm *testMatcher) runonly(pattern string) { - tm.runonlylistpat = regexp.MustCompile(pattern) + tm.runonlylistpat = append(tm.runonlylistpat, regexp.MustCompile(pattern)) } // config defines chain config for tests matching the pattern. @@ -220,7 +220,14 @@ func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest inte t.Skip(r) } if tm.runonlylistpat != nil { - if !tm.runonlylistpat.MatchString(name) { + match := false + for _, pat := range tm.runonlylistpat { + if pat.MatchString(name) { + match = true + break + } + } + if !match { t.Skip("Skipped by runonly") } } diff --git a/tests/state_test.go b/tests/state_test.go index 094dafcafd..1e8341f298 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -68,6 +68,8 @@ func TestState(t *testing.T) { st.fails(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`, "test has incorrect state root") st.fails(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`, "test has incorrect state root") + st.runonly(`^Shanghai`) + // For Istanbul, older tests were moved into LegacyTests for _, dir := range []string{ filepath.Join(baseDir, "EIPTests", "StateTests"), diff --git a/tests/state_test_util.go b/tests/state_test_util.go index c1d48edc21..d058fbf188 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -300,7 +300,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh // And _now_ get the state root root := statedb.IntermediateRoot(config.IsEIP158(block.Number())) statedb.SetExpectedStateRoot(root) - root, _, err = statedb.Commit(block.NumberU64(), nil) + root, _, _ = statedb.Commit(block.NumberU64(), nil) return triedb, snaps, statedb, root, err } diff --git a/trie/triedb/pathdb/database.go b/trie/triedb/pathdb/database.go index 167db6643d..2da9717984 100644 --- a/trie/triedb/pathdb/database.go +++ b/trie/triedb/pathdb/database.go @@ -172,7 +172,7 @@ func New(diskdb ethdb.Database, config *Config) *Database { // mechanism also ensures that at most one **non-readOnly** database // is opened at the same time to prevent accidental mutation. if ancient, err := diskdb.AncientDatadir(); err == nil && ancient != "" && !db.readOnly { - offset := uint64(0) //TODO(Nathan): just for passing compilation + offset := uint64(0) // differ from in block data, only metadata is used in state data freezer, err := rawdb.NewStateFreezer(ancient, false, offset) if err != nil { log.Crit("Failed to open state history freezer", "err", err)