core, eth: unship EIP 2315

This commit is contained in:
Péter Szilágyi 2021-03-02 23:40:57 +02:00
parent 19d7a37abb
commit 7834e4a278
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
14 changed files with 48 additions and 205 deletions

View File

@ -96,19 +96,6 @@ func (c *Contract) validJumpdest(dest *uint256.Int) bool {
return c.isCode(udest) return c.isCode(udest)
} }
func (c *Contract) validJumpSubdest(udest uint64) bool {
// PC cannot go beyond len(code) and certainly can't be bigger than 63 bits.
// Don't bother checking for BEGINSUB in that case.
if int64(udest) < 0 || udest >= uint64(len(c.Code)) {
return false
}
// Only BEGINSUBs allowed for destinations
if OpCode(c.Code[udest]) != BEGINSUB {
return false
}
return c.isCode(udest)
}
// isCode returns true if the provided PC location is an actual opcode, as // isCode returns true if the provided PC location is an actual opcode, as
// opposed to a data-segment following a PUSHN operation. // opposed to a data-segment following a PUSHN operation.
func (c *Contract) isCode(udest uint64) bool { func (c *Contract) isCode(udest uint64) bool {

View File

@ -29,7 +29,6 @@ var activators = map[int]func(*JumpTable){
2200: enable2200, 2200: enable2200,
1884: enable1884, 1884: enable1884,
1344: enable1344, 1344: enable1344,
2315: enable2315,
} }
// EnableEIP enables the given EIP on the config. // EnableEIP enables the given EIP on the config.
@ -108,34 +107,6 @@ func enable2200(jt *JumpTable) {
jt[SSTORE].dynamicGas = gasSStoreEIP2200 jt[SSTORE].dynamicGas = gasSStoreEIP2200
} }
// enable2315 applies EIP-2315 (Simple Subroutines)
// - Adds opcodes that jump to and return from subroutines
func enable2315(jt *JumpTable) {
// New opcode
jt[BEGINSUB] = &operation{
execute: opBeginSub,
constantGas: GasQuickStep,
minStack: minStack(0, 0),
maxStack: maxStack(0, 0),
}
// New opcode
jt[JUMPSUB] = &operation{
execute: opJumpSub,
constantGas: GasSlowStep,
minStack: minStack(1, 0),
maxStack: maxStack(1, 0),
jumps: true,
}
// New opcode
jt[RETURNSUB] = &operation{
execute: opReturnSub,
constantGas: GasFastStep,
minStack: minStack(0, 0),
maxStack: maxStack(0, 0),
jumps: true,
}
}
// enable2929 enables "EIP-2929: Gas cost increases for state access opcodes" // enable2929 enables "EIP-2929: Gas cost increases for state access opcodes"
// https://eips.ethereum.org/EIPS/eip-2929 // https://eips.ethereum.org/EIPS/eip-2929
func enable2929(jt *JumpTable) { func enable2929(jt *JumpTable) {

View File

@ -45,12 +45,6 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
enc.Stack[k] = (*math.HexOrDecimal256)(v) enc.Stack[k] = (*math.HexOrDecimal256)(v)
} }
} }
if s.ReturnStack != nil {
enc.ReturnStack = make([]math.HexOrDecimal64, len(s.ReturnStack))
for k, v := range s.ReturnStack {
enc.ReturnStack[k] = math.HexOrDecimal64(v)
}
}
enc.ReturnData = s.ReturnData enc.ReturnData = s.ReturnData
enc.Storage = s.Storage enc.Storage = s.Storage
enc.Depth = s.Depth enc.Depth = s.Depth
@ -71,7 +65,6 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
Memory *hexutil.Bytes `json:"memory"` Memory *hexutil.Bytes `json:"memory"`
MemorySize *int `json:"memSize"` MemorySize *int `json:"memSize"`
Stack []*math.HexOrDecimal256 `json:"stack"` Stack []*math.HexOrDecimal256 `json:"stack"`
ReturnStack []math.HexOrDecimal64 `json:"returnStack"`
ReturnData *hexutil.Bytes `json:"returnData"` ReturnData *hexutil.Bytes `json:"returnData"`
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
Depth *int `json:"depth"` Depth *int `json:"depth"`
@ -106,12 +99,6 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s.Stack[k] = (*big.Int)(v) s.Stack[k] = (*big.Int)(v)
} }
} }
if dec.ReturnStack != nil {
s.ReturnStack = make([]uint32, len(dec.ReturnStack))
for k, v := range dec.ReturnStack {
s.ReturnStack[k] = uint32(v)
}
}
if dec.ReturnData != nil { if dec.ReturnData != nil {
s.ReturnData = *dec.ReturnData s.ReturnData = *dec.ReturnData
} }

