diff --git a/cmd/state/stateless/deps.go b/cmd/state/stateless/deps.go index 8ac1579d19b4e143f7efa9b2650bf58b7c2e1ab8..52d88d3872b8956cd43b5f6a8f8f33ed72478dd5 100644 --- a/cmd/state/stateless/deps.go +++ b/cmd/state/stateless/deps.go @@ -15,6 +15,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" ) @@ -42,7 +43,7 @@ func NewDepTracer() *DepTracer { func (dt *DepTracer) CaptureStart(depth int, from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error { return nil } -func (dt *DepTracer) CaptureState(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 { +func (dt *DepTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { if op == vm.SSTORE { addr := contract.Address() if stack.Len() == 0 { @@ -72,7 +73,7 @@ func (dt *DepTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cos } return nil } -func (dt *DepTracer) 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 { +func (dt *DepTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { dt.accountsWriteSetFrame = make(map[common.Address]struct{}) dt.storageWriteSetFrame = make(map[common.Address]map[common.Hash]struct{}) return nil diff --git a/cmd/state/stateless/naked_accouts.go b/cmd/state/stateless/naked_accouts.go index 41a6bcd51c884d443fa7693c26dfe04b92df0f55..351b519a41a57dcc282469789125f7575810f103 100644 --- a/cmd/state/stateless/naked_accouts.go +++ b/cmd/state/stateless/naked_accouts.go @@ -20,6 +20,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" ) @@ -41,10 +42,10 @@ func NewAccountsTracer() *AccountsTracer { func (at *AccountsTracer) CaptureStart(depth int, from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error { return nil } -func (at *AccountsTracer) CaptureState(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 { +func (at *AccountsTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } -func (at *AccountsTracer) 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 { +func (at *AccountsTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (at *AccountsTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/cmd/state/stateless/naked_storage.go b/cmd/state/stateless/naked_storage.go index 0871df264945c26c949ceb546ecd6a353509fff4..1ea17bb9fe0a7569715def6084bd903b6baa2127 100644 --- a/cmd/state/stateless/naked_storage.go +++ b/cmd/state/stateless/naked_storage.go @@ -21,6 +21,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" ) @@ -42,7 +43,7 @@ func NewStorageTracer() *StorageTracer { func (st *StorageTracer) CaptureStart(depth int, from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error { return nil } -func (st *StorageTracer) CaptureState(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 { +func (st *StorageTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { if op == vm.SSTORE { addr := contract.Address() if stack.Len() == 0 { @@ -82,7 +83,7 @@ func (st *StorageTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, } return nil } -func (st *StorageTracer) 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 { +func (st *StorageTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (st *StorageTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/cmd/state/stateless/spec_exec.go b/cmd/state/stateless/spec_exec.go index 7d54e375b4075cd59c554a4715e41c4bd3fa1d36..4282cacac10aecf1673e41868c14b5b11c5d7481 100644 --- a/cmd/state/stateless/spec_exec.go +++ b/cmd/state/stateless/spec_exec.go @@ -20,6 +20,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" ) @@ -69,7 +70,7 @@ func (ct *CombTracer) ResetSets() { func (ct *CombTracer) CaptureStart(depth int, from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error { return nil } -func (ct *CombTracer) CaptureState(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 { +func (ct *CombTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { if op == vm.SSTORE { addr := contract.Address() if stack.Len() == 0 { @@ -119,7 +120,7 @@ func (ct *CombTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, co } return nil } -func (ct *CombTracer) 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 { +func (ct *CombTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (ct *CombTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/cmd/state/stateless/state.go b/cmd/state/stateless/state.go index 0eef615050afe5204daa29e9bf8927c732a9d862..cc18c6f13a447aaefc667ff889717167bc52e1ca 100644 --- a/cmd/state/stateless/state.go +++ b/cmd/state/stateless/state.go @@ -33,6 +33,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/types/accounts" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/crypto" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/ethdb/codecpool" @@ -1339,10 +1340,10 @@ func NewCreationTracer(w io.Writer) CreationTracer { func (ct CreationTracer) CaptureStart(depth int, from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error { return nil } -func (ct CreationTracer) CaptureState(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 { +func (ct CreationTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } -func (ct CreationTracer) 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 { +func (ct CreationTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (ct CreationTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/cmd/state/stateless/tokens.go b/cmd/state/stateless/tokens.go index 04e554338193e357e8c66831b846b65d405cc7f2..712bcd3efa1bfc841d70e85b23641b1e7392262c 100644 --- a/cmd/state/stateless/tokens.go +++ b/cmd/state/stateless/tokens.go @@ -15,6 +15,7 @@ import ( "github.com/holiman/uint256" "github.com/ledgerwatch/bolt" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/dbutils" @@ -68,10 +69,10 @@ func (tt TokenTracer) CaptureStart(depth int, from common.Address, to common.Add tt.startMode[depth] = true return nil } -func (tt TokenTracer) CaptureState(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 { +func (tt TokenTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } -func (tt TokenTracer) 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 { +func (tt TokenTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (tt TokenTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/cmd/state/stateless/transaction_stats.go b/cmd/state/stateless/transaction_stats.go index b47479bba2b29a9651e349d9fca27d493602982f..de010a0d721a76551117b93705a7099dd3e988b7 100644 --- a/cmd/state/stateless/transaction_stats.go +++ b/cmd/state/stateless/transaction_stats.go @@ -15,6 +15,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/state" "github.com/ledgerwatch/turbo-geth/core/types" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" ) @@ -94,7 +95,7 @@ func (tt *TxTracer) queryStorageAccess(account common.Address, storageKey common } } -func (tt *TxTracer) CaptureState(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 { +func (tt *TxTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { if tt.measureCreate && tt.measureDepth+1 == depth { tt.gasForCREATE += (tt.measureCurrentGas - gas) } @@ -135,7 +136,7 @@ func (tt *TxTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost } return nil } -func (tt *TxTracer) 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 { +func (tt *TxTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *stack.Stack, contract *vm.Contract, depth int, err error) error { return nil } func (tt *TxTracer) CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error { diff --git a/common/pool/pool_stack.go b/common/pool/pool_stack.go new file mode 100644 index 0000000000000000000000000000000000000000..459a251370df16241fe6f74f0e8f5b2c993ee6f9 --- /dev/null +++ b/common/pool/pool_stack.go @@ -0,0 +1,38 @@ +package pool + +import ( + "sync" + + "github.com/ledgerwatch/turbo-geth/core/vm/stack" +) + +var StackPool = NewStack() + +type Stack struct { + *sync.Pool +} + +const maxCap = 1024 * 2 + +func NewStack() *Stack { + return &Stack{ + &sync.Pool{ + New: func() interface{} { + return stack.New(maxCap) + }, + }, + } +} + +func (p *Stack) Get() *stack.Stack { + return p.Pool.Get().(*stack.Stack) +} + +func (p *Stack) Put(s *stack.Stack) { + if s == nil || s.Cap() == 0 || s.Cap() > maxCap { + return + } + + s.Reset() + p.Pool.Put(s) +} diff --git a/core/vm/eips.go b/core/vm/eips.go index d2290c7cb944fe783b398d2277f9e84d09db9b29..7007813b782f2021533390069cebc1ddbc69c9ae 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -64,7 +64,7 @@ func enable1884(jt *JumpTable) { func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { balance := interpreter.evm.IntraBlockState.GetBalance(callContext.contract.Address()) - callContext.stack.push(balance) + callContext.stack.Push(balance) return nil, nil } @@ -84,7 +84,7 @@ func enable1344(jt *JumpTable) { // opChainID implements CHAINID opcode func opChainID(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { chainID, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID) - callContext.stack.push(chainID) + callContext.stack.Push(chainID) return nil, nil } diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 4aa186dbc53df56a2aebbe7eb561036faae81687..5dd1f8eafb8179c0680e98a5adbb0402d854f813 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -23,6 +23,7 @@ import ( "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/math" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/params" ) @@ -65,7 +66,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { // EXTCODECOPY (stack poition 3) // RETURNDATACOPY (stack position 2) func memoryCopierGas(stackpos int) gasFunc { - return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return func(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { // Gas for expanding the memory gas, err := memoryGasCost(mem, memorySize) if err != nil { @@ -95,7 +96,7 @@ var ( gasReturnDataCopy = memoryCopierGas(2) ) -func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSStore(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { value, x := stack.Back(1), stack.Back(0) key := common.Hash(x.Bytes32()) var current uint256.Int @@ -179,7 +180,7 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi // 2.2.2. If original value equals new value (this storage slot is reset): // 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter. // 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter. -func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { // If we fail the minimum gas availability invariant, fail (0) if contract.Gas <= params.SstoreSentryGasEIP2200 { return 0, errors.New("not enough gas for reentrancy sentry") @@ -223,7 +224,7 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m } func makeGasLog(n uint64) gasFunc { - return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return func(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { requestedSize, overflow := stack.Back(1).Uint64WithOverflow() if overflow { return 0, ErrGasUintOverflow @@ -252,7 +253,7 @@ func makeGasLog(n uint64) gasFunc { } } -func gasSha3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSha3(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err @@ -273,7 +274,7 @@ func gasSha3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize // pureMemoryGascost is used by several operations, which aside from their // static cost have a dynamic cost which is solely based on the memory // expansion -func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func pureMemoryGascost(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { return memoryGasCost(mem, memorySize) } @@ -286,7 +287,7 @@ var ( gasCreate = pureMemoryGascost ) -func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasCreate2(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err @@ -304,8 +305,8 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS return gas, nil } -func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) +func gasExpFrontier(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { + expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8) var ( gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas @@ -317,8 +318,8 @@ func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem return gas, nil } -func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) +func gasExpEIP158(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { + expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8) var ( gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas @@ -330,7 +331,7 @@ func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor return gas, nil } -func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasCall(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { var ( gas uint64 transfersValue = !stack.Back(2).IsZero() @@ -365,7 +366,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize return gas, nil } -func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasCallCode(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { memoryGas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err @@ -390,7 +391,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory return gas, nil } -func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasDelegateCall(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err @@ -406,7 +407,7 @@ func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me return gas, nil } -func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasStaticCall(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { gas, err := memoryGasCost(mem, memorySize) if err != nil { return 0, err @@ -422,7 +423,7 @@ func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo return gas, nil } -func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { +func gasSelfdestruct(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memorySize uint64) (uint64, error) { var gas uint64 // EIP150 homestead gas reprice fork: if evm.chainRules.IsEIP150 { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index a17ef13a300feca734e218d0a1d6306500c70e49..4138616f8709c5d118421fcb0a43b3e4d87214e3 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -26,49 +26,49 @@ import ( ) func opAdd(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Add(&x, y) return nil, nil } func opSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Sub(&x, y) return nil, nil } func opMul(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Mul(&x, y) return nil, nil } func opDiv(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Div(&x, y) return nil, nil } func opSdiv(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.SDiv(&x, y) return nil, nil } func opMod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Mod(&x, y) return nil, nil } func opSmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.SMod(&x, y) return nil, nil } func opExp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - base, exponent := callContext.stack.pop(), callContext.stack.peek() + base, exponent := callContext.stack.Pop(), callContext.stack.Peek() switch { case exponent.IsZero(): // x ^ 0 == 1 @@ -97,20 +97,20 @@ func opExp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt } func opSignExtend(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - back := callContext.stack.pop() - num := callContext.stack.peek() + back := callContext.stack.Pop() + num := callContext.stack.Peek() num.ExtendSign(num, &back) return nil, nil } func opNot(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x := callContext.stack.peek() + x := callContext.stack.Peek() x.Not(x) return nil, nil } func opLt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() if x.Lt(y) { y.SetOne() } else { @@ -120,7 +120,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte } func opGt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() if x.Gt(y) { y.SetOne() } else { @@ -130,7 +130,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte } func opSlt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() if x.Slt(y) { y.SetOne() } else { @@ -140,7 +140,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt } func opSgt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() if x.Sgt(y) { y.SetOne() } else { @@ -150,7 +150,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt } func opEq(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() if x.Eq(y) { y.SetOne() } else { @@ -160,7 +160,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte } func opIszero(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x := callContext.stack.peek() + x := callContext.stack.Peek() if x.IsZero() { x.SetOne() } else { @@ -170,31 +170,31 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([] } func opAnd(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.And(&x, y) return nil, nil } func opOr(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Or(&x, y) return nil, nil } func opXor(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y := callContext.stack.pop(), callContext.stack.peek() + x, y := callContext.stack.Pop(), callContext.stack.Peek() y.Xor(&x, y) return nil, nil } func opByte(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - th, val := callContext.stack.pop(), callContext.stack.peek() + th, val := callContext.stack.Pop(), callContext.stack.Peek() val.Byte(&th) return nil, nil } func opAddmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y, z := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.peek() + x, y, z := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Peek() if z.IsZero() { z.Clear() } else { @@ -204,7 +204,7 @@ func opAddmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([] } func opMulmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x, y, z := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.peek() + x, y, z := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Peek() if z.IsZero() { z.Clear() } else { @@ -218,7 +218,7 @@ func opMulmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([] // and pushes on the stack arg2 shifted to the left by arg1 number of bits. func opSHL(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards - shift, value := callContext.stack.pop(), callContext.stack.peek() + shift, value := callContext.stack.Pop(), callContext.stack.Peek() if shift.LtUint64(256) { value.Lsh(value, uint(shift.Uint64())) } else { @@ -232,7 +232,7 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt // and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill. func opSHR(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards - shift, value := callContext.stack.pop(), callContext.stack.peek() + shift, value := callContext.stack.Pop(), callContext.stack.Peek() if shift.LtUint64(256) { value.Rsh(value, uint(shift.Uint64())) } else { @@ -245,7 +245,7 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt // The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2, // and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension. func opSAR(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - shift, value := callContext.stack.pop(), callContext.stack.peek() + shift, value := callContext.stack.Pop(), callContext.stack.Peek() if shift.GtUint64(255) { if value.Sign() >= 0 { value.Clear() @@ -261,7 +261,7 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt } func opSha3(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - offset, size := callContext.stack.pop(), callContext.stack.peek() + offset, size := callContext.stack.Pop(), callContext.stack.Peek() data := callContext.memory.GetPtr(offset.Uint64(), size.Uint64()) if interpreter.hasher == nil { @@ -281,49 +281,49 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by } func opAddress(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Address().Bytes())) + callContext.stack.Push(new(uint256.Int).SetBytes(callContext.contract.Address().Bytes())) return nil, nil } func opBalance(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - slot := callContext.stack.peek() + slot := callContext.stack.Peek() address := common.Address(slot.Bytes20()) slot.Set(interpreter.evm.IntraBlockState.GetBalance(address)) return nil, nil } func opOrigin(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) + callContext.stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) return nil, nil } func opCaller(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetBytes(callContext.contract.Caller().Bytes())) + callContext.stack.Push(new(uint256.Int).SetBytes(callContext.contract.Caller().Bytes())) return nil, nil } func opCallValue(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(callContext.contract.value) + callContext.stack.Push(callContext.contract.value) return nil, nil } func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - x := callContext.stack.peek() + x := callContext.stack.Peek() data := getDataBig(callContext.contract.Input, x, 32) x.SetBytes(data) return nil, nil } func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(callContext.contract.Input)))) + callContext.stack.Push(new(uint256.Int).SetUint64(uint64(len(callContext.contract.Input)))) return nil, nil } func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - memOffset = callContext.stack.pop() - dataOffset = callContext.stack.pop() - length = callContext.stack.pop() + memOffset = callContext.stack.Pop() + dataOffset = callContext.stack.Pop() + length = callContext.stack.Pop() ) len64 := length.Uint64() callContext.memory.Set(memOffset.Uint64(), len64, getDataBig(callContext.contract.Input, &dataOffset, len64)) @@ -331,15 +331,15 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCt } func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) + callContext.stack.Push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) return nil, nil } func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - memOffset = callContext.stack.pop() - dataOffset = callContext.stack.pop() - length = callContext.stack.pop() + memOffset = callContext.stack.Pop() + dataOffset = callContext.stack.Pop() + length = callContext.stack.Pop() ) offset64, overflow := dataOffset.Uint64WithOverflow() @@ -364,7 +364,7 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, callContext *call } func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - slot := callContext.stack.peek() + slot := callContext.stack.Peek() slot.SetUint64(uint64(interpreter.evm.IntraBlockState.GetCodeSize(common.Address(slot.Bytes20())))) return nil, nil @@ -373,16 +373,16 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx func opCodeSize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { l := new(uint256.Int) l.SetUint64(uint64(len(callContext.contract.Code))) - callContext.stack.push(l) + callContext.stack.Push(l) return nil, nil } func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - memOffset = callContext.stack.pop() - codeOffset = callContext.stack.pop() - length = callContext.stack.pop() + memOffset = callContext.stack.Pop() + codeOffset = callContext.stack.Pop() + length = callContext.stack.Pop() ) len64 := length.Uint64() codeCopy := getDataBig(callContext.contract.Code, &codeOffset, len64) @@ -392,10 +392,10 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ( func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - a = callContext.stack.pop() - memOffset = callContext.stack.pop() - codeOffset = callContext.stack.pop() - length = callContext.stack.pop() + a = callContext.stack.Pop() + memOffset = callContext.stack.Pop() + codeOffset = callContext.stack.Pop() + length = callContext.stack.Pop() ) addr := common.Address(a.Bytes20()) len64 := length.Uint64() @@ -431,7 +431,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx // (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, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - slot := callContext.stack.peek() + slot := callContext.stack.Peek() address := common.Address(slot.Bytes20()) if interpreter.evm.IntraBlockState.Empty(address) { slot.Clear() @@ -443,12 +443,12 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx func opGasprice(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.GasPrice) - callContext.stack.push(v) + callContext.stack.Push(v) return nil, nil } func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - num := callContext.stack.peek() + num := callContext.stack.Peek() num64, overflow := num.Uint64WithOverflow() if overflow { num.Clear() @@ -468,74 +468,74 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) } func opCoinbase(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Coinbase.Bytes())) + callContext.stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Coinbase.Bytes())) return nil, nil } func opTimestamp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.Time) - callContext.stack.push(v) + callContext.stack.Push(v) return nil, nil } func opNumber(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.BlockNumber) - callContext.stack.push(v) + callContext.stack.Push(v) return nil, nil } func opDifficulty(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.Difficulty) - callContext.stack.push(v) + callContext.stack.Push(v) return nil, nil } func opGasLimit(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetUint64(interpreter.evm.GasLimit)) + callContext.stack.Push(new(uint256.Int).SetUint64(interpreter.evm.GasLimit)) return nil, nil } func opPop(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.pop() + callContext.stack.Pop() return nil, nil } func opMload(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - v := callContext.stack.peek() + v := callContext.stack.Peek() offset := v.Uint64() v.SetBytes(callContext.memory.GetPtr(offset, 32)) return nil, nil } func opMstore(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - mStart, val := callContext.stack.pop(), callContext.stack.pop() + mStart, val := callContext.stack.Pop(), callContext.stack.Pop() callContext.memory.Set32(mStart.Uint64(), &val) return nil, nil } func opMstore8(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - off, val := callContext.stack.pop(), callContext.stack.pop() + off, val := callContext.stack.Pop(), callContext.stack.Pop() callContext.memory.store[off.Uint64()] = byte(val.Uint64() & 0xff) return nil, nil } func opSload(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - loc := callContext.stack.peek() + loc := callContext.stack.Peek() interpreter.hasherBuf = loc.Bytes32() interpreter.evm.IntraBlockState.GetState(callContext.contract.Address(), &interpreter.hasherBuf, loc) return nil, nil } func opSstore(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - loc := callContext.stack.pop() - val := callContext.stack.pop() + loc := callContext.stack.Pop() + val := callContext.stack.Pop() interpreter.hasherBuf = loc.Bytes32() interpreter.evm.IntraBlockState.SetState(callContext.contract.Address(), &interpreter.hasherBuf, val) return nil, nil } func opJump(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - pos := callContext.stack.pop() + pos := callContext.stack.Pop() if !callContext.contract.validJumpdest(&pos) { return nil, ErrInvalidJump } @@ -545,7 +545,7 @@ func opJump(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by } func opJumpi(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - pos, cond := callContext.stack.pop(), callContext.stack.pop() + pos, cond := callContext.stack.Pop(), callContext.stack.Pop() if !cond.IsZero() { if !callContext.contract.validJumpdest(&pos) { return nil, ErrInvalidJump @@ -563,25 +563,25 @@ func opJumpdest(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ( } 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 } func opMsize(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetUint64(uint64(callContext.memory.Len()))) + callContext.stack.Push(new(uint256.Int).SetUint64(uint64(callContext.memory.Len()))) return nil, nil } func opGas(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.push(new(uint256.Int).SetUint64(callContext.contract.Gas)) + callContext.stack.Push(new(uint256.Int).SetUint64(callContext.contract.Gas)) return nil, nil } func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - value = callContext.stack.pop() - offset = callContext.stack.pop() - size = callContext.stack.peek() + value = callContext.stack.Pop() + offset = callContext.stack.Pop() + size = callContext.stack.Peek() input = callContext.memory.GetCopy(offset.Uint64(), size.Uint64()) gas = callContext.contract.Gas ) @@ -615,9 +615,9 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([] func opCreate2(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { var ( - endowment = callContext.stack.pop() - offset, size = callContext.stack.pop(), callContext.stack.pop() - salt = callContext.stack.peek() + endowment = callContext.stack.Pop() + offset, size = callContext.stack.Pop(), callContext.stack.Pop() + salt = callContext.stack.Peek() input = callContext.memory.GetCopy(offset.Uint64(), size.Uint64()) gas = callContext.contract.Gas ) @@ -645,11 +645,11 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([ func opCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Pop gas. The actual gas in interpreter.evm.callGasTemp. - callContext.stack.pop() + callContext.stack.Pop() gas := interpreter.evm.callGasTemp // Pop other call parameters. - addr, value, inOffset, inSize, retOffset := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() - retSize := callContext.stack.peek() + addr, value, inOffset, inSize, retOffset := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop() + retSize := callContext.stack.Peek() toAddr := common.Address(addr.Bytes20()) // Get the arguments from the memory. args := callContext.memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) @@ -673,11 +673,11 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by func opCallCode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - callContext.stack.pop() + callContext.stack.Pop() gas := interpreter.evm.callGasTemp // Pop other call parameters. - addr, value, inOffset, inSize, retOffset := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() - retSize := callContext.stack.peek() + addr, value, inOffset, inSize, retOffset := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop() + retSize := callContext.stack.Peek() toAddr := common.Address(addr.Bytes20()) // Get arguments from the memory. args := callContext.memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) @@ -701,11 +701,11 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ( func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - callContext.stack.pop() + callContext.stack.Pop() gas := interpreter.evm.callGasTemp // Pop other call parameters. - addr, inOffset, inSize, retOffset := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() - retSize := callContext.stack.peek() + addr, inOffset, inSize, retOffset := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop() + retSize := callContext.stack.Peek() toAddr := common.Address(addr.Bytes20()) // Get arguments from the memory. args := callContext.memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) @@ -726,11 +726,11 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCt func opStaticCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - callContext.stack.pop() + callContext.stack.Pop() gas := interpreter.evm.callGasTemp // Pop other call parameters. - addr, inOffset, inSize, retOffset := callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop(), callContext.stack.pop() - retSize := callContext.stack.peek() + addr, inOffset, inSize, retOffset := callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop(), callContext.stack.Pop() + retSize := callContext.stack.Peek() toAddr := common.Address(addr.Bytes20()) // Get arguments from the memory. args := callContext.memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) @@ -750,13 +750,13 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) } func opReturn(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - offset, size := callContext.stack.pop(), callContext.stack.pop() + offset, size := callContext.stack.Pop(), callContext.stack.Pop() ret := callContext.memory.GetPtr(offset.Uint64(), size.Uint64()) return ret, nil } func opRevert(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - offset, size := callContext.stack.pop(), callContext.stack.pop() + offset, size := callContext.stack.Pop(), callContext.stack.Pop() ret := callContext.memory.GetPtr(offset.Uint64(), size.Uint64()) return ret, nil } @@ -766,7 +766,7 @@ func opStop(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by } func opSuicide(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - beneficiary := callContext.stack.pop() + beneficiary := callContext.stack.Pop() balance := interpreter.evm.IntraBlockState.GetBalance(callContext.contract.Address()) interpreter.evm.IntraBlockState.AddBalance(common.Address(beneficiary.Bytes20()), balance) @@ -780,9 +780,9 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([ func makeLog(size int) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { topics := make([]common.Hash, size) - mStart, mSize := callContext.stack.pop(), callContext.stack.pop() + mStart, mSize := callContext.stack.Pop(), callContext.stack.Pop() for i := 0; i < size; i++ { - topic := callContext.stack.pop() + topic := callContext.stack.Pop() topics[i] = common.Hash(topic.Bytes32()) } @@ -808,9 +808,9 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]b ) *pc++ if *pc < codeLen { - callContext.stack.push(integer.SetUint64(uint64(callContext.contract.Code[*pc]))) + callContext.stack.Push(integer.SetUint64(uint64(callContext.contract.Code[*pc]))) } else { - callContext.stack.push(integer) + callContext.stack.Push(integer) } return nil, nil } @@ -831,7 +831,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { } integer := new(uint256.Int) - callContext.stack.push(integer.SetBytes(common.RightPadBytes(callContext.contract.Code[startMin:endMin], pushByteSize))) + callContext.stack.Push(integer.SetBytes(common.RightPadBytes(callContext.contract.Code[startMin:endMin], pushByteSize))) *pc += size return nil, nil @@ -841,7 +841,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { // make dup instruction function func makeDup(size int64) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.dup(int(size)) + callContext.stack.Dup(int(size)) return nil, nil } } @@ -851,7 +851,7 @@ func makeSwap(size int64) executionFunc { // switch n + 1 otherwise n would be swapped with n size++ return func(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { - callContext.stack.swap(int(size)) + callContext.stack.Swap(int(size)) return nil, nil } } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 5379bfb03ac65d9fc8bc4176d13f61ebfd5c7dd5..3b27658c49235821d165dbd2ede67f49c237f765 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -26,6 +26,7 @@ import ( "github.com/holiman/uint256" "github.com/ledgerwatch/turbo-geth/common" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/crypto" "github.com/ledgerwatch/turbo-geth/params" ) @@ -94,7 +95,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() pc = uint64(0) evmInterpreter = env.interpreter.(*EVMInterpreter) ) @@ -103,10 +104,10 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected)) - stack.push(x) - stack.push(y) + stack.Push(x) + stack.Push(y) opFn(&pc, evmInterpreter, &callCtx{nil, stack, nil}) - actual := stack.pop() + actual := stack.Pop() if actual.Cmp(expected) != 0 { t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, &actual) @@ -191,7 +192,7 @@ func TestSAR(t *testing.T) { func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() pc = uint64(0) interpreter = env.interpreter.(*EVMInterpreter) ) @@ -199,10 +200,10 @@ func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcas for i, param := range args { x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y)) - stack.push(x) - stack.push(y) + stack.Push(x) + stack.Push(y) opFn(&pc, interpreter, &callCtx{nil, stack, nil}) - actual := stack.pop() + actual := stack.Pop() result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)} } return result @@ -241,7 +242,7 @@ func TestJsonTestcases(t *testing.T) { func opBenchmark(bench *testing.B, op executionFunc, args ...string) { var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -256,10 +257,10 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) { for i := 0; i < bench.N; i++ { for _, arg := range byteArgs { a := new(uint256.Int).SetBytes(arg) - stack.push(a) + stack.Push(a) } op(&pc, evmInterpreter, &callCtx{nil, stack, nil}) - stack.pop() + stack.Pop() } } @@ -474,7 +475,7 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -483,14 +484,14 @@ func TestOpMstore(t *testing.T) { mem.Resize(64) pc := uint64(0) v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" - stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) - stack.push(new(uint256.Int)) + stack.Push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) + stack.Push(new(uint256.Int)) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil}) if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v { t.Fatalf("Mstore fail, got %v, expected %v", got, v) } - stack.push(new(uint256.Int).SetOne()) - stack.push(new(uint256.Int)) + stack.Push(new(uint256.Int).SetOne()) + stack.Push(new(uint256.Int)) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil}) if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { t.Fatalf("Mstore failed to overwrite previous value") @@ -500,7 +501,7 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -513,8 +514,8 @@ func BenchmarkOpMstore(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(value) - stack.push(memStart) + stack.Push(value) + stack.Push(memStart) opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil}) } } @@ -522,7 +523,7 @@ func BenchmarkOpMstore(bench *testing.B) { func BenchmarkOpSHA3(bench *testing.B) { var ( env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + stack = stack.New() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -533,8 +534,8 @@ func BenchmarkOpSHA3(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(uint256.NewInt().SetUint64(32)) - stack.push(start) + stack.Push(uint256.NewInt().SetUint64(32)) + stack.Push(start) opSha3(&pc, evmInterpreter, &callCtx{mem, stack, nil}) } } @@ -600,9 +601,9 @@ func TestCreate2Addreses(t *testing.T) { /* stack := newstack() // salt, but we don't need that for this test - stack.push(big.NewInt(int64(len(code)))) //size - stack.push(big.NewInt(0)) // memstart - stack.push(big.NewInt(0)) // value + stack.Push(big.NewInt(int64(len(code)))) //size + stack.Push(big.NewInt(0)) // memstart + stack.Push(big.NewInt(0)) // value gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0) fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String()) */ diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 41df4c18a3200c80ec6925538bb5ea75bd6869b7..3b3431bfa7e9aad262637fca073121259b8cbfac 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -22,6 +22,8 @@ import ( "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/math" + "github.com/ledgerwatch/turbo-geth/common/pool" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/log" ) @@ -64,7 +66,7 @@ type Interpreter interface { // but not transients like pc and gas type callCtx struct { memory *Memory - stack *Stack + stack *stack.Stack contract *Contract } @@ -158,10 +160,10 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( var ( op OpCode // current opcode mem = NewMemory() // bound memory - stack = newstack() // local stack + locStack = pool.StackPool.Get() callContext = &callCtx{ memory: mem, - stack: stack, + stack: locStack, contract: contract, } // For optimisation reason we're using uint64 as the program counter. @@ -175,15 +177,16 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( logged bool // deferred Tracer should ignore already logged steps res []byte // result of the opcode execution function ) + defer pool.StackPool.Put(locStack) contract.Input = input if in.cfg.Debug { defer func() { if err != nil { if !logged { - in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + _ = in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, locStack, contract, in.evm.depth, err) } else { - in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + _ = in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, locStack, contract, in.evm.depth, err) } } }() @@ -212,7 +215,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( return nil, &ErrInvalidOpCode{opcode: op} } // Validate stack - if sLen := stack.len(); sLen < operation.minStack { + if sLen := locStack.Len(); sLen < operation.minStack { return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} } else if sLen > operation.maxStack { return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} @@ -224,7 +227,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // for a call operation is the value. Transferring value from one // account to the others means the state is modified and should also // return with an error. - if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { + if operation.writes || (op == CALL && locStack.Back(2).Sign() != 0) { return nil, ErrWriteProtection } } @@ -240,7 +243,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // Memory check needs to be done prior to evaluating the dynamic gas portion, // to detect calculation overflows if operation.memorySize != nil { - memSize, overflow := operation.memorySize(stack) + memSize, overflow := operation.memorySize(locStack) if overflow { return nil, ErrGasUintOverflow } @@ -255,7 +258,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // cost is explicitly set so that the capture state defer method can get the proper cost if operation.dynamicGas != nil { var dynamicCost uint64 - dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize) + dynamicCost, err = operation.dynamicGas(in.evm, contract, locStack, mem, memorySize) cost += dynamicCost // total cost, for debug tracing if err != nil || !contract.UseGas(dynamicCost) { return nil, ErrOutOfGas @@ -266,7 +269,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } if in.cfg.Debug { - in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + _ = in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, locStack, contract, in.evm.depth, err) logged = true } diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index b05f95c36b6d63e7c406a103de43cb9e1809c60f..e1201c507b67fc574f52f7b234eeb63504c82725 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -17,14 +17,15 @@ package vm import ( + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/params" ) type ( executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) - gasFunc func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 + gasFunc func(*EVM, *Contract, *stack.Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 // memorySizeFunc returns the required size, and whether the operation overflowed a uint64 - memorySizeFunc func(*Stack) (size uint64, overflow bool) + memorySizeFunc func(*stack.Stack) (size uint64, overflow bool) ) type operation struct { diff --git a/core/vm/logger.go b/core/vm/logger.go index 2b5c85b229f982bb9582a624569263aabd7c5d80..d2956f6f0db84510170b0c0883b827e2654e950e 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -28,6 +28,7 @@ import ( "github.com/ledgerwatch/turbo-geth/common/hexutil" "github.com/ledgerwatch/turbo-geth/common/math" "github.com/ledgerwatch/turbo-geth/core/types" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" ) var errTraceLimitReached = errors.New("the number of logs reached the specified limit") @@ -102,8 +103,8 @@ func (s *StructLog) ErrorString() string { // if you need to retain them beyond the current call. type Tracer interface { CaptureStart(depth int, 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, 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 + CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error + CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error CaptureEnd(depth int, output []byte, gasUsed uint64, t time.Duration, err error) error CaptureCreate(creator common.Address, creation common.Address) error CaptureAccountRead(account common.Address) error @@ -143,7 +144,7 @@ func (l *StructLogger) CaptureStart(depth int, from common.Address, to common.Ad // CaptureState logs a new structured log message and pushes it out to the environment // // CaptureState also tracks SSTORE ops to track dirty values. -func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error { // check if already accumulated the specified number of logs if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { return errTraceLimitReached @@ -157,10 +158,10 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui // capture SSTORE opcodes and determine the changed value and store // it in the local storage container. - if op == SSTORE && stack.len() >= 2 { + if op == SSTORE && stack.Len() >= 2 { var ( - value = common.Hash(stack.data[stack.len()-2].Bytes32()) - address = common.Hash(stack.data[stack.len()-1].Bytes32()) + value = common.Hash(stack.Data[stack.Len()-2].Bytes32()) + address = common.Hash(stack.Data[stack.Len()-1].Bytes32()) ) l.changedValues[contract.Address()][address] = value } @@ -173,8 +174,8 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui // Copy a snapshot of the current stack state to a new buffer var stck []*big.Int if !l.cfg.DisableStack { - stck = make([]*big.Int, len(stack.Data())) - for i, item := range stack.Data() { + stck = make([]*big.Int, len(stack.GetData())) + for i, item := range stack.GetData() { stck[i] = item.ToBig() } } @@ -192,7 +193,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui // CaptureFault implements the Tracer interface to trace an execution fault // while running an opcode. -func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error { return nil } diff --git a/core/vm/logger_json.go b/core/vm/logger_json.go index 421571ef7f5a47fdc9b73c905fb36668eedb4e99..6c2a490a789ef80036f7d88d5f2f9ebfa1d773df 100644 --- a/core/vm/logger_json.go +++ b/core/vm/logger_json.go @@ -24,6 +24,7 @@ import ( "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/math" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" ) type JSONLogger struct { @@ -46,7 +47,7 @@ func (l *JSONLogger) CaptureStart(depth int, from common.Address, to common.Addr } // CaptureState outputs state information on the logger. -func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error { log := StructLog{ Pc: pc, Op: op, @@ -62,8 +63,8 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint log.Memory = memory.Data() } if !l.cfg.DisableStack { - log.Stack = make([]*big.Int, len(stack.Data())) - for i, item := range stack.Data() { + log.Stack = make([]*big.Int, len(stack.GetData())) + for i, item := range stack.GetData() { log.Stack[i] = item.ToBig() } } @@ -71,7 +72,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint } // CaptureFault outputs state information on the logger. -func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *stack.Stack, contract *Contract, depth int, err error) error { return nil } diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go index 96a09555ff064a414c1f9e4f36b9757211579b08..8b4fc7b251d58f4e13737cbd8ac5588c578d2851 100644 --- a/core/vm/logger_test.go +++ b/core/vm/logger_test.go @@ -24,6 +24,7 @@ import ( "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/core/state" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/params" ) @@ -55,11 +56,11 @@ func TestStoreCapture(t *testing.T) { env = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{}) logger = NewStructLogger(nil) mem = NewMemory() - stack = newstack() + stack = stack.New() contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 0) ) - stack.push(uint256.NewInt().SetOne()) - stack.push(uint256.NewInt()) + stack.Push(uint256.NewInt().SetOne()) + stack.Push(uint256.NewInt()) var index common.Hash logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, contract, 0, nil) if len(logger.changedValues[contract.Address()]) == 0 { diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 4fcb41442c4e28a593a80b20e5caba007fd641cb..4b0007eda7cfc3e007cb3887ee84c6aa1aeac63f 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -16,47 +16,49 @@ package vm -func memorySha3(stack *Stack) (uint64, bool) { +import "github.com/ledgerwatch/turbo-geth/core/vm/stack" + +func memorySha3(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryCallDataCopy(stack *Stack) (uint64, bool) { +func memoryCallDataCopy(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryReturnDataCopy(stack *Stack) (uint64, bool) { +func memoryReturnDataCopy(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryCodeCopy(stack *Stack) (uint64, bool) { +func memoryCodeCopy(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(2)) } -func memoryExtCodeCopy(stack *Stack) (uint64, bool) { +func memoryExtCodeCopy(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(1), stack.Back(3)) } -func memoryMLoad(stack *Stack) (uint64, bool) { +func memoryMLoad(stack *stack.Stack) (uint64, bool) { return calcMemSize64WithUint(stack.Back(0), 32) } -func memoryMStore8(stack *Stack) (uint64, bool) { +func memoryMStore8(stack *stack.Stack) (uint64, bool) { return calcMemSize64WithUint(stack.Back(0), 1) } -func memoryMStore(stack *Stack) (uint64, bool) { +func memoryMStore(stack *stack.Stack) (uint64, bool) { return calcMemSize64WithUint(stack.Back(0), 32) } -func memoryCreate(stack *Stack) (uint64, bool) { +func memoryCreate(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(1), stack.Back(2)) } -func memoryCreate2(stack *Stack) (uint64, bool) { +func memoryCreate2(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(1), stack.Back(2)) } -func memoryCall(stack *Stack) (uint64, bool) { +func memoryCall(stack *stack.Stack) (uint64, bool) { x, overflow := calcMemSize64(stack.Back(5), stack.Back(6)) if overflow { return 0, true @@ -70,7 +72,7 @@ func memoryCall(stack *Stack) (uint64, bool) { } return y, false } -func memoryDelegateCall(stack *Stack) (uint64, bool) { +func memoryDelegateCall(stack *stack.Stack) (uint64, bool) { x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) if overflow { return 0, true @@ -85,7 +87,7 @@ func memoryDelegateCall(stack *Stack) (uint64, bool) { return y, false } -func memoryStaticCall(stack *Stack) (uint64, bool) { +func memoryStaticCall(stack *stack.Stack) (uint64, bool) { x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) if overflow { return 0, true @@ -100,14 +102,14 @@ func memoryStaticCall(stack *Stack) (uint64, bool) { return y, false } -func memoryReturn(stack *Stack) (uint64, bool) { +func memoryReturn(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryRevert(stack *Stack) (uint64, bool) { +func memoryRevert(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(1)) } -func memoryLog(stack *Stack) (uint64, bool) { +func memoryLog(stack *stack.Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(1)) } diff --git a/core/vm/stack.go b/core/vm/stack/stack.go similarity index 64% rename from core/vm/stack.go rename to core/vm/stack/stack.go index 687b05632bf33938afe1dbcb0ae0f383f96e80c9..f336c17d4347c977dd5f9bed6b000aca638b83b6 100644 --- a/core/vm/stack.go +++ b/core/vm/stack/stack.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. -package vm +package stack import ( "fmt" @@ -26,59 +26,66 @@ import ( // expected to be changed and modified. stack does not take care of adding newly // initialised objects. type Stack struct { - data []uint256.Int + Data []uint256.Int } -func newstack() *Stack { +func New(n ...int) *Stack { + if len(n) > 0 { + return &Stack{make([]uint256.Int, 0, n[0])} + } return &Stack{} } // Data returns the underlying uint256.Int array. -func (st *Stack) Data() []uint256.Int { - return st.data +func (st *Stack) GetData() []uint256.Int { + return st.Data } -func (st *Stack) push(d *uint256.Int) { +func (st *Stack) Push(d *uint256.Int) { // NOTE push limit (1024) is checked in baseCheck - st.data = append(st.data, *d) + st.Data = append(st.Data, *d) } -func (st *Stack) pop() (ret uint256.Int) { - ret = st.data[len(st.data)-1] - st.data = st.data[:len(st.data)-1] - return +func (st *Stack) Pop() uint256.Int { + ret := st.Data[len(st.Data)-1] + st.Data = st.Data[:len(st.Data)-1] + return ret } -func (st *Stack) len() int { - return len(st.data) +func (st *Stack) Len() int { + return len(st.Data) } -func (st *Stack) Len() int { - return len(st.data) +func (st *Stack) Cap() int { + return cap(st.Data) } -func (st *Stack) swap(n int) { - st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n] +func (st *Stack) Swap(n int) { + st.Data[st.Len()-n], st.Data[st.Len()-1] = st.Data[st.Len()-1], st.Data[st.Len()-n] } -func (st *Stack) dup(n int) { - st.push(&st.data[st.len()-n]) +func (st *Stack) Dup(n int) { + st.Push(&st.Data[st.Len()-n]) } -func (st *Stack) peek() *uint256.Int { - return &st.data[st.len()-1] +func (st *Stack) Peek() *uint256.Int { + return &st.Data[st.Len()-1] } // Back returns the n'th item in stack func (st *Stack) Back(n int) *uint256.Int { - return &st.data[st.len()-n-1] + return &st.Data[st.Len()-n-1] +} + +func (st *Stack) Reset() { + st.Data = st.Data[:0] } // Print dumps the content of the stack func (st *Stack) Print() { fmt.Println("### stack ###") - if len(st.data) > 0 { - for i, val := range st.data { + if len(st.Data) > 0 { + for i, val := range st.Data { fmt.Printf("%-3d %v\n", i, val) } } else { diff --git a/eth/tracers/tracer.go b/eth/tracers/tracer.go index 81f8b11968de286651cd6fc37571c5a9a0e1f78b..093b7359c4869fc4bcdbd40ce090b223d5e9f650 100644 --- a/eth/tracers/tracer.go +++ b/eth/tracers/tracer.go @@ -26,11 +26,12 @@ import ( "unsafe" "github.com/holiman/uint256" - duktape "gopkg.in/olebedev/go-duktape.v3" + "gopkg.in/olebedev/go-duktape.v3" "github.com/ledgerwatch/turbo-geth/common" "github.com/ledgerwatch/turbo-geth/common/hexutil" "github.com/ledgerwatch/turbo-geth/core/vm" + "github.com/ledgerwatch/turbo-geth/core/vm/stack" "github.com/ledgerwatch/turbo-geth/crypto" "github.com/ledgerwatch/turbo-geth/log" ) @@ -153,15 +154,15 @@ func (mw *memoryWrapper) pushObject(vm *duktape.Context) { // stackWrapper provides a JavaScript wrapper around vm.Stack. type stackWrapper struct { - stack *vm.Stack + stack *stack.Stack } // peek returns the nth-from-the-top element of the stack. func (sw *stackWrapper) peek(idx int) *big.Int { - if len(sw.stack.Data()) <= idx || idx < 0 { + if len(sw.stack.GetData()) <= idx || idx < 0 { // TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go // runtime goes belly up https://github.com/golang/go/issues/15639. - log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx) + log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.GetData()), "index", idx) return new(big.Int) } return sw.stack.Back(idx).ToBig() @@ -172,7 +173,7 @@ func (sw *stackWrapper) peek(idx int) *big.Int { func (sw *stackWrapper) pushObject(vm *duktape.Context) { obj := vm.PushObject() - vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.Data())); return 1 }) + vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.GetData())); return 1 }) vm.PutPropString(obj, "length") // Generate the `peek` method which takes an int and returns a bigint @@ -548,7 +549,7 @@ func (jst *Tracer) CaptureStart(depth int, from common.Address, to common.Addres } // 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, 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 *stack.Stack, contract *vm.Contract, depth int, err error) error { if jst.err == nil { // Initialize the context if it wasn't done yet if !jst.inited { @@ -587,7 +588,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 // 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, 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 *stack.Stack, contract *vm.Contract, depth int, err error) error { if jst.err == nil { // Apart from the error, everything matches the previous invocation jst.errorValue = new(string)