From d74666941da7f1eed1dbc748e674a1886d657ae7 Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 12 May 2023 14:24:19 +0800 Subject: [PATCH 1/6] feature: Enable Berlin EIPs Enable Berlin EIPs by including the BerlinBlock in BSCChainConfig This enable following Berlin EIPs into the BSC: EIP-2565: ModExp Gas Cost EIP-2929: Gas cost increases for state access opcodes EIP-2718: Typed Transaction Envelope EIP-2930: Optional access lists --- params/config.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/params/config.go b/params/config.go index 9883968446..b3cd1a7be6 100644 --- a/params/config.go +++ b/params/config.go @@ -195,6 +195,9 @@ var ( LubanBlock: nil, PlatoBlock: nil, + // TODO modify blockNumber to enable Berlin EIPs after the block. + BerlinBlock: nil, + Parlia: &ParliaConfig{ Period: 3, Epoch: 200, From 04fd80642eaacab49b32437461614458f44ae76f Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 12 May 2023 14:42:52 +0800 Subject: [PATCH 2/6] fix: golang-lint error --- params/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/config.go b/params/config.go index b3cd1a7be6..fe797ac271 100644 --- a/params/config.go +++ b/params/config.go @@ -195,7 +195,7 @@ var ( LubanBlock: nil, PlatoBlock: nil, - // TODO modify blockNumber to enable Berlin EIPs after the block. + // TODO modify blockNumber to enable Berlin EIPs after the block. BerlinBlock: nil, Parlia: &ParliaConfig{ From fa885d29f5e6be5fbcc94021db6f5349de4033b0 Mon Sep 17 00:00:00 2001 From: Sunny Date: Mon, 15 May 2023 18:25:57 +0800 Subject: [PATCH 3/6] feature: introduce HertzBlock --- eth/gasprice/gasprice_test.go | 1 + eth/handler_eth_test.go | 1 + params/config.go | 35 ++++++++++++++++++++++++++++------- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 2820cc683d..f2a0eb68fd 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -138,6 +138,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke config.GibbsBlock = nil config.LubanBlock = nil config.PlatoBlock = nil + config.HertzBlock = nil engine := ethash.NewFaker() db := rawdb.NewMemoryDatabase() genesis, err := gspec.Commit(db) diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 0144332e1c..48b487c874 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -110,6 +110,7 @@ func testForkIDSplit(t *testing.T, protocol uint) { MoranBlock: big.NewInt(5), LubanBlock: big.NewInt(6), PlatoBlock: big.NewInt(6), + HertzBlock: big.NewInt(7), } dbNoFork = rawdb.NewMemoryDatabase() dbProFork = rawdb.NewMemoryDatabase() diff --git a/params/config.go b/params/config.go index fe797ac271..78512600b6 100644 --- a/params/config.go +++ b/params/config.go @@ -194,9 +194,8 @@ var ( // TODO Caution !!! it should be very careful !!! LubanBlock: nil, PlatoBlock: nil, - - // TODO modify blockNumber to enable Berlin EIPs after the block. - BerlinBlock: nil, + // TODO modify blockNumber, this block should enable Berlin and London EIPs. + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -229,6 +228,7 @@ var ( // TODO Caution !!! it should be very careful !!! LubanBlock: big.NewInt(29295050), PlatoBlock: big.NewInt(29861024), + HertzBlock: big.NewInt(0), Parlia: &ParliaConfig{ Period: 3, @@ -260,6 +260,7 @@ var ( // TODO LubanBlock: nil, PlatoBlock: nil, + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -273,16 +274,16 @@ var ( // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil} TestRules = TestChainConfig.Rules(new(big.Int), false) ) @@ -381,6 +382,7 @@ type ChainConfig struct { PlanckBlock *big.Int `json:"planckBlock,omitempty" toml:",omitempty"` // planckBlock switch block (nil = no fork, 0 = already activated) LubanBlock *big.Int `json:"lubanBlock,omitempty" toml:",omitempty"` // lubanBlock switch block (nil = no fork, 0 = already activated) PlatoBlock *big.Int `json:"platoBlock,omitempty" toml:",omitempty"` // platoBlock switch block (nil = no fork, 0 = already activated) + HertzBlock *big.Int `json:"hertzBlock,omitempty" toml:",omitempty"` // hertzBlock switch block (nil = no fork, 0 = already activated) // Various consensus engines Ethash *EthashConfig `json:"ethash,omitempty" toml:",omitempty"` @@ -432,7 +434,7 @@ func (c *ChainConfig) String() string { engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Engine: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Engine: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -462,6 +464,7 @@ func (c *ChainConfig) String() string { c.PlanckBlock, c.LubanBlock, c.PlatoBlock, + c.HertzBlock, engine, ) } @@ -571,6 +574,16 @@ func (c *ChainConfig) IsOnPlato(num *big.Int) bool { return configNumEqual(c.PlatoBlock, num) } +// IsHertz returns whether num is either equal to the second fast finality fork block or greater. +func (c *ChainConfig) IsHertz(num *big.Int) bool { + return isForked(c.HertzBlock, num) +} + +// IsOnHertz returns whether num is equal to the second fast finality fork block. +func (c *ChainConfig) IsOnHertz(num *big.Int) bool { + return configNumEqual(c.HertzBlock, num) +} + // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater. func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool { return isForked(c.MuirGlacierBlock, num) @@ -590,6 +603,10 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { // IsBerlin returns whether num is either equal to the Berlin fork block or greater. func (c *ChainConfig) IsBerlin(num *big.Int) bool { + // Check if it is Hertz, which works on BSC + if c.IsHertz(num) { + return true + } return isForked(c.BerlinBlock, num) } @@ -679,6 +696,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "gibbsBlock", block: c.GibbsBlock}, {name: "lubanBlock", block: c.LubanBlock}, {name: "platoBlock", block: c.PlatoBlock}, + {name: "hertzBlock", block: c.HertzBlock}, } { if lastFork.name != "" { // Next one must be higher number @@ -784,6 +802,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi if isForkIncompatible(c.PlatoBlock, newcfg.PlatoBlock, head) { return newCompatError("plato fork block", c.PlatoBlock, newcfg.PlatoBlock) } + if isForkIncompatible(c.HertzBlock, newcfg.HertzBlock, head) { + return newCompatError("hartz fork block", c.HertzBlock, newcfg.HertzBlock) + } return nil } From 67da3166500b6d8ad79f9a6155bc5660922c1483 Mon Sep 17 00:00:00 2001 From: Sunny Date: Tue, 16 May 2023 10:03:57 +0800 Subject: [PATCH 4/6] fix: fix serveral errors of typo and wrong comments --- params/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/config.go b/params/config.go index 78512600b6..978700fff2 100644 --- a/params/config.go +++ b/params/config.go @@ -228,7 +228,7 @@ var ( // TODO Caution !!! it should be very careful !!! LubanBlock: big.NewInt(29295050), PlatoBlock: big.NewInt(29861024), - HertzBlock: big.NewInt(0), + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -574,12 +574,12 @@ func (c *ChainConfig) IsOnPlato(num *big.Int) bool { return configNumEqual(c.PlatoBlock, num) } -// IsHertz returns whether num is either equal to the second fast finality fork block or greater. +// IsHertz returns whether num is either equal to the block of enabling Berlin EIPs or greater. func (c *ChainConfig) IsHertz(num *big.Int) bool { return isForked(c.HertzBlock, num) } -// IsOnHertz returns whether num is equal to the second fast finality fork block. +// IsOnHertz returns whether num is equal to the fork block of enabling Berlin EIPs. func (c *ChainConfig) IsOnHertz(num *big.Int) bool { return configNumEqual(c.HertzBlock, num) } @@ -803,7 +803,7 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi return newCompatError("plato fork block", c.PlatoBlock, newcfg.PlatoBlock) } if isForkIncompatible(c.HertzBlock, newcfg.HertzBlock, head) { - return newCompatError("hartz fork block", c.HertzBlock, newcfg.HertzBlock) + return newCompatError("hertz fork block", c.HertzBlock, newcfg.HertzBlock) } return nil } From 56608fea0159e1b71954f7bea17f81a8e78c3150 Mon Sep 17 00:00:00 2001 From: Sunny Date: Wed, 17 May 2023 16:09:00 +0800 Subject: [PATCH 5/6] fix: add Hertz precomile contracts --- core/vm/contracts.go | 25 +++++++++++++++++++++++++ core/vm/evm.go | 2 ++ params/config.go | 2 ++ 3 files changed, 29 insertions(+) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 3132fbd95f..1958a88ba5 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -179,6 +179,25 @@ var PrecompiledContractsPlato = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, } +// PrecompiledContractsHertz contains the default set of pre-compiled Ethereum +// contracts used in the Hertz release. +var PrecompiledContractsHertz = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + + common.BytesToAddress([]byte{100}): &tmHeaderValidate{}, + common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{}, + common.BytesToAddress([]byte{102}): &blsSignatureVerify{}, + common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, +} + // PrecompiledContractsBLS contains the set of pre-compiled Ethereum // contracts specified in EIP-2537. These are exported for testing purposes. var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ @@ -194,6 +213,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ } var ( + PrecompiledAddressesHertz []common.Address PrecompiledAddressesPlato []common.Address PrecompiledAddressesLuban []common.Address PrecompiledAddressesPlanck []common.Address @@ -233,11 +253,16 @@ func init() { for k := range PrecompiledContractsPlato { PrecompiledAddressesPlato = append(PrecompiledAddressesPlato, k) } + for k := range PrecompiledContractsHertz { + PrecompiledAddressesHertz = append(PrecompiledAddressesHertz, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsHertz: + return PrecompiledAddressesHertz case rules.IsPlato: return PrecompiledAddressesPlato case rules.IsLuban: diff --git a/core/vm/evm.go b/core/vm/evm.go index ae33238105..1d2beff18c 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -51,6 +51,8 @@ type ( func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { + case evm.chainRules.IsHertz: + precompiles = PrecompiledContractsHertz case evm.chainRules.IsPlato: precompiles = PrecompiledContractsPlato case evm.chainRules.IsLuban: diff --git a/params/config.go b/params/config.go index 978700fff2..20484c5738 100644 --- a/params/config.go +++ b/params/config.go @@ -879,6 +879,7 @@ type Rules struct { IsPlanck bool IsLuban bool IsPlato bool + IsHertz bool } // Rules ensures c's ChainID is not nil. @@ -905,5 +906,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules { IsPlanck: c.IsPlanck(num), IsLuban: c.IsLuban(num), IsPlato: c.IsPlato(num), + IsHertz: c.IsHertz(num), } } From d77140f42ad25ebeef6b0adc2e1d1c8e0d2470d5 Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 19 May 2023 18:15:17 +0800 Subject: [PATCH 6/6] fix: separate Berlin and Hertz block in config --- params/config.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/params/config.go b/params/config.go index 20484c5738..5cd772c8d0 100644 --- a/params/config.go +++ b/params/config.go @@ -194,8 +194,9 @@ var ( // TODO Caution !!! it should be very careful !!! LubanBlock: nil, PlatoBlock: nil, - // TODO modify blockNumber, this block should enable Berlin and London EIPs. - HertzBlock: nil, + // TODO modify blockNumber, make sure the Hertz block number is equal to BerlinBlock for enabling Berlin EIPs + BerlinBlock: nil, + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -226,9 +227,10 @@ var ( // 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(29295050), - PlatoBlock: big.NewInt(29861024), - HertzBlock: nil, + LubanBlock: big.NewInt(29295050), + PlatoBlock: big.NewInt(29861024), + BerlinBlock: nil, + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -258,9 +260,10 @@ var ( PlanckBlock: nil, // TODO - LubanBlock: nil, - PlatoBlock: nil, - HertzBlock: nil, + LubanBlock: nil, + PlatoBlock: nil, + BerlinBlock: nil, + HertzBlock: nil, Parlia: &ParliaConfig{ Period: 3, @@ -603,10 +606,6 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { // IsBerlin returns whether num is either equal to the Berlin fork block or greater. func (c *ChainConfig) IsBerlin(num *big.Int) bool { - // Check if it is Hertz, which works on BSC - if c.IsHertz(num) { - return true - } return isForked(c.BerlinBlock, num) }