View File

@ -547,38 +547,6 @@ func opJumpdest(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) (
return nil, nil return nil, nil
} }
func opBeginSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
return nil, ErrInvalidSubroutineEntry
}
func opJumpSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
if len(callContext.rstack.data) >= 1023 {
return nil, ErrReturnStackExceeded
}
pos := callContext.stack.pop()
if !pos.IsUint64() {
return nil, ErrInvalidJump
}
posU64 := pos.Uint64()
if !callContext.contract.validJumpSubdest(posU64) {
return nil, ErrInvalidJump
}
callContext.rstack.push(uint32(*pc))
*pc = posU64 + 1
return nil, nil
}
func opReturnSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
if len(callContext.rstack.data) == 0 {
return nil, ErrInvalidRetsub
}
// Other than the check that the return stack is not empty, there is no
// need to validate the pc from 'returns', since we only ever push valid
//values onto it via jumpsub.
*pc = uint64(callContext.rstack.pop()) + 1
return nil, nil
}
func opPc(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { func opPc(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
callContext.stack.push(new(uint256.Int).SetUint64(*pc)) callContext.stack.push(new(uint256.Int).SetUint64(*pc))
return nil, nil return nil, nil

View File

@ -94,7 +94,6 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack = newstack() stack = newstack()
rstack = newReturnStack()
pc = uint64(0) pc = uint64(0)
evmInterpreter = env.interpreter.(*EVMInterpreter) evmInterpreter = env.interpreter.(*EVMInterpreter)
) )
@ -105,7 +104,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
stack.push(x) stack.push(x)
stack.push(y) stack.push(y)
opFn(&pc, evmInterpreter, &callCtx{nil, stack, rstack, nil}) opFn(&pc, evmInterpreter, &callCtx{nil, stack, nil})
if len(stack.data) != 1 { if len(stack.data) != 1 {
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data)) t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
} }
@ -220,7 +219,7 @@ func TestAddMod(t *testing.T) {
stack.push(z) stack.push(z)
stack.push(y) stack.push(y)
stack.push(x) stack.push(x)
opAddmod(&pc, evmInterpreter, &callCtx{nil, stack, nil, nil}) opAddmod(&pc, evmInterpreter, &callCtx{nil, stack, nil})
actual := stack.pop() actual := stack.pop()
if actual.Cmp(expected) != 0 { if actual.Cmp(expected) != 0 {
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual) t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
@ -232,7 +231,7 @@ func TestAddMod(t *testing.T) {
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack, rstack = newstack(), newReturnStack() stack = newstack()
pc = uint64(0) pc = uint64(0)
interpreter = env.interpreter.(*EVMInterpreter) interpreter = env.interpreter.(*EVMInterpreter)
) )
@ -242,7 +241,7 @@ func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcas
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
stack.push(x) stack.push(x)
stack.push(y) stack.push(y)
opFn(&pc, interpreter, &callCtx{nil, stack, rstack, nil}) opFn(&pc, interpreter, &callCtx{nil, stack, nil})
actual := stack.pop() actual := stack.pop()
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)} result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
} }
@ -282,7 +281,7 @@ func TestJsonTestcases(t *testing.T) {
func opBenchmark(bench *testing.B, op executionFunc, args ...string) { func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack, rstack = newstack(), newReturnStack() stack = newstack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig) evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
) )
@ -300,7 +299,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
a.SetBytes(arg) a.SetBytes(arg)
stack.push(a) stack.push(a)
} }
op(&pc, evmInterpreter, &callCtx{nil, stack, rstack, nil}) op(&pc, evmInterpreter, &callCtx{nil, stack, nil})
stack.pop() stack.pop()
} }
} }
@ -516,7 +515,7 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) { func TestOpMstore(t *testing.T) {
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack, rstack = newstack(), newReturnStack() stack = newstack()
mem = NewMemory() mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig) evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
) )
@ -526,12 +525,12 @@ func TestOpMstore(t *testing.T) {
pc := uint64(0) pc := uint64(0)
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
stack.pushN(*new(uint256.Int).SetBytes(common.Hex2Bytes(v)), *new(uint256.Int)) stack.pushN(*new(uint256.Int).SetBytes(common.Hex2Bytes(v)), *new(uint256.Int))
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil}) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v { if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
t.Fatalf("Mstore fail, got %v, expected %v", got, v) t.Fatalf("Mstore fail, got %v, expected %v", got, v)
} }
stack.pushN(*new(uint256.Int).SetUint64(0x1), *new(uint256.Int)) stack.pushN(*new(uint256.Int).SetUint64(0x1), *new(uint256.Int))
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil}) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
t.Fatalf("Mstore failed to overwrite previous value") t.Fatalf("Mstore failed to overwrite previous value")
} }
@ -540,7 +539,7 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) { func BenchmarkOpMstore(bench *testing.B) {
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack, rstack = newstack(), newReturnStack() stack = newstack()
mem = NewMemory() mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig) evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
) )
@ -554,14 +553,14 @@ func BenchmarkOpMstore(bench *testing.B) {
bench.ResetTimer() bench.ResetTimer()
for i := 0; i < bench.N; i++ { for i := 0; i < bench.N; i++ {
stack.pushN(*value, *memStart) stack.pushN(*value, *memStart)
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil}) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
} }
} }
func BenchmarkOpSHA3(bench *testing.B) { func BenchmarkOpSHA3(bench *testing.B) {
var ( var (
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
stack, rstack = newstack(), newReturnStack() stack = newstack()
mem = NewMemory() mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig) evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
) )
@ -573,7 +572,7 @@ func BenchmarkOpSHA3(bench *testing.B) {
bench.ResetTimer() bench.ResetTimer()
for i := 0; i < bench.N; i++ { for i := 0; i < bench.N; i++ {
stack.pushN(*uint256.NewInt().SetUint64(32), *start) stack.pushN(*uint256.NewInt().SetUint64(32), *start)
opSha3(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil}) opSha3(&pc, evmInterpreter, &callCtx{mem, stack, nil})
} }
} }

