diff options
author | gary rong <garyrong0905@gmail.com> | 2018-07-24 23:06:40 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2018-07-24 23:06:40 +0800 |
commit | 2433349c808fad601419d1f06275bec5b6a93ec8 (patch) | |
tree | 883b11148d15fd8a191131a9aaf17731f28856d0 | |
parent | cab1cff11cbcd4ff60f1a149deb71ec87413b487 (diff) | |
download | dexon-2433349c808fad601419d1f06275bec5b6a93ec8.tar.gz dexon-2433349c808fad601419d1f06275bec5b6a93ec8.tar.zst dexon-2433349c808fad601419d1f06275bec5b6a93ec8.zip |
core/vm, params: implement EXTCODEHASH opcode (#17202)
* core/vm, params: implement EXTCODEHASH opcode
* core, params: tiny fixes and polish
* core: add function description
-rw-r--r-- | core/vm/gas_table.go | 4 | ||||
-rw-r--r-- | core/vm/instructions.go | 32 | ||||
-rw-r--r-- | core/vm/jump_table.go | 6 | ||||
-rw-r--r-- | core/vm/opcodes.go | 3 | ||||
-rw-r--r-- | params/config.go | 2 | ||||
-rw-r--r-- | params/gas_table.go | 17 |
6 files changed, 63 insertions, 1 deletions
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index e130406ec..f9eea319e 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -241,6 +241,10 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta return gas, nil } +func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return gt.ExtcodeHash, nil +} + func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var overflow bool gas, err := memoryGasCost(mem, memorySize) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index b25c0111a..122fc21e4 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -496,6 +496,38 @@ func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta return nil, nil } +// opExtCodeHash returns the code hash of a specified account. +// There are several cases when the function is called, while we can relay everything +// to `state.GetCodeHash` function to ensure the correctness. +// (1) Caller tries to get the code hash of a normal contract account, state +// should return the relative code hash and set it as the result. +// +// (2) Caller tries to get the code hash of a non-existent account, state should +// return common.Hash{} and zero will be set as the result. +// +// (3) Caller tries to get the code hash for an account without contract code, +// state should return emptyCodeHash(0xc5d246...) as the result. +// +// (4) Caller tries to get the code hash of a precompiled account, the result +// should be zero or emptyCodeHash. +// +// It is worth noting that in order to avoid unnecessary create and clean, +// all precompile accounts on mainnet have been transferred 1 wei, so the return +// here should be emptyCodeHash. +// If the precompile account is not transferred any amount on a private or +// customized chain, the return value will be zero. +// +// (5) Caller tries to get the code hash for an account which is marked as suicided +// in the current transaction, the code hash of this account should be returned. +// +// (6) Caller tries to get the code hash for an account which is marked as deleted, +// this account should be regarded as a non-existent account and zero should be returned. +func opExtCodeHash(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + slot := stack.peek() + slot.SetBytes(evm.StateDB.GetCodeHash(common.BigToAddress(slot)).Bytes()) + return nil, nil +} + func opGasprice(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { stack.push(evm.interpreter.intPool.get().Set(evm.GasPrice)) return nil, nil diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 014496567..f387e6133 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -80,6 +80,12 @@ func newConstantinopleInstructionSet() [256]operation { validateStack: makeStackFunc(2, 1), valid: true, } + instructionSet[EXTCODEHASH] = operation{ + execute: opExtCodeHash, + gasCost: gasExtCodeHash, + validateStack: makeStackFunc(1, 1), + valid: true, + } instructionSet[CREATE2] = operation{ execute: opCreate2, gasCost: gasCreate2, diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 84426a28a..4349ffd29 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -90,6 +90,7 @@ const ( EXTCODECOPY RETURNDATASIZE RETURNDATACOPY + EXTCODEHASH ) // 0x40 range - block operations. @@ -267,6 +268,7 @@ var opCodeToString = map[OpCode]string{ EXTCODECOPY: "EXTCODECOPY", RETURNDATASIZE: "RETURNDATASIZE", RETURNDATACOPY: "RETURNDATACOPY", + EXTCODEHASH: "EXTCODEHASH", // 0x40 range - block operations. BLOCKHASH: "BLOCKHASH", @@ -435,6 +437,7 @@ var stringToOp = map[string]OpCode{ "EXTCODECOPY": EXTCODECOPY, "RETURNDATASIZE": RETURNDATASIZE, "RETURNDATACOPY": RETURNDATACOPY, + "EXTCODEHASH": EXTCODEHASH, "BLOCKHASH": BLOCKHASH, "COINBASE": COINBASE, "TIMESTAMP": TIMESTAMP, diff --git a/params/config.go b/params/config.go index 6e6a5cb8b..b9e9bb8d6 100644 --- a/params/config.go +++ b/params/config.go @@ -211,6 +211,8 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable { return GasTableHomestead } switch { + case c.IsConstantinople(num): + return GasTableConstantinople case c.IsEIP158(num): return GasTableEIP158 case c.IsEIP150(num): diff --git a/params/gas_table.go b/params/gas_table.go index d33bebbe5..6c4a38269 100644 --- a/params/gas_table.go +++ b/params/gas_table.go @@ -20,6 +20,7 @@ package params type GasTable struct { ExtcodeSize uint64 ExtcodeCopy uint64 + ExtcodeHash uint64 Balance uint64 SLoad uint64 Calls uint64 @@ -63,7 +64,7 @@ var ( CreateBySuicide: 25000, } // GasTableEIP158 contain the gas re-prices for - // the EIP15* phase. + // the EIP155/EIP158 phase. GasTableEIP158 = GasTable{ ExtcodeSize: 700, ExtcodeCopy: 700, @@ -75,4 +76,18 @@ var ( CreateBySuicide: 25000, } + // GasTableConstantinople contain the gas re-prices for + // the constantinople phase. + GasTableConstantinople = GasTable{ + ExtcodeSize: 700, + ExtcodeCopy: 700, + ExtcodeHash: 400, + Balance: 400, + SLoad: 200, + Calls: 700, + Suicide: 5000, + ExpByte: 50, + + CreateBySuicide: 25000, + } ) |