diff --git a/core/state_transition.go b/core/state_transition.go index ee6d041c2..33d4892b5 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -377,8 +377,20 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*Executi homestead := st.evm.ChainRules().IsHomestead istanbul := st.evm.ChainRules().IsIstanbul london := st.evm.ChainRules().IsLondon + nano := st.evm.ChainRules().IsNano contractCreation := msg.To() == nil + if nano { + for _, blackListAddr := range types.NanoBlackList { + if blackListAddr == sender.Address() { + return nil, fmt.Errorf("block blacklist account") + } + if msg.To() != nil && *msg.To() == blackListAddr { + return nil, fmt.Errorf("block blacklist account") + } + } + } + // Check clauses 4-5, subtract intrinsic gas if everything is correct gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, homestead, istanbul) if err != nil { diff --git a/core/types/blacklist.go b/core/types/blacklist.go new file mode 100644 index 000000000..9428a7632 --- /dev/null +++ b/core/types/blacklist.go @@ -0,0 +1,11 @@ +package types + +import "github.com/ledgerwatch/erigon/common" + +// This is introduced because of the Tendermint IAVL Merkel Proof verification exploitation. +var NanoBlackList = []common.Address{ + common.HexToAddress("0x489A8756C18C0b8B24EC2a2b9FF3D4d447F79BEc"), + common.HexToAddress("0xFd6042Df3D74ce9959922FeC559d7995F3933c55"), + // Test Account + common.HexToAddress("0xdb789Eb5BDb4E559beD199B8b82dED94e1d056C9"), +} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 5d86ae74a..e0285cc72 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -95,6 +95,21 @@ var PrecompiledContractsIstanbulForBSC = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{101}): &iavlMerkleProofValidate{}, } +var PrecompiledContractsNano = 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{}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + + common.BytesToAddress([]byte{100}): &tmHeaderValidateNano{}, + common.BytesToAddress([]byte{101}): &iavlMerkleProofValidateNano{}, +} + // PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum // contracts used in the Berlin release. var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ @@ -124,6 +139,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ } var ( + PrecompiledAddressesNano []common.Address PrecompiledAddressesBerlin []common.Address PrecompiledAddressesIstanbul []common.Address PrecompiledAddressesIstanbulForBSC []common.Address @@ -147,11 +163,16 @@ func init() { for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } + for k := range PrecompiledContractsNano { + PrecompiledAddressesNano = append(PrecompiledAddressesNano, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules *params.Rules) []common.Address { switch { + case rules.IsNano: + return PrecompiledAddressesNano case rules.IsBerlin: return PrecompiledAddressesBerlin case rules.IsIstanbul: diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go index d46dc23eb..1a7d1d6fc 100644 --- a/core/vm/contracts_lightclient.go +++ b/core/vm/contracts_lightclient.go @@ -133,3 +133,28 @@ func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) { binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-uint64TypeLength:], 0x01) return result, nil } + +// tmHeaderValidate implemented as a native contract. +type tmHeaderValidateNano struct{} + +func (c *tmHeaderValidateNano) RequiredGas(input []byte) uint64 { + return params.TendermintHeaderValidateGas +} + +func (c *tmHeaderValidateNano) Run(input []byte) (result []byte, err error) { + return nil, fmt.Errorf("suspend") +} + +// ------------------------------------------------------------------------------------------------------------------------------------------------ +type iavlMerkleProofValidateNano struct{} + +func (c *iavlMerkleProofValidateNano) RequiredGas(input []byte) uint64 { + return params.IAVLMerkleProofValidateGas +} + +// input: +// | payload length | payload | +// | 32 bytes | | +func (c *iavlMerkleProofValidateNano) Run(input []byte) (result []byte, err error) { + return nil, fmt.Errorf("suspend") +} diff --git a/core/vm/evm.go b/core/vm/evm.go index dcee26142..ac97f5225 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -45,6 +45,8 @@ type ( func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { + case evm.chainRules.IsNano: + precompiles = PrecompiledContractsNano case evm.chainRules.IsBerlin: precompiles = PrecompiledContractsBerlin case evm.chainRules.IsIstanbul: diff --git a/params/chainspecs/bsc.json b/params/chainspecs/bsc.json index d31d9db53..711d412c8 100644 --- a/params/chainspecs/bsc.json +++ b/params/chainspecs/bsc.json @@ -16,6 +16,7 @@ "mirrorSyncBlock": 5184000, "brunoBlock": 13082000, "eulerBlock": 18907621, + "nanoBlock": 21962149, "parlia": { "DBPath": "", "InMemory": false, diff --git a/params/chainspecs/chapel.json b/params/chainspecs/chapel.json index 0a0dca293..03283d7cc 100644 --- a/params/chainspecs/chapel.json +++ b/params/chainspecs/chapel.json @@ -17,6 +17,7 @@ "brunoBlock": 13837000, "eulerBlock": 19203503, "gibbsBlock": 22800220, + "nanoBlock": 23482428, "parlia": { "DBPath": "", "InMemory": false, diff --git a/params/config.go b/params/config.go index 152de4023..a4ab648f7 100644 --- a/params/config.go +++ b/params/config.go @@ -259,6 +259,7 @@ type ChainConfig struct { BrunoBlock *big.Int `json:"brunoBlock,omitempty" toml:",omitempty"` // brunoBlock switch block (nil = no fork, 0 = already activated) EulerBlock *big.Int `json:"eulerBlock,omitempty" toml:",omitempty"` // eulerBlock switch block (nil = no fork, 0 = already activated) GibbsBlock *big.Int `json:"gibbsBlock,omitempty" toml:",omitempty"` // gibbsBlock switch block (nil = no fork, 0 = already activated) + NanoBlock *big.Int `json:"nanoBlock,omitempty" toml:",omitempty"` // nanoBlock switch block (nil = no fork, 0 = already activated) // Gnosis Chain fork blocks PosdaoBlock *big.Int `json:"posdaoBlock,omitempty"` @@ -398,7 +399,7 @@ func (c *ChainConfig) String() string { // TODO Covalent: Refactor to more generic approach and potentially introduce tag for "ecosystem" field (Ethereum, BSC, etc.) if c.Consensus == ParliaConsensus { - return fmt.Sprintf("{ChainID: %v Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Euler: %v, Gibbs: %v, Engine: %v}", + return fmt.Sprintf("{ChainID: %v Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Euler: %v, Gibbs: %v, Nano: %v, Engine: %v}", c.ChainID, c.RamanujanBlock, c.NielsBlock, @@ -406,6 +407,7 @@ func (c *ChainConfig) String() string { c.BrunoBlock, c.EulerBlock, c.GibbsBlock, + c.NanoBlock, engine, ) } @@ -550,6 +552,15 @@ func (c *ChainConfig) IsOnGibbs(num *big.Int) bool { return configNumEqual(c.GibbsBlock, num) } +// IsNano returns whether num is either equal to the euler fork block or greater. +func (c *ChainConfig) IsNano(num uint64) bool { + return isForked(c.NanoBlock, num) +} + +func (c *ChainConfig) IsOnNano(num *big.Int) bool { + return configNumEqual(c.NanoBlock, num) +} + // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater. func (c *ChainConfig) IsMuirGlacier(num uint64) bool { return isForked(c.MuirGlacierBlock, num) @@ -748,6 +759,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head uint64) *ConfigC if isForkIncompatible(c.GibbsBlock, newcfg.GibbsBlock, head) { return newCompatError("Gibbs fork block", c.GibbsBlock, newcfg.GibbsBlock) } + if isForkIncompatible(c.NanoBlock, newcfg.NanoBlock, head) { + return newCompatError("Nano fork block", c.NanoBlock, newcfg.NanoBlock) + } return nil } @@ -817,6 +831,7 @@ type Rules struct { IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon, IsShanghai, IsCancun bool IsParlia, IsStarknet, IsAura bool + IsNano bool } // Rules ensures c's ChainID is not nil. @@ -838,6 +853,7 @@ func (c *ChainConfig) Rules(num uint64) *Rules { IsLondon: c.IsLondon(num), IsShanghai: c.IsShanghai(num), IsCancun: c.IsCancun(num), + IsNano: c.IsNano(num), IsParlia: c.Parlia != nil, IsAura: c.Aura != nil, }