View File

@ -67,7 +67,6 @@ type Interpreter interface {
type callCtx struct { type callCtx struct {
memory *Memory memory *Memory
stack *Stack stack *Stack
rstack *ReturnStack
contract *Contract contract *Contract
} }
@ -164,11 +163,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
op OpCode // current opcode op OpCode // current opcode
mem = NewMemory() // bound memory mem = NewMemory() // bound memory
stack = newstack() // local stack stack = newstack() // local stack
returns = newReturnStack() // local returns stack
callContext = &callCtx{ callContext = &callCtx{
memory: mem, memory: mem,
stack: stack, stack: stack,
rstack: returns,
contract: contract, contract: contract,
} }
// For optimisation reason we're using uint64 as the program counter. // For optimisation reason we're using uint64 as the program counter.
@ -187,7 +184,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// they are returned to the pools // they are returned to the pools
defer func() { defer func() {
returnStack(stack) returnStack(stack)
returnRStack(returns)
}() }()
contract.Input = input contract.Input = input
@ -195,9 +191,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
defer func() { defer func() {
if err != nil { if err != nil {
if !logged { if !logged {
in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, in.returnData, contract, in.evm.depth, err)
} else { } else {
in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, contract, in.evm.depth, err) in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
} }
} }
}() }()
@ -279,7 +275,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
} }
if in.cfg.Debug { if in.cfg.Debug {
in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, in.returnData, contract, in.evm.depth, err)
logged = true logged = true
} }

