From dbcefefc3f9853ac656f6a0cfdcfd792e57b55bc Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 9 Apr 2019 11:30:21 +0200 Subject: [PATCH] core: initial implementation of https://eips.ethereum.org/EIPS/eip-1884 --- core/vm/instructions.go | 6 ++++++ core/vm/interpreter.go | 2 ++ core/vm/jump_table.go | 13 +++++++++++++ core/vm/opcodes.go | 1 + params/config.go | 16 ++++++++++++---- params/gas_table.go | 12 ++++++++++++ 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 2a062d7e77..5dc41b1a7f 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -415,6 +415,12 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo return nil, nil } +func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + balance := interpreter.intPool.get().Set(interpreter.evm.StateDB.GetBalance(contract.Address())) + stack.push(balance) + return nil, nil +} + func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { stack.push(interpreter.intPool.get().SetBytes(interpreter.evm.Origin.Bytes())) return nil, nil diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 989f85f5d3..97cb7b1b8b 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -91,6 +91,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { // we'll set the default jump table. if !cfg.JumpTable[STOP].valid { switch { + case evm.ChainConfig().IsIstanbul(evm.BlockNumber): + cfg.JumpTable = istanbulInstructionSet case evm.ChainConfig().IsConstantinople(evm.BlockNumber): cfg.JumpTable = constantinopleInstructionSet case evm.ChainConfig().IsByzantium(evm.BlockNumber): diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 425436f9e5..e271178fb4 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -58,8 +58,21 @@ var ( homesteadInstructionSet = newHomesteadInstructionSet() byzantiumInstructionSet = newByzantiumInstructionSet() constantinopleInstructionSet = newConstantinopleInstructionSet() + istanbulInstructionSet = newIstanbulInstructionSet() ) +func newIstanbulInstructionSet() [256]operation { + instructionSet := newConstantinopleInstructionSet() + instructionSet[SELFBALANCE] = operation{ + execute: opSelfBalance, + constantGas: GasFastStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + valid: true, + } + return instructionSet +} + // NewConstantinopleInstructionSet returns the frontier, homestead // byzantium and contantinople instructions. func newConstantinopleInstructionSet() [256]operation { diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 4349ffd295..1ae88c7dd4 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -101,6 +101,7 @@ const ( NUMBER DIFFICULTY GASLIMIT + SELFBALANCE ) // 0x50 range - 'storage' and execution. diff --git a/params/config.go b/params/config.go index c59c748ac2..bb2431307a 100644 --- a/params/config.go +++ b/params/config.go @@ -151,16 +151,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -199,6 +199,7 @@ type ChainConfig struct { ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium) ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated) PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople) + IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated) // Various consensus engines @@ -236,7 +237,7 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v ConstantinopleFix: %v Engine: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v ConstantinopleFix: %v Istanbul %v Engine: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -247,6 +248,7 @@ func (c *ChainConfig) String() string { c.ByzantiumBlock, c.ConstantinopleBlock, c.PetersburgBlock, + c.IstanbulBlock, engine, ) } @@ -293,6 +295,10 @@ func (c *ChainConfig) IsPetersburg(num *big.Int) bool { return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num) } +func (c *ChainConfig) IsIstanbul(num *big.Int) bool { + return isForked(c.IstanbulBlock, num) +} + // IsEWASM returns whether num represents a block number after the EWASM fork func (c *ChainConfig) IsEWASM(num *big.Int) bool { return isForked(c.EWASMBlock, num) @@ -306,6 +312,8 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable { return GasTableHomestead } switch { + case c.IsIstanbul(num): + return GasTableEipIstanbul case c.IsConstantinople(num): return GasTableConstantinople case c.IsEIP158(num): diff --git a/params/gas_table.go b/params/gas_table.go index 6c4a38269c..36c724e831 100644 --- a/params/gas_table.go +++ b/params/gas_table.go @@ -90,4 +90,16 @@ var ( CreateBySuicide: 25000, } + // GasTableEipIstanbul contain the gas re-prices for EIP 1884 + GasTableEipIstanbul = GasTable{ + ExtcodeSize: 700, + ExtcodeCopy: 700, + ExtcodeHash: 400, + Balance: 700, // Increase from 400 to 700 + SLoad: 800, + Calls: 700, + Suicide: 5000, + ExpByte: 50, + CreateBySuicide: 25000, + } )