diff --git a/builder/files/genesis-mainnet-v1.json b/builder/files/genesis-mainnet-v1.json index d3f0d02206..a5b96140ca 100644 --- a/builder/files/genesis-mainnet-v1.json +++ b/builder/files/genesis-mainnet-v1.json @@ -15,14 +15,17 @@ "londonBlock": 23850000, "bor": { "jaipurBlock": 23850000, + "delhiBlock": 36499456, "period": { "0": 2 }, "producerDelay": { - "0": 6 + "0": 6, + "36499456": 4 }, "sprint": { - "0": 64 + "0": 64, + "36499456": 16 }, "backupMultiplier": { "0": 2 diff --git a/builder/files/genesis-testnet-v4.json b/builder/files/genesis-testnet-v4.json index 8a0af45088..52ac2645f7 100644 --- a/builder/files/genesis-testnet-v4.json +++ b/builder/files/genesis-testnet-v4.json @@ -15,15 +15,18 @@ "londonBlock": 22640000, "bor": { "jaipurBlock": 22770000, + "delhiBlock": 29389056, "period": { "0": 2, "25275000": 5 }, "producerDelay": { - "0": 6 + "0": 6, + "29389056": 4 }, "sprint": { - "0": 64 + "0": 64, + "29389056": 16 }, "backupMultiplier": { "0": 2, diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 3cc8c68ec2..1b4ddec45d 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -169,7 +169,7 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) { header.Nonce, } - if c.IsJaipur(header.Number.Uint64()) { + if c.IsJaipur(header.Number) { if header.BaseFee != nil { enc = append(enc, header.BaseFee) } diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index fc2d59520d..9ca361a18d 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -125,20 +125,20 @@ func TestEncodeSigHeaderJaipur(t *testing.T) { ) // Jaipur NOT enabled and BaseFee not set - hash := SealHash(h, ¶ms.BorConfig{JaipurBlock: 10}) + hash := SealHash(h, ¶ms.BorConfig{JaipurBlock: big.NewInt(10)}) require.Equal(t, hash, hashWithoutBaseFee) // Jaipur enabled (Jaipur=0) and BaseFee not set - hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 0}) + hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: common.Big0}) require.Equal(t, hash, hashWithoutBaseFee) h.BaseFee = big.NewInt(2) // Jaipur enabled (Jaipur=Header block) and BaseFee set - hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 1}) + hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: common.Big1}) require.Equal(t, hash, hashWithBaseFee) // Jaipur NOT enabled and BaseFee set - hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: 10}) + hash = SealHash(h, ¶ms.BorConfig{JaipurBlock: big.NewInt(10)}) require.Equal(t, hash, hashWithoutBaseFee) } diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index 8fca0fdc70..193a5b84e2 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -59,9 +59,10 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { } var ( - parentGasTarget = parent.GasLimit / params.ElasticityMultiplier - parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget) - baseFeeChangeDenominator = new(big.Int).SetUint64(params.BaseFeeChangeDenominator) + parentGasTarget = parent.GasLimit / params.ElasticityMultiplier + parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget) + baseFeeChangeDenominatorUint64 = params.BaseFeeChangeDenominator(config.Bor, parent.Number) + baseFeeChangeDenominator = new(big.Int).SetUint64(baseFeeChangeDenominatorUint64) ) // If the parent gasUsed is the same as the target, the baseFee remains unchanged. if parent.GasUsed == parentGasTarget { diff --git a/consensus/misc/eip1559_test.go b/consensus/misc/eip1559_test.go index 23cd9023de..aba95d8005 100644 --- a/consensus/misc/eip1559_test.go +++ b/consensus/misc/eip1559_test.go @@ -20,7 +20,6 @@ import ( "math/big" "testing" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) @@ -47,12 +46,14 @@ func copyConfig(original *params.ChainConfig) *params.ChainConfig { TerminalTotalDifficulty: original.TerminalTotalDifficulty, Ethash: original.Ethash, Clique: original.Clique, + Bor: original.Bor, } } func config() *params.ChainConfig { config := copyConfig(params.TestChainConfig) config.LondonBlock = big.NewInt(5) + config.Bor.DelhiBlock = big.NewInt(8) return config } @@ -108,6 +109,8 @@ func TestBlockGasLimits(t *testing.T) { // TestCalcBaseFee assumes all blocks are 1559-blocks func TestCalcBaseFee(t *testing.T) { + t.Parallel() + tests := []struct { parentBaseFee int64 parentGasLimit uint64 @@ -117,10 +120,12 @@ func TestCalcBaseFee(t *testing.T) { {params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target {params.InitialBaseFee, 20000000, 9000000, 987500000}, // usage below target {params.InitialBaseFee, 20000000, 11000000, 1012500000}, // usage above target + {params.InitialBaseFee, 20000000, 20000000, 1125000000}, // usage full + {params.InitialBaseFee, 20000000, 0, 875000000}, // usage 0 } for i, test := range tests { parent := &types.Header{ - Number: common.Big32, + Number: big.NewInt(6), GasLimit: test.parentGasLimit, GasUsed: test.parentGasUsed, BaseFee: big.NewInt(test.parentBaseFee), @@ -130,3 +135,38 @@ func TestCalcBaseFee(t *testing.T) { } } } + +// TestCalcBaseFee assumes all blocks are 1559-blocks post Delhi Hard Fork +func TestCalcBaseFeeDelhi(t *testing.T) { + t.Parallel() + + testConfig := copyConfig(config()) + + // Test Delhi Hard Fork + // Hard fork kicks in at block 8 + + tests := []struct { + parentBaseFee int64 + parentGasLimit uint64 + parentGasUsed uint64 + expectedBaseFee int64 + }{ + {params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target + {params.InitialBaseFee, 20000000, 9000000, 993750000}, // usage below target + {params.InitialBaseFee, 20000000, 11000000, 1006250000}, // usage above target + {params.InitialBaseFee, 20000000, 20000000, 1062500000}, // usage full + {params.InitialBaseFee, 20000000, 0, 937500000}, // usage 0 + + } + for i, test := range tests { + parent := &types.Header{ + Number: big.NewInt(8), + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: big.NewInt(test.parentBaseFee), + } + if have, want := CalcBaseFee(testConfig, parent), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 { + t.Errorf("test %d: have %d want %d, ", i, have, want) + } + } +} diff --git a/internal/cli/server/chains/mainnet.go b/internal/cli/server/chains/mainnet.go index 20ff8bc9f2..8b75039f1a 100644 --- a/internal/cli/server/chains/mainnet.go +++ b/internal/cli/server/chains/mainnet.go @@ -29,15 +29,18 @@ var mainnetBor = &Chain{ BerlinBlock: big.NewInt(14750000), LondonBlock: big.NewInt(23850000), Bor: ¶ms.BorConfig{ - JaipurBlock: 23850000, + JaipurBlock: big.NewInt(23850000), + DelhiBlock: big.NewInt(36499456), Period: map[string]uint64{ "0": 2, }, ProducerDelay: map[string]uint64{ - "0": 6, + "0": 6, + "36499456": 4, }, Sprint: map[string]uint64{ - "0": 64, + "0": 64, + "36499456": 16, }, BackupMultiplier: map[string]uint64{ "0": 2, diff --git a/internal/cli/server/chains/mumbai.go b/internal/cli/server/chains/mumbai.go index 9015e1b82b..e195f5e584 100644 --- a/internal/cli/server/chains/mumbai.go +++ b/internal/cli/server/chains/mumbai.go @@ -29,16 +29,19 @@ var mumbaiTestnet = &Chain{ BerlinBlock: big.NewInt(13996000), LondonBlock: big.NewInt(22640000), Bor: ¶ms.BorConfig{ - JaipurBlock: 22770000, + JaipurBlock: big.NewInt(22770000), + DelhiBlock: big.NewInt(29389056), Period: map[string]uint64{ "0": 2, "25275000": 5, }, ProducerDelay: map[string]uint64{ - "0": 6, + "0": 6, + "29389056": 4, }, Sprint: map[string]uint64{ - "0": 64, + "0": 64, + "29389056": 16, }, BackupMultiplier: map[string]uint64{ "0": 2, diff --git a/internal/cli/server/chains/test_files/chain_legacy_test.json b/internal/cli/server/chains/test_files/chain_legacy_test.json index 69702c6ad6..bdea670388 100644 --- a/internal/cli/server/chains/test_files/chain_legacy_test.json +++ b/internal/cli/server/chains/test_files/chain_legacy_test.json @@ -19,10 +19,12 @@ "0": 2 }, "producerDelay": { - "0": 6 + "0": 6, + "29389056": 4 }, "sprint": { - "0": 64 + "0": 64, + "29389056": 16 }, "backupMultiplier": { "0": 2 @@ -41,7 +43,8 @@ "burntContract": { "22640000": "0x70bcA57F4579f58670aB2d18Ef16e02C17553C38" }, - "jaipurBlock": 22770000 + "jaipurBlock": 22770000, + "delhiBlock": 29389056 } }, "nonce": "0x0", diff --git a/internal/cli/server/chains/test_files/chain_test.json b/internal/cli/server/chains/test_files/chain_test.json index c8d9f6f4f8..8f61363a9b 100644 --- a/internal/cli/server/chains/test_files/chain_test.json +++ b/internal/cli/server/chains/test_files/chain_test.json @@ -21,10 +21,12 @@ "0":2 }, "producerDelay":{ - "0": 6 + "0": 6, + "29389056": 4 }, "sprint":{ - "0": 64 + "0": 64, + "29389056": 16 }, "backupMultiplier":{ "0":2 @@ -43,7 +45,8 @@ "burntContract":{ "22640000":"0x70bcA57F4579f58670aB2d18Ef16e02C17553C38" }, - "jaipurBlock":22770000 + "jaipurBlock":22770000, + "delhiBlock": 29389056 } }, "nonce":"0x0", diff --git a/params/config.go b/params/config.go index fe17f31bb0..6fac0e5a07 100644 --- a/params/config.go +++ b/params/config.go @@ -349,16 +349,19 @@ var ( BerlinBlock: big.NewInt(13996000), LondonBlock: big.NewInt(22640000), Bor: &BorConfig{ - JaipurBlock: 22770000, + JaipurBlock: big.NewInt(22770000), + DelhiBlock: big.NewInt(29389056), Period: map[string]uint64{ "0": 2, "25275000": 5, }, ProducerDelay: map[string]uint64{ - "0": 6, + "0": 6, + "29389056": 4, }, Sprint: map[string]uint64{ - "0": 64, + "0": 64, + "29389056": 16, }, BackupMultiplier: map[string]uint64{ "0": 2, @@ -398,15 +401,18 @@ var ( BerlinBlock: big.NewInt(14750000), LondonBlock: big.NewInt(23850000), Bor: &BorConfig{ - JaipurBlock: 23850000, + JaipurBlock: big.NewInt(23850000), + DelhiBlock: big.NewInt(36499456), Period: map[string]uint64{ "0": 2, }, ProducerDelay: map[string]uint64{ - "0": 6, + "0": 6, + "36499456": 4, }, Sprint: map[string]uint64{ - "0": 64, + "0": 64, + "36499456": 16, }, BackupMultiplier: map[string]uint64{ "0": 2, @@ -576,7 +582,8 @@ type BorConfig struct { OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count BlockAlloc map[string]interface{} `json:"blockAlloc"` BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork - JaipurBlock uint64 `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) + JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) + DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) } // String implements the stringer interface, returning the consensus engine details. @@ -600,8 +607,12 @@ func (c *BorConfig) CalculatePeriod(number uint64) uint64 { return c.calculateBorConfigHelper(c.Period, number) } -func (c *BorConfig) IsJaipur(number uint64) bool { - return number >= c.JaipurBlock +func (c *BorConfig) IsJaipur(number *big.Int) bool { + return isForked(c.JaipurBlock, number) +} + +func (c *BorConfig) IsDelhi(number *big.Int) bool { + return isForked(c.DelhiBlock, number) } func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uint64) uint64 { diff --git a/params/protocol_params.go b/params/protocol_params.go index 5f154597a7..d468af5d3c 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -119,9 +119,11 @@ const ( // Introduced in Tangerine Whistle (Eip 150) CreateBySelfdestructGas uint64 = 25000 - BaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks. - ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. - InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks. + BaseFeeChangeDenominatorPreDelhi = 8 // Bounds the amount the base fee can change between blocks before Delhi Hard Fork. + BaseFeeChangeDenominatorPostDelhi = 16 // Bounds the amount the base fee can change between blocks after Delhi Hard Fork. + + ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. + InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks. MaxCodeSize = 24576 // Maximum bytecode to permit for a contract @@ -168,3 +170,11 @@ var ( MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. ) + +func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 { + if borConfig.IsDelhi(number) { + return BaseFeeChangeDenominatorPostDelhi + } else { + return BaseFeeChangeDenominatorPreDelhi + } +} diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index 0b339b04d1..d059956e6a 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -1073,11 +1073,11 @@ func TestJaipurFork(t *testing.T) { block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor, nil, res.Result.ValidatorSet.Validators) insertNewBlock(t, chain, block) - if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock-1 { + if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock.Uint64()-1 { require.Equal(t, testSealHash(block.Header(), init.genesis.Config.Bor), bor.SealHash(block.Header(), init.genesis.Config.Bor)) } - if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock { + if block.Number().Uint64() == init.genesis.Config.Bor.JaipurBlock.Uint64() { require.Equal(t, testSealHash(block.Header(), init.genesis.Config.Bor), bor.SealHash(block.Header(), init.genesis.Config.Bor)) } } @@ -1109,7 +1109,7 @@ func testEncodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) header.MixDigest, header.Nonce, } - if c.IsJaipur(header.Number.Uint64()) { + if c.IsJaipur(header.Number) { if header.BaseFee != nil { enc = append(enc, header.BaseFee) } diff --git a/tests/bor/testdata/genesis.json b/tests/bor/testdata/genesis.json index 87a7ea0b98..cbae055a0a 100644 --- a/tests/bor/testdata/genesis.json +++ b/tests/bor/testdata/genesis.json @@ -15,6 +15,7 @@ "londonBlock": 1, "bor": { "jaipurBlock": 2, + "delhiBlock" :3, "period": { "0": 1 }, diff --git a/tests/bor/testdata/genesis_21val.json b/tests/bor/testdata/genesis_21val.json index 2f67e56073..e2c604b1dc 100644 --- a/tests/bor/testdata/genesis_21val.json +++ b/tests/bor/testdata/genesis_21val.json @@ -15,6 +15,7 @@ "londonBlock": 0, "bor": { "jaipurBlock": 0, + "delhiBlock" :0, "period": { "0": 1 }, diff --git a/tests/bor/testdata/genesis_2val.json b/tests/bor/testdata/genesis_2val.json index 4ff647dde4..5ce5fbcd4e 100644 --- a/tests/bor/testdata/genesis_2val.json +++ b/tests/bor/testdata/genesis_2val.json @@ -15,6 +15,7 @@ "londonBlock": 1, "bor": { "jaipurBlock": 2, + "delhiBlock" :3, "period": { "0": 1 }, diff --git a/tests/bor/testdata/genesis_7val.json b/tests/bor/testdata/genesis_7val.json index 7fd5d08057..97982a3deb 100644 --- a/tests/bor/testdata/genesis_7val.json +++ b/tests/bor/testdata/genesis_7val.json @@ -15,6 +15,7 @@ "londonBlock": 0, "bor": { "jaipurBlock": 0, + "delhiBlock" :0, "period": { "0": 1 }, diff --git a/tests/bor/testdata/genesis_sprint_length_change.json b/tests/bor/testdata/genesis_sprint_length_change.json index ce6a2cb5f4..cb6eb2a729 100644 --- a/tests/bor/testdata/genesis_sprint_length_change.json +++ b/tests/bor/testdata/genesis_sprint_length_change.json @@ -15,6 +15,7 @@ "londonBlock": 1, "bor": { "jaipurBlock": 2, + "delhiBlock" :3, "period": { "0": 1 },