Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Agharta/EIP1052 EXTCODEHASH implementation #55

Merged
merged 20 commits into from
Oct 18, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,26 +228,27 @@ type ruleSet struct{}

func (ruleSet) IsHomestead(*big.Int) bool { return true }

func (ruleSet) IsAtlantis(*big.Int) bool {
// Default true for tests
return true
}
//set IsAtlantis to true by default for tests
func (ruleSet) IsAtlantis(*big.Int) bool { return true }

func (ruleSet) IsAgharta(*big.Int) bool {
return true
}
//set IsAgharta to true by default for tests
func (ruleSet) IsAgharta(*big.Int) bool { return true }

func (ruleSet) GasTable(*big.Int) *vm.GasTable {
//IsAgharta will always return true here,
//just have gastable default to returning the Agharta GasTable
return &vm.GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
ExtcodeHash: big.NewInt(400),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(10),
ExpByte: big.NewInt(50),
GregTheGreek marked this conversation as resolved.
Show resolved Hide resolved
CreateBySuicide: big.NewInt(25000),
}

}

func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
Expand Down
2 changes: 2 additions & 0 deletions core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,8 @@ func (c *ChainConfig) GasTable(num *big.Int) *vm.GasTable {
name = ""
} // will wall to default panic
switch name {
case "agharta":
return DefaultAghartaGasTable
case "homestead":
return DefaultHomeSteadGasTable
case "eip150":
Expand Down
12 changes: 12 additions & 0 deletions core/data_gastable.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,15 @@ var DefaultDiehardGasTable = &vm.GasTable{
ExpByte: big.NewInt(50),
CreateBySuicide: big.NewInt(25000),
}

var DefaultAghartaGasTable = &vm.GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
ExtcodeHash: big.NewInt(400),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(50),
CreateBySuicide: big.NewInt(25000),
}
2 changes: 2 additions & 0 deletions core/vm/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var (
type GasTable struct {
ExtcodeSize *big.Int
ExtcodeCopy *big.Int
ExtcodeHash *big.Int
Balance *big.Int
SLoad *big.Int
Calls *big.Int
Expand Down Expand Up @@ -176,6 +177,7 @@ var _baseCheck = map[OpCode]req{
BLOCKHASH: {1, GasExtStep, 1},
BALANCE: {1, new(big.Int), 1},
EXTCODESIZE: {1, new(big.Int), 1},
EXTCODEHASH: {1, new(big.Int), 1},
EXTCODECOPY: {4, new(big.Int), 0},
SLOAD: {1, big.NewInt(50), 1},
SSTORE: {2, new(big.Int), 0},
Expand Down
30 changes: 22 additions & 8 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"github.com/eth-classic/go-ethereum/common"
"github.com/eth-classic/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common/math"
)

var callStipend = big.NewInt(2300) // Free gas given at beginning of call.
Expand Down Expand Up @@ -275,33 +274,33 @@ func opMulmod(pc *uint64, env Environment, contract *Contract, memory *Memory, s
}

func opSHL(pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) ([]byte, error) {
shift, value := math.U256(stack.pop()), math.U256(stack.pop())
shift, value := U256(stack.pop()), U256(stack.pop())

if shift.Cmp(big.NewInt(256)) >= 0 {
value.SetUint64(0)
} else {
n := uint(shift.Uint64())
math.U256(value.Lsh(value, n))
U256(value.Lsh(value, n))
}
stack.push(value)
return nil, nil
}

func opSHR(pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) ([]byte, error) {
shift, value := math.U256(stack.pop()), math.U256(stack.pop())
shift, value := U256(stack.pop()), U256(stack.pop())

if shift.Cmp(big.NewInt(256)) >= 0 {
value.SetUint64(0)
} else {
n := uint(shift.Uint64())
math.U256(value.Rsh(value, n))
U256(value.Rsh(value, n))
}
stack.push(value)
return nil, nil
}

func opSAR(pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) ([]byte, error) {
shift, value := math.U256(stack.pop()), math.S256(stack.pop())
shift, value := U256(stack.pop()), S256(stack.pop())

if shift.Cmp(big.NewInt(256)) >= 0 {
if value.Sign() >= 0 {
Expand All @@ -310,12 +309,12 @@ func opSAR(pc *uint64, env Environment, contract *Contract, memory *Memory, stac
value.SetInt64(-1)
}

stack.push(math.U256(value))
stack.push(U256(value))
} else {
n := uint(shift.Uint64())
// value
value.Rsh(value, n)
stack.push(math.U256(value))
stack.push(U256(value))
}
return nil, nil
}
Expand Down Expand Up @@ -383,6 +382,21 @@ func opExtCodeSize(pc *uint64, env Environment, contract *Contract, memory *Memo
return nil, nil
}

func opExtCodeHash(pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) ([]byte, error) {
//get address placed on stack
slot := stack.peek()
address := common.BigToAddress(slot)

//The EXTCODEHASH of non-existent OR empty account is 0
//see issue https://github.com/ethereum/tests/pull/569
if env.Db().Empty(address) {
slot.SetUint64(0)
} else {
slot.SetBytes(env.Db().GetCodeHash(address).Bytes())
}
return nil, nil
}

func opCodeSize(pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) ([]byte, error) {
l := big.NewInt(int64(len(contract.Code)))
stack.push(l)
Expand Down
6 changes: 5 additions & 1 deletion core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ func newJumpTable(ruleset RuleSet, blockNumber *big.Int) vmJumpTable {
}

if ruleset.IsAgharta(blockNumber) {

jumpTable[EXTCODEHASH] = jumpPtr{
fn: opExtCodeHash,
valid: true,
}

jumpTable[SHL] = jumpPtr{
fn: opSHL,
valid: true,
Expand Down
3 changes: 3 additions & 0 deletions core/vm/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const (
EXTCODECOPY
RETURNDATASIZE
RETURNDATACOPY
EXTCODEHASH
)

const (
Expand Down Expand Up @@ -262,6 +263,7 @@ var opCodeToString = map[OpCode]string{
GASPRICE: "TXGASPRICE",
RETURNDATASIZE: "RETURNDATASIZE",
RETURNDATACOPY: "RETURNDATACOPY",
EXTCODEHASH: "EXTCODEHASH",

// 0x40 range - block operations
BLOCKHASH: "BLOCKHASH",
Expand Down Expand Up @@ -432,6 +434,7 @@ var stringToOp = map[string]OpCode{
"GASLIMIT": GASLIMIT,
"EXTCODESIZE": EXTCODESIZE,
"EXTCODECOPY": EXTCODECOPY,
"EXTCODEHASH": EXTCODEHASH,
"RETURNDATASIZE": RETURNDATASIZE,
"RETURNDATACOPY": RETURNDATACOPY,
"POP": POP,
Expand Down
5 changes: 5 additions & 0 deletions core/vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,21 @@ func (ruleSet) IsHomestead(*big.Int) bool { return true }
func (ruleSet) IsAtlantis(*big.Int) bool { return true }
func (ruleSet) IsAgharta(*big.Int) bool { return true }
func (ruleSet) GasTable(*big.Int) *vm.GasTable {

//IsAgharta will always return true
//just have gastable default to returning the Agharta GasTable
return &vm.GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
ExtcodeHash: big.NewInt(400),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(10),
austinabell marked this conversation as resolved.
Show resolved Hide resolved
CreateBySuicide: big.NewInt(25000),
}

}

// Config is a basic type specifying certain configuration flags for running
Expand Down
4 changes: 4 additions & 0 deletions core/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ func calculateGasAndSize(gasTable *GasTable, env Environment, contract *Contract
}
case EXTCODESIZE:
gas.Set(gasTable.ExtcodeSize)
case EXTCODEHASH:
if gasTable.ExtcodeHash != nil {
gas.Set(gasTable.ExtcodeHash)
}
case BALANCE:
gas.Set(gasTable.Balance)
case SLOAD:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ require (
gopkg.in/urfave/cli.v1 v1.17.0
)

replace github.com/eth-classic/go-ethereum/accounts/abi/bind v0.0.0-20190521151733-fe17e9e1e2ce => ./accounts/abi/bind
replace github.com/eth-classic/go-ethereum/accounts/abi/bind v0.0.0-20190521151733-fe17e9e1e2ce => ./accounts/abi/bind
13 changes: 0 additions & 13 deletions tests/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,21 +689,8 @@ func TestAllETH(t *testing.T) {
skipTests["RevertPrecompiledTouch_storage.json/ConstantinopleFix/0"] = "Bug in Test"
skipTests["RevertPrecompiledTouch_storage.json/ConstantinopleFix/3"] = "Bug in Test"

//EIP 1052 (EXTCODEHASH) not implemented
skipTests["randomStatetestDEFAULT-Tue_07_58_41-15153-575192.json"] = "EXTCODEHASH not implemented"

unsupportedDirs := map[string]bool{
"stZeroKnowledge": true,
"stZeroKnowledge2": true,
"stExtCodeHash": true,
}

for _, dn := range dirNames {
dirName := dn[strings.LastIndex(dn, "/")+1 : len(dn)]
if unsupportedDirs[dirName] {
continue
}

t.Run(dirName, func(t *testing.T) {
fns, _ := filepath.Glob(filepath.Join(ethGeneralStateDir, dirName, "*"))
runETHTests(t, fns, skipTests)
Expand Down
14 changes: 14 additions & 0 deletions tests/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,23 @@ func (r RuleSet) GasTable(num *big.Int) *vm.GasTable {
}
}

if r.AtlantisBlock == nil || num == nil || num.Cmp(r.AtlantisBlock) < 0 {
return &vm.GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
ExpByte: big.NewInt(50),
CreateBySuicide: big.NewInt(25000),
}
}

return &vm.GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
ExtcodeHash: big.NewInt(400),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Expand Down