aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
authorgary rong <garyrong0905@gmail.com>2018-07-24 23:06:40 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-07-24 23:06:40 +0800
commit2433349c808fad601419d1f06275bec5b6a93ec8 (patch)
tree883b11148d15fd8a191131a9aaf17731f28856d0 /core/vm
parentcab1cff11cbcd4ff60f1a149deb71ec87413b487 (diff)
downloaddexon-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
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/gas_table.go4
-rw-r--r--core/vm/instructions.go32
-rw-r--r--core/vm/jump_table.go6
-rw-r--r--core/vm/opcodes.go3
4 files changed, 45 insertions, 0 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,