View File

@ -66,7 +66,6 @@ type JumpTable [256]*operation
// contantinople, istanbul, petersburg and berlin instructions. // contantinople, istanbul, petersburg and berlin instructions.
func newBerlinInstructionSet() JumpTable { func newBerlinInstructionSet() JumpTable {
instructionSet := newIstanbulInstructionSet() instructionSet := newIstanbulInstructionSet()
enable2315(&instructionSet) // Subroutines - https://eips.ethereum.org/EIPS/eip-2315
enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929 enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
return instructionSet return instructionSet
} }

View File

@ -70,7 +70,6 @@ type StructLog struct {
Memory []byte `json:"memory"` Memory []byte `json:"memory"`
MemorySize int `json:"memSize"` MemorySize int `json:"memSize"`
Stack []*big.Int `json:"stack"` Stack []*big.Int `json:"stack"`
ReturnStack []uint32 `json:"returnStack"`
ReturnData []byte `json:"returnData"` ReturnData []byte `json:"returnData"`
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"` Depth int `json:"depth"`
@ -81,7 +80,6 @@ type StructLog struct {
// overrides for gencodec // overrides for gencodec
type structLogMarshaling struct { type structLogMarshaling struct {
Stack []*math.HexOrDecimal256 Stack []*math.HexOrDecimal256
ReturnStack []math.HexOrDecimal64
Gas math.HexOrDecimal64 Gas math.HexOrDecimal64
GasCost math.HexOrDecimal64 GasCost math.HexOrDecimal64
Memory hexutil.Bytes Memory hexutil.Bytes
@ -110,8 +108,8 @@ func (s *StructLog) ErrorString() string {
// if you need to retain them beyond the current call. // if you need to retain them beyond the current call.
type Tracer interface { type Tracer interface {
CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error
CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, rData []byte, contract *Contract, depth int, err error) error CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rData []byte, contract *Contract, depth int, err error) error
CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, contract *Contract, depth int, err error) error CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
} }
@ -148,7 +146,7 @@ func (l *StructLogger) CaptureStart(from common.Address, to common.Address, crea
// CaptureState logs a new structured log message and pushes it out to the environment // CaptureState logs a new structured log message and pushes it out to the environment
// //
// CaptureState also tracks SLOAD/SSTORE ops to track storage change. // CaptureState also tracks SLOAD/SSTORE ops to track storage change.
func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, rData []byte, contract *Contract, depth int, err error) error { func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rData []byte, contract *Contract, depth int, err error) error {
// check if already accumulated the specified number of logs // check if already accumulated the specified number of logs
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
return errTraceLimitReached return errTraceLimitReached
@ -167,11 +165,6 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
stck[i] = new(big.Int).Set(item.ToBig()) stck[i] = new(big.Int).Set(item.ToBig())
} }
} }
var rstack []uint32
if !l.cfg.DisableStack && rStack != nil {
rstck := make([]uint32, len(rStack.data))
copy(rstck, rStack.data)
}
// Copy a snapshot of the current storage to a new container // Copy a snapshot of the current storage to a new container
var storage Storage var storage Storage
if !l.cfg.DisableStorage { if !l.cfg.DisableStorage {
@ -204,14 +197,14 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
copy(rdata, rData) copy(rdata, rData)
} }
// create a new snapshot of the EVM. // create a new snapshot of the EVM.
log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rstack, rdata, storage, depth, env.StateDB.GetRefund(), err} log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, env.StateDB.GetRefund(), err}
l.logs = append(l.logs, log) l.logs = append(l.logs, log)
return nil return nil
} }
// CaptureFault implements the Tracer interface to trace an execution fault // CaptureFault implements the Tracer interface to trace an execution fault
// while running an opcode. // while running an opcode.
func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, contract *Contract, depth int, err error) error { func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
return nil return nil
} }
@ -252,12 +245,6 @@ func WriteTrace(writer io.Writer, logs []StructLog) {
fmt.Fprintf(writer, "%08d %x\n", len(log.Stack)-i-1, math.PaddedBigBytes(log.Stack[i], 32)) fmt.Fprintf(writer, "%08d %x\n", len(log.Stack)-i-1, math.PaddedBigBytes(log.Stack[i], 32))
} }
} }
if len(log.ReturnStack) > 0 {
fmt.Fprintln(writer, "ReturnStack:")
for i := len(log.Stack) - 1; i >= 0; i-- {
fmt.Fprintf(writer, "%08d 0x%x (%d)\n", len(log.Stack)-i-1, log.ReturnStack[i], log.ReturnStack[i])
}
}
if len(log.Memory) > 0 { if len(log.Memory) > 0 {
fmt.Fprintln(writer, "Memory:") fmt.Fprintln(writer, "Memory:")
fmt.Fprint(writer, hex.Dump(log.Memory)) fmt.Fprint(writer, hex.Dump(log.Memory))
@ -323,7 +310,7 @@ func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create b
return nil return nil
} }
func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, rData []byte, contract *Contract, depth int, err error) error { func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rData []byte, contract *Contract, depth int, err error) error {
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost) fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
if !t.cfg.DisableStack { if !t.cfg.DisableStack {
@ -334,14 +321,6 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
} }
b := fmt.Sprintf("[%v]", strings.Join(a, ",")) b := fmt.Sprintf("[%v]", strings.Join(a, ","))
fmt.Fprintf(t.out, "%10v |", b) fmt.Fprintf(t.out, "%10v |", b)
// format return stack
a = a[:0]
for _, elem := range rStack.data {
a = append(a, fmt.Sprintf("%2d", elem))
}
b = fmt.Sprintf("[%v]", strings.Join(a, ","))
fmt.Fprintf(t.out, "%10v |", b)
} }
fmt.Fprintf(t.out, "%10v |", env.StateDB.GetRefund()) fmt.Fprintf(t.out, "%10v |", env.StateDB.GetRefund())
fmt.Fprintln(t.out, "") fmt.Fprintln(t.out, "")
@ -351,7 +330,7 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
return nil return nil
} }
func (t *mdLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, contract *Contract, depth int, err error) error { func (t *mdLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err) fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)

