core/vm, params: implement EXTCODEHASH opcode (#17202)

* core/vm, params: implement EXTCODEHASH opcode

* core, params: tiny fixes and polish

* core: add function description
This commit is contained in:
gary rong 2018-07-24 23:06:40 +08:00 committed by Péter Szilágyi
parent cab1cff11c
commit 2433349c80
6 changed files with 63 additions and 1 deletions

@ -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)

@ -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

@ -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,

@ -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,

@ -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):

@ -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,
@ -73,6 +74,20 @@ var (
Suicide: 5000,
ExpByte: 50,
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,
}
)