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
This commit is contained in:
HAOYUatHZ 2023-11-22 15:15:10 +08:00 committed by GitHub
parent 8f446dd407
commit fccf142288
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 5 deletions

View file

@ -34,6 +34,10 @@ import (
"golang.org/x/crypto/ripemd160" "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 // 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 // requires a deterministic gas count based on the input size of the Run method of the
// contract. // contract.
@ -92,6 +96,20 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{9}): &blake2F{}, 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 // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
// contracts used in the Cancun release. // contracts used in the Cancun release.
var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
@ -122,11 +140,12 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
} }
var ( var (
PrecompiledAddressesCancun []common.Address PrecompiledAddressesCancun []common.Address
PrecompiledAddressesBerlin []common.Address PrecompiledAddressesArchimedes []common.Address
PrecompiledAddressesIstanbul []common.Address PrecompiledAddressesBerlin []common.Address
PrecompiledAddressesByzantium []common.Address PrecompiledAddressesIstanbul []common.Address
PrecompiledAddressesHomestead []common.Address PrecompiledAddressesByzantium []common.Address
PrecompiledAddressesHomestead []common.Address
) )
func init() { func init() {
@ -142,6 +161,9 @@ func init() {
for k := range PrecompiledContractsBerlin { for k := range PrecompiledContractsBerlin {
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
} }
for k := range PrecompiledContractsArchimedes {
PrecompiledAddressesArchimedes = append(PrecompiledAddressesArchimedes, k)
}
for k := range PrecompiledContractsCancun { for k := range PrecompiledContractsCancun {
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
} }
@ -152,6 +174,8 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
switch { switch {
case rules.IsCancun: case rules.IsCancun:
return PrecompiledAddressesCancun return PrecompiledAddressesCancun
case rules.IsArchimedes:
return PrecompiledAddressesArchimedes
case rules.IsBerlin: case rules.IsBerlin:
return PrecompiledAddressesBerlin return PrecompiledAddressesBerlin
case rules.IsIstanbul: case rules.IsIstanbul:
@ -231,6 +255,15 @@ func (c *sha256hash) Run(input []byte) ([]byte, error) {
return h[:], nil 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. // RIPEMD160 implemented as a native contract.
type ripemd160hash struct{} type ripemd160hash struct{}
@ -247,6 +280,15 @@ func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil 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. // data copy implemented as a native contract.
type dataCopy struct{} type dataCopy struct{}
@ -647,6 +689,15 @@ func (c *blake2F) Run(input []byte) ([]byte, error) {
return output, nil 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 ( var (
errBLS12381InvalidInputLength = errors.New("invalid input length") errBLS12381InvalidInputLength = errors.New("invalid input length")
errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes")

View file

@ -42,6 +42,8 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
switch { switch {
case evm.chainRules.IsCancun: case evm.chainRules.IsCancun:
precompiles = PrecompiledContractsCancun precompiles = PrecompiledContractsCancun
case evm.chainRules.IsArchimedes:
precompiles = PrecompiledContractsArchimedes
case evm.chainRules.IsBerlin: case evm.chainRules.IsBerlin:
precompiles = PrecompiledContractsBerlin precompiles = PrecompiledContractsBerlin
case evm.chainRules.IsIstanbul: case evm.chainRules.IsIstanbul:

View file

@ -70,6 +70,7 @@ func setDefaults(cfg *Config) {
MuirGlacierBlock: new(big.Int), MuirGlacierBlock: new(big.Int),
BerlinBlock: new(big.Int), BerlinBlock: new(big.Int),
LondonBlock: new(big.Int), LondonBlock: new(big.Int),
ArchimedesBlock: new(big.Int),
} }
} }

View file

@ -309,6 +309,7 @@ type ChainConfig struct {
BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin) 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) 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) 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) 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 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 { 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) 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 { 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) 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) 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. // 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 { func (c *ChainConfig) IsGrayGlacier(num *big.Int) bool {
return isBlockForked(c.GrayGlacierBlock, num) return isBlockForked(c.GrayGlacierBlock, num)
@ -594,6 +603,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "berlinBlock", block: c.BerlinBlock}, {name: "berlinBlock", block: c.BerlinBlock},
{name: "londonBlock", block: c.LondonBlock}, {name: "londonBlock", block: c.LondonBlock},
{name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true}, {name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true},
{name: "archimedesBlock", block: c.ArchimedesBlock, optional: true},
{name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true}, {name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true},
{name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true}, {name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true},
{name: "shanghaiTime", timestamp: c.ShanghaiTime}, {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) { if isForkBlockIncompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, headNumber) {
return newBlockCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock) 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) { if isForkBlockIncompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, headNumber) {
return newBlockCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock) return newBlockCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock)
} }
@ -850,6 +863,7 @@ type Rules struct {
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon bool IsBerlin, IsLondon bool
IsArchimedes bool
IsMerge, IsShanghai, IsCancun, IsPrague bool IsMerge, IsShanghai, IsCancun, IsPrague bool
IsVerkle bool IsVerkle bool
} }
@ -872,6 +886,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsIstanbul: c.IsIstanbul(num), IsIstanbul: c.IsIstanbul(num),
IsBerlin: c.IsBerlin(num), IsBerlin: c.IsBerlin(num),
IsLondon: c.IsLondon(num), IsLondon: c.IsLondon(num),
IsArchimedes: c.IsArchimedes(num),
IsMerge: isMerge, IsMerge: isMerge,
IsShanghai: c.IsShanghai(num, timestamp), IsShanghai: c.IsShanghai(num, timestamp),
IsCancun: c.IsCancun(num, timestamp), IsCancun: c.IsCancun(num, timestamp),