View File

@ -46,7 +46,7 @@ func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create
} }
// CaptureState outputs state information on the logger. // CaptureState outputs state information on the logger.
func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, rData []byte, contract *Contract, depth int, err error) error { func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rData []byte, contract *Contract, depth int, err error) error {
log := StructLog{ log := StructLog{
Pc: pc, Pc: pc,
Op: op, Op: op,
@ -68,7 +68,6 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
logstack[i] = item.ToBig() logstack[i] = item.ToBig()
} }
log.Stack = logstack log.Stack = logstack
log.ReturnStack = rStack.data
} }
if !l.cfg.DisableReturnData { if !l.cfg.DisableReturnData {
log.ReturnData = rData log.ReturnData = rData
@ -77,7 +76,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
} }
// CaptureFault outputs state information on the logger. // CaptureFault outputs state information on the logger.
func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, rStack *ReturnStack, contract *Contract, depth int, err error) error { func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
return nil return nil
} }

View File

@ -55,13 +55,12 @@ func TestStoreCapture(t *testing.T) {
logger = NewStructLogger(nil) logger = NewStructLogger(nil)
mem = NewMemory() mem = NewMemory()
stack = newstack() stack = newstack()
rstack = newReturnStack()
contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0) contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
) )
stack.push(uint256.NewInt().SetUint64(1)) stack.push(uint256.NewInt().SetUint64(1))
stack.push(uint256.NewInt()) stack.push(uint256.NewInt())
var index common.Hash var index common.Hash
logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, rstack, nil, contract, 0, nil) logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, nil, contract, 0, nil)
if len(logger.storage[contract.Address()]) == 0 { if len(logger.storage[contract.Address()]) == 0 {
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.storage[contract.Address()])) t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.storage[contract.Address()]))
} }

View File

