From fccf14228882ebdf63e5ad5fe428762cca208791 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Wed, 22 Nov 2023 15:15:10 +0800 Subject: [PATCH] feat: add archimedes fork (disable sha256, ripemd160, blake2f precompiles) (#574) * update core/vm/contracts.go * update core/vm/evm.go * update core/vm/runtime/runtime.go * update params/config.go * update `(c *ChainConfig) Description()` * fix --- core/vm/contracts.go | 61 ++++++++++++++++++++++++++++++++++---- core/vm/evm.go | 2 ++ core/vm/runtime/runtime.go | 1 + params/config.go | 15 ++++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 574bb9bef6..5a456bfbce 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -34,6 +34,10 @@ import ( "golang.org/x/crypto/ripemd160" ) +var ( + errPrecompileDisabled = errors.New("sha256, ripemd160, blake2f precompiles temporarily disabled") +) + // PrecompiledContract is the basic interface for native Go contracts. The implementation // requires a deterministic gas count based on the input size of the Run method of the // contract. @@ -92,6 +96,20 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{9}): &blake2F{}, } +// PrecompiledContractsArchimedes contains the default set of pre-compiled Ethereum +// contracts used in the Archimedes release. Same as Berlin but without sha2, blake2f, ripemd160 +var PrecompiledContractsArchimedes = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hashDisabled{}, + common.BytesToAddress([]byte{3}): &ripemd160hashDisabled{}, + 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}): &blake2FDisabled{}, +} + // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum // contracts used in the Cancun release. var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{ @@ -122,11 +140,12 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ } var ( - PrecompiledAddressesCancun []common.Address - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesCancun []common.Address + PrecompiledAddressesArchimedes []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { @@ -142,6 +161,9 @@ func init() { for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } + for k := range PrecompiledContractsArchimedes { + PrecompiledAddressesArchimedes = append(PrecompiledAddressesArchimedes, k) + } for k := range PrecompiledContractsCancun { PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) } @@ -152,6 +174,8 @@ func ActivePrecompiles(rules params.Rules) []common.Address { switch { case rules.IsCancun: return PrecompiledAddressesCancun + case rules.IsArchimedes: + return PrecompiledAddressesArchimedes case rules.IsBerlin: return PrecompiledAddressesBerlin case rules.IsIstanbul: @@ -231,6 +255,15 @@ func (c *sha256hash) Run(input []byte) ([]byte, error) { return h[:], nil } +type sha256hashDisabled struct{} + +func (c *sha256hashDisabled) RequiredGas(input []byte) uint64 { + return (&sha256hash{}).RequiredGas(input) +} +func (c *sha256hashDisabled) Run(input []byte) ([]byte, error) { + return nil, errPrecompileDisabled +} + // RIPEMD160 implemented as a native contract. type ripemd160hash struct{} @@ -247,6 +280,15 @@ func (c *ripemd160hash) Run(input []byte) ([]byte, error) { return common.LeftPadBytes(ripemd.Sum(nil), 32), nil } +type ripemd160hashDisabled struct{} + +func (c *ripemd160hashDisabled) RequiredGas(input []byte) uint64 { + return (&ripemd160hash{}).RequiredGas(input) +} +func (c *ripemd160hashDisabled) Run(input []byte) ([]byte, error) { + return nil, errPrecompileDisabled +} + // data copy implemented as a native contract. type dataCopy struct{} @@ -647,6 +689,15 @@ func (c *blake2F) Run(input []byte) ([]byte, error) { return output, nil } +type blake2FDisabled struct{} + +func (c *blake2FDisabled) RequiredGas(input []byte) uint64 { + return (&blake2F{}).RequiredGas(input) +} +func (c *blake2FDisabled) Run(input []byte) ([]byte, error) { + return nil, errPrecompileDisabled +} + var ( errBLS12381InvalidInputLength = errors.New("invalid input length") errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") diff --git a/core/vm/evm.go b/core/vm/evm.go index 2c6cc7d484..eaed9f1827 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -42,6 +42,8 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { switch { case evm.chainRules.IsCancun: precompiles = PrecompiledContractsCancun + case evm.chainRules.IsArchimedes: + precompiles = PrecompiledContractsArchimedes case evm.chainRules.IsBerlin: precompiles = PrecompiledContractsBerlin case evm.chainRules.IsIstanbul: diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index cfd7e4dbc4..2a42bf8ec5 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -70,6 +70,7 @@ func setDefaults(cfg *Config) { MuirGlacierBlock: new(big.Int), BerlinBlock: new(big.Int), LondonBlock: new(big.Int), + ArchimedesBlock: new(big.Int), } } diff --git a/params/config.go b/params/config.go index 88ff772a1d..6b1dec74b8 100644 --- a/params/config.go +++ b/params/config.go @@ -309,6 +309,7 @@ type ChainConfig struct { BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin) LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london) ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) + ArchimedesBlock *big.Int `json:"archimedesBlock,omitempty"` // Archimedes switch block (nil = no fork, 0 = already on archimedes) GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter @@ -408,6 +409,9 @@ func (c *ChainConfig) Description() string { if c.ArrowGlacierBlock != nil { banner += fmt.Sprintf(" - Arrow Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md)\n", c.ArrowGlacierBlock) } + if c.ArchimedesBlock != nil { + banner += fmt.Sprintf(" - Archimedes: #%-8v\n", c.ArchimedesBlock) // TODO: add archimedes execution-specs + } if c.GrayGlacierBlock != nil { banner += fmt.Sprintf(" - Gray Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)\n", c.GrayGlacierBlock) } @@ -512,6 +516,11 @@ func (c *ChainConfig) IsArrowGlacier(num *big.Int) bool { return isBlockForked(c.ArrowGlacierBlock, num) } +// IsArchimedes returns whether num is either equal to the Archimedes fork block or greater. +func (c *ChainConfig) IsArchimedes(num *big.Int) bool { + return isBlockForked(c.ArchimedesBlock, num) +} + // IsGrayGlacier returns whether num is either equal to the Gray Glacier (EIP-5133) fork block or greater. func (c *ChainConfig) IsGrayGlacier(num *big.Int) bool { return isBlockForked(c.GrayGlacierBlock, num) @@ -594,6 +603,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "berlinBlock", block: c.BerlinBlock}, {name: "londonBlock", block: c.LondonBlock}, {name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true}, + {name: "archimedesBlock", block: c.ArchimedesBlock, optional: true}, {name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true}, {name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true}, {name: "shanghaiTime", timestamp: c.ShanghaiTime}, @@ -688,6 +698,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, if isForkBlockIncompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, headNumber) { return newBlockCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock) } + if isForkBlockIncompatible(c.ArchimedesBlock, newcfg.ArchimedesBlock, headNumber) { + return newBlockCompatError("Archimedes fork block", c.ArchimedesBlock, newcfg.ArchimedesBlock) + } if isForkBlockIncompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, headNumber) { return newBlockCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock) } @@ -850,6 +863,7 @@ type Rules struct { IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon bool + IsArchimedes bool IsMerge, IsShanghai, IsCancun, IsPrague bool IsVerkle bool } @@ -872,6 +886,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsIstanbul: c.IsIstanbul(num), IsBerlin: c.IsBerlin(num), IsLondon: c.IsLondon(num), + IsArchimedes: c.IsArchimedes(num), IsMerge: isMerge, IsShanghai: c.IsShanghai(num, timestamp), IsCancun: c.IsCancun(num, timestamp),