mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
core/vm: reduce allocations on function call path
This commit is contained in:
parent
c3ef6c77c2
commit
bdcaeb299c
7 changed files with 74 additions and 68 deletions
|
|
@ -47,12 +47,12 @@ type Contract struct {
|
|||
}
|
||||
|
||||
// NewContract returns a new contract environment for the execution of EVM.
|
||||
func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests JumpDestCache) *Contract {
|
||||
func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests JumpDestCache) Contract {
|
||||
// Initialize the jump analysis cache if it's nil, mostly for tests
|
||||
if jumpDests == nil {
|
||||
jumpDests = newMapJumpDests()
|
||||
}
|
||||
return &Contract{
|
||||
return Contract{
|
||||
caller: caller,
|
||||
address: address,
|
||||
jumpDests: jumpDests,
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ type EVM struct {
|
|||
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
|
||||
ScopeContext // Current Run context
|
||||
}
|
||||
|
||||
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||
|
|
@ -294,7 +296,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
contract := NewContract(caller, addr, value, gas, evm.jumpDests)
|
||||
contract.IsSystemCall = isSystemCall(caller)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), code)
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
ret, err = evm.Run(&contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +355,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, caller, value, gas, evm.jumpDests)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
ret, err = evm.Run(&contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -397,7 +399,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
// Note: The value refers to the original value from the parent call.
|
||||
contract := NewContract(originCaller, caller, value, gas, evm.jumpDests)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.Run(contract, input, false)
|
||||
ret, err = evm.Run(&contract, input, false)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -452,7 +454,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
// When an error was returned by the EVM or when setting the creation code
|
||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||
// when we're in Homestead this also counts for code storage gas errors.
|
||||
ret, err = evm.Run(contract, input, true)
|
||||
ret, err = evm.Run(&contract, input, true)
|
||||
gas = contract.Gas
|
||||
}
|
||||
if err != nil {
|
||||
|
|
@ -560,7 +562,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
contract.SetCallCode(common.Hash{}, code)
|
||||
contract.IsDeployment = true
|
||||
|
||||
ret, err = evm.initNewContract(contract, address)
|
||||
ret, err = evm.initNewContract(&contract, address)
|
||||
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
|
|||
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
opFn(&pc, evm, &ScopeContext{Stack: stack})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ func TestAddMod(t *testing.T) {
|
|||
stack.push(z)
|
||||
stack.push(y)
|
||||
stack.push(x)
|
||||
opAddmod(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
opAddmod(&pc, evm, &ScopeContext{Stack: stack})
|
||||
actual := stack.pop()
|
||||
if actual.Cmp(expected) != 0 {
|
||||
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
|
||||
|
|
@ -247,7 +247,7 @@ func TestWriteExpectedValues(t *testing.T) {
|
|||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
opFn(&pc, evm, &ScopeContext{Stack: stack})
|
||||
actual := stack.pop()
|
||||
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
|||
var (
|
||||
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
scope = &ScopeContext{nil, stack, nil}
|
||||
scope = &ScopeContext{Stack: stack}
|
||||
)
|
||||
// convert args
|
||||
intArgs := make([]*uint256.Int, len(args))
|
||||
|
|
@ -528,13 +528,13 @@ func TestOpMstore(t *testing.T) {
|
|||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{Memory: mem, Stack: stack})
|
||||
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).SetUint64(0x1))
|
||||
stack.push(new(uint256.Int))
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{Memory: mem, Stack: stack})
|
||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||
t.Fatalf("Mstore failed to overwrite previous value")
|
||||
}
|
||||
|
|
@ -555,7 +555,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
|||
for i := 0; i < bench.N; i++ {
|
||||
stack.push(value)
|
||||
stack.push(memStart)
|
||||
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
opMstore(&pc, evm, &ScopeContext{Memory: mem, Stack: stack})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -568,7 +568,7 @@ func TestOpTstore(t *testing.T) {
|
|||
caller = common.Address{}
|
||||
to = common.Address{1}
|
||||
contract = NewContract(caller, to, new(uint256.Int), 0, nil)
|
||||
scopeContext = ScopeContext{mem, stack, contract}
|
||||
scopeContext = ScopeContext{Memory: mem, Stack: stack, Contract: contract}
|
||||
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
||||
)
|
||||
|
||||
|
|
@ -613,7 +613,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
|
|||
for i := 0; i < bench.N; i++ {
|
||||
stack.push(uint256.NewInt(32))
|
||||
stack.push(start)
|
||||
opKeccak256(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
opKeccak256(&pc, evm, &ScopeContext{Memory: mem, Stack: stack})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ func TestRandom(t *testing.T) {
|
|||
stack = newstack()
|
||||
pc = uint64(0)
|
||||
)
|
||||
opRandom(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
opRandom(&pc, evm, &ScopeContext{Stack: stack})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||
}
|
||||
|
|
@ -749,7 +749,7 @@ func TestBlobHash(t *testing.T) {
|
|||
)
|
||||
evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
|
||||
stack.push(uint256.NewInt(tt.idx))
|
||||
opBlobHash(&pc, evm, &ScopeContext{nil, stack, nil})
|
||||
opBlobHash(&pc, evm, &ScopeContext{Stack: stack})
|
||||
if len(stack.data) != 1 {
|
||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||
}
|
||||
|
|
@ -889,7 +889,7 @@ func TestOpMCopy(t *testing.T) {
|
|||
mem.Resize(memorySize)
|
||||
}
|
||||
// Do the copy
|
||||
opMcopy(&pc, evm, &ScopeContext{mem, stack, nil})
|
||||
opMcopy(&pc, evm, &ScopeContext{Memory: mem, Stack: stack})
|
||||
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
||||
if have := mem.store; !bytes.Equal(want, have) {
|
||||
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
||||
|
|
@ -911,7 +911,7 @@ func TestPush(t *testing.T) {
|
|||
scope := &ScopeContext{
|
||||
Memory: nil,
|
||||
Stack: newstack(),
|
||||
Contract: &Contract{
|
||||
Contract: Contract{
|
||||
Code: code,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,13 @@ type Config struct {
|
|||
StatelessSelfValidation bool // Generate execution witnesses and self-check against them (testing purpose)
|
||||
}
|
||||
|
||||
// ScopeContext contains the things that are per-call, such as stack and memory,
|
||||
// but not transients like pc and gas
|
||||
// ScopeContext contains the things that are per-call
|
||||
type ScopeContext struct {
|
||||
pc uint64
|
||||
|
||||
Memory *Memory
|
||||
Stack *Stack
|
||||
Contract *Contract
|
||||
Contract Contract
|
||||
}
|
||||
|
||||
// MemoryData returns the underlying memory slice. Callers must not modify the contents
|
||||
|
|
@ -94,9 +95,30 @@ func (ctx *ScopeContext) ContractCode() []byte {
|
|||
// considered a revert-and-consume-all-gas operation except for
|
||||
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
||||
func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
||||
// Don't bother with the execution if there's no code.
|
||||
if len(contract.Code) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Increment the call depth which is restricted to 1024
|
||||
prevContext := evm.ScopeContext
|
||||
evm.ScopeContext = ScopeContext{
|
||||
pc: 0,
|
||||
Memory: NewMemory(),
|
||||
Stack: newstack(),
|
||||
Contract: *contract,
|
||||
}
|
||||
evm.depth++
|
||||
defer func() { evm.depth-- }()
|
||||
defer func() {
|
||||
evm.depth--
|
||||
*contract = evm.Contract
|
||||
// Don't move this deferred function, it's placed before the OnOpcode-deferred method,
|
||||
// so that it gets executed _after_: the OnOpcode needs the stacks before
|
||||
// they are returned to the pools
|
||||
returnStack(evm.Stack)
|
||||
evm.Memory.Free()
|
||||
evm.ScopeContext = prevContext
|
||||
}()
|
||||
|
||||
// Make sure the readOnly is only set if we aren't in readOnly yet.
|
||||
// This also makes sure that the readOnly flag isn't removed for child calls.
|
||||
|
|
@ -109,25 +131,12 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
// as every returning call will return new data anyway.
|
||||
evm.returnData = nil
|
||||
|
||||
// Don't bother with the execution if there's no code.
|
||||
if len(contract.Code) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
op OpCode // current opcode
|
||||
jumpTable *JumpTable = evm.table
|
||||
mem = NewMemory() // bound memory
|
||||
stack = newstack() // local stack
|
||||
callContext = &ScopeContext{
|
||||
Memory: mem,
|
||||
Stack: stack,
|
||||
Contract: contract,
|
||||
}
|
||||
op OpCode // current opcode
|
||||
jumpTable *JumpTable = evm.table
|
||||
// For optimisation reason we're using uint64 as the program counter.
|
||||
// It's theoretically possible to go above 2^64. The YP defines the PC
|
||||
// to be uint256. Practically much less so feasible.
|
||||
pc = uint64(0) // program counter
|
||||
cost uint64
|
||||
// copies used by tracer
|
||||
pcCopy uint64 // needed for the deferred EVMLogger
|
||||
|
|
@ -137,14 +146,7 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
debug = evm.Config.Tracer != nil
|
||||
isEIP4762 = evm.chainRules.IsEIP4762
|
||||
)
|
||||
// Don't move this deferred function, it's placed before the OnOpcode-deferred method,
|
||||
// so that it gets executed _after_: the OnOpcode needs the stacks before
|
||||
// they are returned to the pools
|
||||
defer func() {
|
||||
returnStack(stack)
|
||||
mem.Free()
|
||||
}()
|
||||
contract.Input = input
|
||||
evm.Contract.Input = input
|
||||
|
||||
if debug {
|
||||
defer func() { // this deferred method handles exit-with-error
|
||||
|
|
@ -152,10 +154,10 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
return
|
||||
}
|
||||
if !logged && evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, &evm.ScopeContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
if logged && evm.Config.Tracer.OnFault != nil {
|
||||
evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, evm.depth, VMErrorFromErr(err))
|
||||
evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, &evm.ScopeContext, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -167,14 +169,14 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
for {
|
||||
if debug {
|
||||
// Capture pre-execution values for tracing.
|
||||
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
||||
logged, pcCopy, gasCopy = false, evm.pc, evm.Contract.Gas
|
||||
}
|
||||
|
||||
if isEIP4762 && !contract.IsDeployment && !contract.IsSystemCall {
|
||||
// if the PC ends up in a new "chunk" of verkleized code, charge the
|
||||
// associated costs.
|
||||
contractAddr := contract.Address()
|
||||
consumed, wanted := evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
consumed, wanted := evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, evm.pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
|
|
@ -183,20 +185,20 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
|
||||
// Get the operation from the jump table and validate the stack to ensure there are
|
||||
// enough stack items available to perform the operation.
|
||||
op = contract.GetOp(pc)
|
||||
op = evm.Contract.GetOp(evm.pc)
|
||||
operation := jumpTable[op]
|
||||
cost = operation.constantGas // For tracing
|
||||
// Validate stack
|
||||
if sLen := stack.len(); sLen < operation.minStack {
|
||||
if sLen := evm.Stack.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}
|
||||
}
|
||||
// for tracing: this gas consumption event is emitted below in the debug section.
|
||||
if contract.Gas < cost {
|
||||
if evm.Contract.Gas < cost {
|
||||
return nil, ErrOutOfGas
|
||||
} else {
|
||||
contract.Gas -= cost
|
||||
evm.Contract.Gas -= cost
|
||||
}
|
||||
|
||||
// All ops with a dynamic memory usage also has a dynamic gas cost.
|
||||
|
|
@ -207,7 +209,7 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
// 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(evm.Stack)
|
||||
if overflow {
|
||||
return nil, ErrGasUintOverflow
|
||||
}
|
||||
|
|
@ -220,16 +222,16 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
// Consume the gas and return an error if not enough gas is available.
|
||||
// cost is explicitly set so that the capture state defer method can get the proper cost
|
||||
var dynamicCost uint64
|
||||
dynamicCost, err = operation.dynamicGas(evm, contract, stack, mem, memorySize)
|
||||
dynamicCost, err = operation.dynamicGas(evm, &evm.Contract, evm.Stack, evm.Memory, memorySize)
|
||||
cost += dynamicCost // for tracing
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrOutOfGas, err)
|
||||
}
|
||||
// for tracing: this gas consumption event is emitted below in the debug section.
|
||||
if contract.Gas < dynamicCost {
|
||||
if evm.Contract.Gas < dynamicCost {
|
||||
return nil, ErrOutOfGas
|
||||
} else {
|
||||
contract.Gas -= dynamicCost
|
||||
evm.Contract.Gas -= dynamicCost
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,20 +241,20 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
evm.Config.Tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
}
|
||||
if evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pc, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
evm.Config.Tracer.OnOpcode(evm.pc, byte(op), gasCopy, cost, &evm.ScopeContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
logged = true
|
||||
}
|
||||
}
|
||||
if memorySize > 0 {
|
||||
mem.Resize(memorySize)
|
||||
evm.Memory.Resize(memorySize)
|
||||
}
|
||||
|
||||
// execute the operation
|
||||
res, err = operation.execute(&pc, evm, callContext)
|
||||
res, err = operation.execute(&evm.pc, evm, &evm.ScopeContext)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
pc++
|
||||
evm.pc++
|
||||
}
|
||||
|
||||
if err == errStopToken {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,6 @@ func BenchmarkInterpreter(b *testing.B) {
|
|||
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
gasSStoreEIP3529(evm, contract, stack, mem, 1234)
|
||||
gasSStoreEIP3529(evm, &contract, stack, mem, 1234)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
|
|||
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice}), contract.Caller())
|
||||
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
||||
ret, err := evm.Run(contract, []byte{}, false)
|
||||
ret, err := evm.Run(&contract, []byte{}, false)
|
||||
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
||||
// Rest gas assumes no refund
|
||||
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
||||
|
|
@ -182,8 +182,9 @@ func TestHaltBetweenSteps(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
contract := vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil)
|
||||
scope := &vm.ScopeContext{
|
||||
Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
Contract: contract,
|
||||
}
|
||||
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)})
|
||||
|
|
@ -280,8 +281,9 @@ func TestEnterExit(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
contract := vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil)
|
||||
scope := &vm.ScopeContext{
|
||||
Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
Contract: contract,
|
||||
}
|
||||
tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
|
||||
tracer.OnExit(1, []byte{}, 400, nil, false)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func TestStoreCapture(t *testing.T) {
|
|||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||
var index common.Hash
|
||||
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
||||
_, err := evm.Run(contract, []byte{}, false)
|
||||
_, err := evm.Run(&contract, []byte{}, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue