diff --git a/cmd/geth/retesteth.go b/cmd/geth/retesteth.go index f20f2295a..bda19324d 100644 --- a/cmd/geth/retesteth.go +++ b/cmd/geth/retesteth.go @@ -132,6 +132,7 @@ type CParamsParams struct { ByzantiumForkBlock *math.HexOrDecimal64 `json:"byzantiumForkBlock"` ConstantinopleForkBlock *math.HexOrDecimal64 `json:"constantinopleForkBlock"` ConstantinopleFixForkBlock *math.HexOrDecimal64 `json:"constantinopleFixForkBlock"` + IstanbulBlock *math.HexOrDecimal64 `json:"istanbulForkBlock"` ChainID *math.HexOrDecimal256 `json:"chainID"` MaximumExtraDataSize math.HexOrDecimal64 `json:"maximumExtraDataSize"` TieBreakingGas bool `json:"tieBreakingGas"` @@ -319,6 +320,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa byzantiumBlock *big.Int constantinopleBlock *big.Int petersburgBlock *big.Int + istanbulBlock *big.Int ) if chainParams.Params.HomesteadForkBlock != nil { homesteadBlock = big.NewInt(int64(*chainParams.Params.HomesteadForkBlock)) @@ -345,6 +347,10 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa if constantinopleBlock != nil && petersburgBlock == nil { petersburgBlock = big.NewInt(100000000000) } + if chainParams.Params.IstanbulBlock != nil { + istanbulBlock = big.NewInt(int64(*chainParams.Params.IstanbulBlock)) + } + genesis := &core.Genesis{ Config: ¶ms.ChainConfig{ ChainID: chainId, @@ -357,6 +363,7 @@ func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainPa ByzantiumBlock: byzantiumBlock, ConstantinopleBlock: constantinopleBlock, PetersburgBlock: petersburgBlock, + IstanbulBlock: istanbulBlock, }, Nonce: uint64(chainParams.Genesis.Nonce), Timestamp: uint64(chainParams.Genesis.Timestamp), diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index be6e00a6e..fe06492de 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -93,6 +93,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { if !cfg.JumpTable[STOP].valid { var jt JumpTable switch { + case evm.chainRules.IsIstanbul: + jt = istanbulInstructionSet case evm.chainRules.IsConstantinople: jt = constantinopleInstructionSet case evm.chainRules.IsByzantium: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index da532541c..b26b55284 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -60,15 +60,27 @@ var ( spuriousDragonInstructionSet = newSpuriousDragonInstructionSet() byzantiumInstructionSet = newByzantiumInstructionSet() constantinopleInstructionSet = newConstantinopleInstructionSet() + istanbulInstructionSet = newIstanbulInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. type JumpTable [256]operation -// NewConstantinopleInstructionSet returns the frontier, homestead +// newIstanbulInstructionSet returns the frontier, homestead +// byzantium, contantinople and petersburg instructions. +func newIstanbulInstructionSet() JumpTable { + instructionSet := newConstantinopleInstructionSet() + + enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344 + enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884 + enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200 + + return instructionSet +} + +// newConstantinopleInstructionSet returns the frontier, homestead // byzantium and contantinople instructions. func newConstantinopleInstructionSet() JumpTable { - // instructions that can be executed during the byzantium phase. instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = operation{ execute: opSHL, @@ -112,10 +124,9 @@ func newConstantinopleInstructionSet() JumpTable { return instructionSet } -// NewByzantiumInstructionSet returns the frontier, homestead and +// newByzantiumInstructionSet returns the frontier, homestead and // byzantium instructions. func newByzantiumInstructionSet() JumpTable { - // instructions that can be executed during the homestead phase. instructionSet := newSpuriousDragonInstructionSet() instructionSet[STATICCALL] = operation{ execute: opStaticCall, @@ -177,7 +188,7 @@ func newTangerineWhistleInstructionSet() JumpTable { return instructionSet } -// NewHomesteadInstructionSet returns the frontier and homestead +// newHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. func newHomesteadInstructionSet() JumpTable { instructionSet := newFrontierInstructionSet() @@ -194,7 +205,7 @@ func newHomesteadInstructionSet() JumpTable { return instructionSet } -// NewFrontierInstructionSet returns the frontier instructions +// newFrontierInstructionSet returns the frontier instructions // that can be executed during the frontier phase. func newFrontierInstructionSet() JumpTable { return JumpTable{ diff --git a/tests/init.go b/tests/init.go index f9af5c0ca..a18e12bdd 100644 --- a/tests/init.go +++ b/tests/init.go @@ -75,6 +75,18 @@ var Forks = map[string]*params.ChainConfig{ ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), }, + "Istanbul": { + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + DAOForkBlock: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + }, "FrontierToHomesteadAt5": { ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(5), @@ -117,6 +129,17 @@ var Forks = map[string]*params.ChainConfig{ ConstantinopleBlock: big.NewInt(5), PetersburgBlock: big.NewInt(5), }, + "ConstantinopleFixToIstanbulAt5": { + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(5), + }, } // UnsupportedForkError is returned when a test requests a fork that isn't implemented.