Skip to content

Commit

Permalink
Agharta/EIP1052 EXTCODEHASH implementation (#55)
Browse files Browse the repository at this point in the history
* implemented EXTCODEHASH, need to figure out memory alloc in vm.go

* fixed some issues with extCodeHash, we are still failing tests relating to account being created and self-destructed in the same transaction

* remove accidentally commited file

* Figured out why tests weren't passing, skipped irrelevant tests that used Create2

* removed fmt import

* removed individual skipped tests, Added constantinople as unsupported fork

* added in case for Atlantis

* removed explicit gas price for extCodeHash

* forgot to add additional argument to ruleSet struct

* we can just have the gastable return agharta gastable as default in main and runtime

* pull from development

* fix build issues

* Fixed reference

* Removed skipped test

* Fix spacing

* Add back gas consumption

* Add nil check for opcode

* Remove skipped directories

* clean up comments and discrepancy
  • Loading branch information
austinabell authored and GregTheGreek committed Oct 18, 2019
1 parent 53296c5 commit a10e3ec
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 32 deletions.
16 changes: 8 additions & 8 deletions cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,24 +228,24 @@ type ruleSet struct{}

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

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

func (ruleSet) IsAgharta(*big.Int) bool {
return true
}
// IsAgharta defaults to true 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),
CreateBySuicide: big.NewInt(25000),
}
}
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
6 changes: 5 additions & 1 deletion core/vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@ 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),
ExpByte: big.NewInt(50),
CreateBySuicide: big.NewInt(25000),
}
}
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

0 comments on commit a10e3ec

Please sign in to comment.