@ -119,9 +119,6 @@ const (
MSIZE OpCode = 0x59 MSIZE OpCode = 0x59
GAS OpCode = 0x5a GAS OpCode = 0x5a
JUMPDEST OpCode = 0x5b JUMPDEST OpCode = 0x5b
BEGINSUB OpCode = 0x5c
RETURNSUB OpCode = 0x5d
JUMPSUB OpCode = 0x5e
) )
// 0x60 range. // 0x60 range.
@ -300,10 +297,6 @@ var opCodeToString = map[OpCode]string{
GAS: "GAS", GAS: "GAS",
JUMPDEST: "JUMPDEST", JUMPDEST: "JUMPDEST",
BEGINSUB: "BEGINSUB",
JUMPSUB: "JUMPSUB",
RETURNSUB: "RETURNSUB",
// 0x60 range - push. // 0x60 range - push.
PUSH1: "PUSH1", PUSH1: "PUSH1",
PUSH2: "PUSH2", PUSH2: "PUSH2",
@ -468,9 +461,6 @@ var stringToOp = map[string]OpCode{
"MSIZE": MSIZE, "MSIZE": MSIZE,
"GAS": GAS, "GAS": GAS,
"JUMPDEST": JUMPDEST, "JUMPDEST": JUMPDEST,
"BEGINSUB": BEGINSUB,
"RETURNSUB": RETURNSUB,
"JUMPSUB": JUMPSUB,
"PUSH1": PUSH1, "PUSH1": PUSH1,
"PUSH2": PUSH2, "PUSH2": PUSH2,
"PUSH3": PUSH3, "PUSH3": PUSH3,

View File

@ -98,34 +98,3 @@ func (st *Stack) Print() {
} }
fmt.Println("#############") fmt.Println("#############")
} }
var rStackPool = sync.Pool{
New: func() interface{} {
return &ReturnStack{data: make([]uint32, 0, 10)}
},
}
// ReturnStack is an object for basic return stack operations.
type ReturnStack struct {
data []uint32
}
func newReturnStack() *ReturnStack {
return rStackPool.Get().(*ReturnStack)
}
func returnRStack(rs *ReturnStack) {
rs.data = rs.data[:0]
rStackPool.Put(rs)
}
func (st *ReturnStack) push(d uint32) {
st.data = append(st.data, d)
}
// A uint32 is sufficient as for code below 4.2G
func (st *ReturnStack) pop() (ret uint32) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
}

View File

@ -544,7 +544,7 @@ func (jst *Tracer) CaptureStart(from common.Address, to common.Address, create b
} }
// CaptureState implements the Tracer interface to trace a single step of VM execution. // CaptureState implements the Tracer interface to trace a single step of VM execution.
func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, rStack *vm.ReturnStack, rdata []byte, contract *vm.Contract, depth int, err error) error { func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, rdata []byte, contract *vm.Contract, depth int, err error) error {
if jst.err == nil { if jst.err == nil {
// Initialize the context if it wasn't done yet // Initialize the context if it wasn't done yet
if !jst.inited { if !jst.inited {
@ -595,7 +595,7 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
// CaptureFault implements the Tracer interface to trace an execution fault // CaptureFault implements the Tracer interface to trace an execution fault
// while running an opcode. // while running an opcode.
func (jst *Tracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, rStack *vm.ReturnStack, contract *vm.Contract, depth int, err error) error { func (jst *Tracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
if jst.err == nil { if jst.err == nil {
// Apart from the error, everything matches the previous invocation // Apart from the error, everything matches the previous invocation
jst.errorValue = new(string) jst.errorValue = new(string)

View File

@ -152,10 +152,10 @@ func TestHaltBetweenSteps(t *testing.T) {
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0) contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, nil, contract, 0, nil) tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, contract, 0, nil)
timeout := errors.New("stahp") timeout := errors.New("stahp")
tracer.Stop(timeout) tracer.Stop(timeout)
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, nil, contract, 0, nil) tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, contract, 0, nil)
if _, err := tracer.GetResult(); err.Error() != timeout.Error() { if _, err := tracer.GetResult(); err.Error() != timeout.Error() {
t.Errorf("Expected timeout error, got %v", err) t.Errorf("Expected timeout error, got %v", err)