diff --git a/builder/files/genesis-mainnet-v1.json b/builder/files/genesis-mainnet-v1.json index 79c09c61c8..c5e19fdf77 100644 --- a/builder/files/genesis-mainnet-v1.json +++ b/builder/files/genesis-mainnet-v1.json @@ -23,13 +23,14 @@ "ahmedabadBlock": 62278656, "bhilaiBlock": 73440256, "rioBlock": 77414656, - "madhugiriBlock": 79783223, + "madhugiriBlock": 80084800, + "madhugiriProBlock": 80084800, "stateSyncConfirmationDelay": { "44934656": 128 }, "period": { "0": 2, - "79783223": 1 + "80084800": 1 }, "producerDelay": { "0": 6, @@ -43,7 +44,7 @@ "0": 2 }, "coinbase": { - "0": "0x0000000000000000000000000000000000000000", + "0": "0x0000000000000000000000000000000000000000", "77414656": "0x7Ee41D8A25641000661B1EF5E6AE8A00400466B0" }, "validatorContract": "0x0000000000000000000000000000000000001000", @@ -60,7 +61,11 @@ "14953856": 0 }, "overrideStateSyncRecordsInRange": [ - { "startBlock": 73812433, "endBlock": 73826700, "value": 0 } + { + "startBlock": 73812433, + "endBlock": 73826700, + "value": 0 + } ], "blockAlloc": { "22156660": { diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 71c35fdbb6..7b25a59f3f 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -186,15 +186,39 @@ var PrecompiledContractsMadhugiri = PrecompiledContracts{ common.BytesToAddress([]byte{0x11}): &bls12381MapG2{}, } +// PrecompiledContractsMadhugiriPro contains the set of pre-compiled Ethereum +// contracts used in the MadhugiriPro release (bor HF). +var PrecompiledContractsMadhugiriPro = PrecompiledContracts{ + common.BytesToAddress([]byte{0x01}): &ecrecover{}, + common.BytesToAddress([]byte{0x02}): &sha256hash{}, + common.BytesToAddress([]byte{0x03}): &ripemd160hash{}, + common.BytesToAddress([]byte{0x04}): &dataCopy{}, + common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true, eip7823: true, eip7883: true}, + common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{0x09}): &blake2F{}, + common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, + common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{}, + common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{}, + common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{}, + common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{}, + common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{}, + common.BytesToAddress([]byte{0x10}): &bls12381MapG1{}, + common.BytesToAddress([]byte{0x11}): &bls12381MapG2{}, + common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, +} + var ( - PrecompiledAddressesMadhugiri []common.Address - PrecompiledAddressesOsaka []common.Address - PrecompiledAddressesPrague []common.Address - PrecompiledAddressesCancun []common.Address - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesMadhugiriPro []common.Address + PrecompiledAddressesMadhugiri []common.Address + PrecompiledAddressesOsaka []common.Address + PrecompiledAddressesPrague []common.Address + PrecompiledAddressesCancun []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { @@ -225,10 +249,15 @@ func init() { for k := range PrecompiledContractsMadhugiri { PrecompiledAddressesMadhugiri = append(PrecompiledAddressesMadhugiri, k) } + for k := range PrecompiledContractsMadhugiriPro { + PrecompiledAddressesMadhugiriPro = append(PrecompiledAddressesMadhugiriPro, k) + } } func activePrecompiledContracts(rules params.Rules) PrecompiledContracts { switch { + case rules.IsMadhugiriPro: + return PrecompiledContractsMadhugiriPro case rules.IsMadhugiri: return PrecompiledContractsMadhugiri case rules.IsVerkle: @@ -258,6 +287,8 @@ func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts { // ActivePrecompiles returns the precompile addresses enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsMadhugiriPro: + return PrecompiledAddressesMadhugiriPro case rules.IsMadhugiri: return PrecompiledAddressesMadhugiri case rules.IsOsaka: diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 0392fb5a5f..e9996bf0d6 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -23,6 +23,7 @@ import ( "math" "math/big" "os" + "reflect" "testing" "time" @@ -458,3 +459,64 @@ func TestPrecompiledP256VerifyAlwaysAvailableInHFs(t *testing.T) { assert.Equal(t, &p256Verify{}, preCompiledContracts[precompiledP256VerifyAddress]) } } + +// If this test failed, it likely means a new HF were introduced and is very likely that PreCompiles got changed (by introducing new ones, changing olds ones or removing). +// Please follow the instructions here to properly handle this new HF +// +// 1. Make sure if p256Verify were properly set on this Hardfork, it was introduced by us in PIP-27 +// +// 2. Double check all the changes on the preCompiles of the current HF and the new one. +// You should also pay attention for any params changes like in &bigModExp{eip2565: true, eip7823: true, eip7883: true} +// Make sure all changes reflects the Ethereum's new proposals while reflecting the changes we did internally. Currently just PIP-27 +// +// 3. Check if Erigon reflects the exact same configuration for the PreCompiles, including also the same params for precompiles +// +// 4. Runs a e2e test which includes all the preCompiles in a single transaction. If a new preCompile were introduced, please reflect the new one on the tests +// The test must run on a multiclient network, including both Erigon and Bor. The test is available in our e2e repository. +// +// 5. After all checks done, you can increase insert the NewHF on the expected list to make the test pass +func TestReinforceMultiClientPreCompilesTest(t *testing.T) { + rulesType := reflect.TypeOf(params.Rules{}) + + // Extract actual field names + actual := make([]string, 0, rulesType.NumField()) + for i := 0; i < rulesType.NumField(); i++ { + actual = append(actual, rulesType.Field(i).Name) + } + + // Expected field names (in order) + expected := []string{ + "ChainID", + "IsHomestead", + "IsEIP150", + "IsEIP155", + "IsEIP158", + "IsEIP2929", + "IsEIP4762", + "IsByzantium", + "IsConstantinople", + "IsPetersburg", + "IsIstanbul", + "IsBerlin", + "IsLondon", + "IsMerge", + "IsShanghai", + "IsCancun", + "IsPrague", + "IsOsaka", + "IsVerkle", + "IsMadhugiri", + "IsMadhugiriPro", + } + + if len(actual) != len(expected) { + t.Fatalf("A new hardfork were detected. Please read and follow the instruction on the comment section of this test") + } + + // Compare names one-by-one for stability + for i := range expected { + if actual[i] != expected[i] { + t.Fatalf("A new hardfork were detected. Please read and follow the instruction on the comment section of this test") + } + } +} diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go index 4055d57e62..fee64996ac 100644 --- a/core/vm/jump_table_export.go +++ b/core/vm/jump_table_export.go @@ -28,6 +28,8 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) { switch { case rules.IsVerkle: return newCancunInstructionSet(), errors.New("verkle-fork not defined yet") + case rules.IsMadhugiriPro: + return newPragueInstructionSet(), errors.New("madhugiriPro-fork not defined yet") case rules.IsMadhugiri: return newPragueInstructionSet(), errors.New("madhugiri-fork not defined yet") case rules.IsOsaka: diff --git a/internal/cli/server/chains/amoy.go b/internal/cli/server/chains/amoy.go index a9a906b264..cacec69f15 100644 --- a/internal/cli/server/chains/amoy.go +++ b/internal/cli/server/chains/amoy.go @@ -30,13 +30,14 @@ var amoyTestnet = &Chain{ CancunBlock: big.NewInt(5423600), PragueBlock: big.NewInt(22765056), Bor: ¶ms.BorConfig{ - JaipurBlock: big.NewInt(73100), - DelhiBlock: big.NewInt(73100), - IndoreBlock: big.NewInt(73100), - AhmedabadBlock: big.NewInt(11865856), - BhilaiBlock: big.NewInt(22765056), - RioBlock: big.NewInt(26272256), - MadhugiriBlock: big.NewInt(28899616), + JaipurBlock: big.NewInt(73100), + DelhiBlock: big.NewInt(73100), + IndoreBlock: big.NewInt(73100), + AhmedabadBlock: big.NewInt(11865856), + BhilaiBlock: big.NewInt(22765056), + RioBlock: big.NewInt(26272256), + MadhugiriBlock: big.NewInt(28899616), + MadhugiriProBlock: big.NewInt(29287400), StateSyncConfirmationDelay: map[string]uint64{ "0": 128, }, diff --git a/internal/cli/server/chains/mainnet.go b/internal/cli/server/chains/mainnet.go index 960dcd7ee7..60aa6f7841 100644 --- a/internal/cli/server/chains/mainnet.go +++ b/internal/cli/server/chains/mainnet.go @@ -31,19 +31,20 @@ var mainnetBor = &Chain{ CancunBlock: big.NewInt(54876000), PragueBlock: big.NewInt(73440256), Bor: ¶ms.BorConfig{ - JaipurBlock: big.NewInt(23850000), - DelhiBlock: big.NewInt(38189056), - IndoreBlock: big.NewInt(44934656), - AhmedabadBlock: big.NewInt(62278656), - BhilaiBlock: big.NewInt(73440256), - RioBlock: big.NewInt(77414656), - MadhugiriBlock: big.NewInt(79783223), + JaipurBlock: big.NewInt(23850000), + DelhiBlock: big.NewInt(38189056), + IndoreBlock: big.NewInt(44934656), + AhmedabadBlock: big.NewInt(62278656), + BhilaiBlock: big.NewInt(73440256), + RioBlock: big.NewInt(77414656), + MadhugiriBlock: big.NewInt(80084800), + MadhugiriProBlock: big.NewInt(80084800), StateSyncConfirmationDelay: map[string]uint64{ "44934656": 128, }, Period: map[string]uint64{ "0": 2, - "79783223": 1, + "80084800": 1, }, ProducerDelay: map[string]uint64{ "0": 6, diff --git a/params/config.go b/params/config.go index b796985b6a..62347fe2d1 100644 --- a/params/config.go +++ b/params/config.go @@ -332,13 +332,14 @@ var ( CancunBlock: big.NewInt(5423600), PragueBlock: big.NewInt(22765056), Bor: &BorConfig{ - JaipurBlock: big.NewInt(73100), - DelhiBlock: big.NewInt(73100), - IndoreBlock: big.NewInt(73100), - AhmedabadBlock: big.NewInt(11865856), - BhilaiBlock: big.NewInt(22765056), - RioBlock: big.NewInt(26272256), - MadhugiriBlock: big.NewInt(28899616), + JaipurBlock: big.NewInt(73100), + DelhiBlock: big.NewInt(73100), + IndoreBlock: big.NewInt(73100), + AhmedabadBlock: big.NewInt(11865856), + BhilaiBlock: big.NewInt(22765056), + RioBlock: big.NewInt(26272256), + MadhugiriBlock: big.NewInt(28899616), + MadhugiriProBlock: big.NewInt(29287400), StateSyncConfirmationDelay: map[string]uint64{ "0": 128, }, @@ -414,20 +415,21 @@ var ( CancunBlock: big.NewInt(54876000), PragueBlock: big.NewInt(73440256), Bor: &BorConfig{ - JaipurBlock: big.NewInt(23850000), - DelhiBlock: big.NewInt(38189056), - IndoreBlock: big.NewInt(44934656), - AhmedabadBlock: big.NewInt(62278656), - BhilaiBlock: big.NewInt(73440256), - RioBlock: big.NewInt(77414656), - MadhugiriBlock: big.NewInt(79783223), + JaipurBlock: big.NewInt(23850000), + DelhiBlock: big.NewInt(38189056), + IndoreBlock: big.NewInt(44934656), + AhmedabadBlock: big.NewInt(62278656), + BhilaiBlock: big.NewInt(73440256), + RioBlock: big.NewInt(77414656), + MadhugiriBlock: big.NewInt(80084800), + MadhugiriProBlock: big.NewInt(80084800), StateSyncConfirmationDelay: map[string]uint64{ "44934656": 128, }, Period: map[string]uint64{ "0": 2, - "79783223": 1, + "80084800": 1, }, ProducerDelay: map[string]uint64{ "0": 6, @@ -885,6 +887,7 @@ type BorConfig struct { BhilaiBlock *big.Int `json:"bhilaiBlock"` // Bhilai switch block (nil = no fork, 0 = already on bhilai) RioBlock *big.Int `json:"rioBlock"` // Rio switch block (nil = no fork, 0 = already on rio) MadhugiriBlock *big.Int `json:"madhugiriBlock"` // Madhugiri switch block (nil = no fork, 0 = already on madhugiri) + MadhugiriProBlock *big.Int `json:"madhugiriProBlock"` // MadhugiriPro switch block (nil = no fork, 0 = already on madhugiriPro) } // String implements the stringer interface, returning the consensus engine details. @@ -940,6 +943,10 @@ func (c *BorConfig) IsMadhugiri(number *big.Int) bool { return isBlockForked(c.MadhugiriBlock, number) } +func (c *BorConfig) IsMadhugiriPro(number *big.Int) bool { + return isBlockForked(c.MadhugiriProBlock, number) +} + // // TODO: modify this function once the block number is finalized // func (c *BorConfig) IsNapoli(number *big.Int) bool { // if c.NapoliBlock != nil { @@ -1640,6 +1647,7 @@ type Rules struct { IsMerge, IsShanghai, IsCancun, IsPrague, IsOsaka bool IsVerkle bool IsMadhugiri bool + IsMadhugiriPro bool } // Rules ensures c's ChainID is not nil. @@ -1672,5 +1680,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsOsaka: c.IsOsaka(num), IsEIP4762: c.IsVerkle(num), IsMadhugiri: c.Bor != nil && c.Bor.IsMadhugiri(num), + IsMadhugiriPro: c.Bor != nil && c.Bor.IsMadhugiriPro(num), } } diff --git a/params/version.go b/params/version.go index e7b38cb6b3..ce7152ebee 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 2 // Major version component of the current release - VersionMinor = 4 // Minor version component of the current release + VersionMinor = 5 // Minor version component of the current release VersionPatch = 0 // Patch version component of the current release VersionMeta = "" // Version metadata to append to the version string )