core,eth: implement tx-level hooks for tracers (#24510)
* core,eth: add empty tx logger hooks * core,eth: add initial and remaining gas to tx hooks * store tx gasLimit in js tracer * use gasLimit to compute intrinsic cost for js tracer * re-use rules in transitiondb * rm logs * rm logs * Mv some fields from Start to TxStart * simplify sender lookup in prestate tracer * mv env to TxStart * Revert "mv env to TxStart" This reverts commit 656939634b9aff19f55a1cd167345faf8b1ec310. * Revert "simplify sender lookup in prestate tracer" This reverts commit ab65bce48007cab99e68232e7aac2fe008338d50. * Revert "Mv some fields from Start to TxStart" This reverts commit aa50d3d9b2559addc80df966111ef5fb5d0c1b6b. * fix intrinsic gas for prestate tracer * add comments * refactor * fix test case * simplify consumedGas calc in prestate tracer
This commit is contained in:
parent
da16d089c0
commit
3fd16af5a9
|
@ -287,15 +287,23 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||||
if err := st.preCheck(); err != nil {
|
if err := st.preCheck(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
msg := st.msg
|
|
||||||
sender := vm.AccountRef(msg.From())
|
if st.evm.Config.Debug {
|
||||||
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
|
st.evm.Config.Tracer.CaptureTxStart(st.initialGas)
|
||||||
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
|
defer func() {
|
||||||
london := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
|
st.evm.Config.Tracer.CaptureTxEnd(st.gas)
|
||||||
contractCreation := msg.To() == nil
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
msg = st.msg
|
||||||
|
sender = vm.AccountRef(msg.From())
|
||||||
|
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil)
|
||||||
|
contractCreation = msg.To() == nil
|
||||||
|
)
|
||||||
|
|
||||||
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
||||||
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, homestead, istanbul)
|
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, rules.IsHomestead, rules.IsIstanbul)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -310,7 +318,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the initial access list.
|
// Set up the initial access list.
|
||||||
if rules := st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil); rules.IsBerlin {
|
if rules.IsBerlin {
|
||||||
st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
|
st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
@ -325,7 +333,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||||
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !london {
|
if !rules.IsLondon {
|
||||||
// Before EIP-3529: refunds were capped to gasUsed / 2
|
// Before EIP-3529: refunds were capped to gasUsed / 2
|
||||||
st.refundGas(params.RefundQuotient)
|
st.refundGas(params.RefundQuotient)
|
||||||
} else {
|
} else {
|
||||||
|
@ -333,7 +341,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||||
st.refundGas(params.RefundQuotientEIP3529)
|
st.refundGas(params.RefundQuotientEIP3529)
|
||||||
}
|
}
|
||||||
effectiveTip := st.gasPrice
|
effectiveTip := st.gasPrice
|
||||||
if london {
|
if rules.IsLondon {
|
||||||
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
|
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
|
||||||
}
|
}
|
||||||
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
|
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
|
||||||
|
|
|
@ -29,10 +29,16 @@ import (
|
||||||
// Note that reference types are actual VM data structures; make copies
|
// Note that reference types are actual VM data structures; make copies
|
||||||
// if you need to retain them beyond the current call.
|
// if you need to retain them beyond the current call.
|
||||||
type EVMLogger interface {
|
type EVMLogger interface {
|
||||||
|
// Transaction level
|
||||||
|
CaptureTxStart(gasLimit uint64)
|
||||||
|
CaptureTxEnd(restGas uint64)
|
||||||
|
// Top call frame
|
||||||
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
|
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
|
||||||
|
// Rest of call frames
|
||||||
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureExit(output []byte, gasUsed uint64, err error)
|
CaptureExit(output []byte, gasUsed uint64, err error)
|
||||||
|
// Opcode level
|
||||||
|
CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
|
||||||
CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
|
CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
|
||||||
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
tracers2 "github.com/ethereum/go-ethereum/eth/tracers"
|
tracers2 "github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
@ -419,6 +418,7 @@ type jsTracer struct {
|
||||||
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
|
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
|
||||||
traceSteps bool // When true, will invoke step() on each opcode
|
traceSteps bool // When true, will invoke step() on each opcode
|
||||||
traceCallFrames bool // When true, will invoke enter() and exit() js funcs
|
traceCallFrames bool // When true, will invoke enter() and exit() js funcs
|
||||||
|
gasLimit uint64 // Amount of gas bought for the whole tx
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a new tracer instance. code specifies a Javascript snippet,
|
// New instantiates a new tracer instance. code specifies a Javascript snippet,
|
||||||
|
@ -679,7 +679,18 @@ func wrapError(context string, err error) error {
|
||||||
return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
|
return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the Tracer interface to initialize the tracing operation.
|
// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
|
||||||
|
// transaction processing.
|
||||||
|
func (jst *jsTracer) CaptureTxStart(gasLimit uint64) {
|
||||||
|
jst.gasLimit = gasLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptureTxStart implements the Tracer interface and is invoked at the end of
|
||||||
|
// transaction processing.
|
||||||
|
func (*jsTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
|
// CaptureStart implements the Tracer interface and is invoked before executing the
|
||||||
|
// top-level call frame of a transaction.
|
||||||
func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
jst.env = env
|
jst.env = env
|
||||||
jst.ctx["type"] = "CALL"
|
jst.ctx["type"] = "CALL"
|
||||||
|
@ -700,14 +711,8 @@ func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
|
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
|
||||||
jst.activePrecompiles = vm.ActivePrecompiles(rules)
|
jst.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
|
|
||||||
// Compute intrinsic gas
|
// Intrinsic costs are the only things reduced from initial gas to this point
|
||||||
isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
|
jst.ctx["intrinsicGas"] = jst.gasLimit - gas
|
||||||
isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
|
|
||||||
intrinsicGas, err := core.IntrinsicGas(input, nil, jst.ctx["type"] == "CREATE", isHomestead, isIstanbul)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jst.ctx["intrinsicGas"] = intrinsicGas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the Tracer interface to trace a single step of VM execution.
|
// CaptureState implements the Tracer interface to trace a single step of VM execution.
|
||||||
|
@ -760,7 +765,7 @@ func (jst *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, sco
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the top-level call finishes.
|
||||||
func (jst *jsTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
func (jst *jsTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
||||||
jst.ctx["output"] = output
|
jst.ctx["output"] = output
|
||||||
jst.ctx["time"] = t.String()
|
jst.ctx["time"] = t.String()
|
||||||
|
|
|
@ -62,15 +62,19 @@ func testCtx() *vmContext {
|
||||||
func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
|
func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
|
||||||
var (
|
var (
|
||||||
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
|
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
gasLimit uint64 = 31000
|
||||||
startGas uint64 = 10000
|
startGas uint64 = 10000
|
||||||
value = big.NewInt(0)
|
value = big.NewInt(0)
|
||||||
contract = vm.NewContract(account{}, account{}, value, startGas)
|
contract = vm.NewContract(account{}, account{}, value, startGas)
|
||||||
)
|
)
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
||||||
|
|
||||||
|
tracer.CaptureTxStart(gasLimit)
|
||||||
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
|
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
|
||||||
ret, err := env.Interpreter().Run(contract, []byte{}, false)
|
ret, err := env.Interpreter().Run(contract, []byte{}, false)
|
||||||
tracer.CaptureEnd(ret, startGas-contract.Gas, 1, err)
|
tracer.CaptureEnd(ret, startGas-contract.Gas, 1, err)
|
||||||
|
// Rest gas assumes no refund
|
||||||
|
tracer.CaptureTxEnd(startGas - contract.Gas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,10 @@ func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
|
func (*AccessListTracer) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*AccessListTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// AccessList returns the current accesslist maintained by the tracer.
|
// AccessList returns the current accesslist maintained by the tracer.
|
||||||
func (a *AccessListTracer) AccessList() types.AccessList {
|
func (a *AccessListTracer) AccessList() types.AccessList {
|
||||||
return a.list.accessList()
|
return a.list.accessList()
|
||||||
|
|
|
@ -223,6 +223,10 @@ func (l *StructLogger) CaptureEnter(typ vm.OpCode, from common.Address, to commo
|
||||||
|
|
||||||
func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
|
func (*StructLogger) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*StructLogger) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// StructLogs returns the captured log entries.
|
// StructLogs returns the captured log entries.
|
||||||
func (l *StructLogger) StructLogs() []StructLog { return l.logs }
|
func (l *StructLogger) StructLogs() []StructLog { return l.logs }
|
||||||
|
|
||||||
|
@ -347,3 +351,7 @@ func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Ad
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
|
func (*mdLogger) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*mdLogger) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
|
@ -98,3 +98,7 @@ func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
|
func (l *JSONLogger) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (l *JSONLogger) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
|
@ -131,6 +131,10 @@ func (t *fourByteTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64,
|
||||||
func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
|
func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*fourByteTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// GetResult returns the json-encoded nested list of call traces, and any
|
// GetResult returns the json-encoded nested list of call traces, and any
|
||||||
// error arising from the encoding or forceful termination (via `Stop`).
|
// error arising from the encoding or forceful termination (via `Stop`).
|
||||||
func (t *fourByteTracer) GetResult() (json.RawMessage, error) {
|
func (t *fourByteTracer) GetResult() (json.RawMessage, error) {
|
||||||
|
|
|
@ -142,6 +142,10 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*callTracer) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*callTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// GetResult returns the json-encoded nested list of call traces, and any
|
// GetResult returns the json-encoded nested list of call traces, and any
|
||||||
// error arising from the encoding or forceful termination (via `Stop`).
|
// error arising from the encoding or forceful termination (via `Stop`).
|
||||||
func (t *callTracer) GetResult() (json.RawMessage, error) {
|
func (t *callTracer) GetResult() (json.RawMessage, error) {
|
||||||
|
|
|
@ -64,6 +64,10 @@ func (t *noopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.
|
||||||
func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*noopTracer) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
|
||||||
|
func (*noopTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// GetResult returns an empty json object.
|
// GetResult returns an empty json object.
|
||||||
func (t *noopTracer) GetResult() (json.RawMessage, error) {
|
func (t *noopTracer) GetResult() (json.RawMessage, error) {
|
||||||
return json.RawMessage(`{}`), nil
|
return json.RawMessage(`{}`), nil
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
@ -47,6 +46,7 @@ type prestateTracer struct {
|
||||||
prestate prestate
|
prestate prestate
|
||||||
create bool
|
create bool
|
||||||
to common.Address
|
to common.Address
|
||||||
|
gasLimit uint64 // Amount of gas bought for the whole tx
|
||||||
interrupt uint32 // Atomic flag to signal execution interruption
|
interrupt uint32 // Atomic flag to signal execution interruption
|
||||||
reason error // Textual reason for the interruption
|
reason error // Textual reason for the interruption
|
||||||
}
|
}
|
||||||
|
@ -63,14 +63,6 @@ func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
|
||||||
t.create = create
|
t.create = create
|
||||||
t.to = to
|
t.to = to
|
||||||
|
|
||||||
// Compute intrinsic gas
|
|
||||||
isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
|
|
||||||
isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
|
|
||||||
intrinsicGas, err := core.IntrinsicGas(input, nil, create, isHomestead, isIstanbul)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.lookupAccount(from)
|
t.lookupAccount(from)
|
||||||
t.lookupAccount(to)
|
t.lookupAccount(to)
|
||||||
|
|
||||||
|
@ -79,17 +71,11 @@ func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
|
||||||
toBal = new(big.Int).Sub(toBal, value)
|
toBal = new(big.Int).Sub(toBal, value)
|
||||||
t.prestate[to].Balance = hexutil.EncodeBig(toBal)
|
t.prestate[to].Balance = hexutil.EncodeBig(toBal)
|
||||||
|
|
||||||
// The sender balance is after reducing: value, gasLimit, intrinsicGas.
|
// The sender balance is after reducing: value and gasLimit.
|
||||||
// We need to re-add them to get the pre-tx balance.
|
// We need to re-add them to get the pre-tx balance.
|
||||||
fromBal := hexutil.MustDecodeBig(t.prestate[from].Balance)
|
fromBal := hexutil.MustDecodeBig(t.prestate[from].Balance)
|
||||||
gasPrice := env.TxContext.GasPrice
|
gasPrice := env.TxContext.GasPrice
|
||||||
consumedGas := new(big.Int).Mul(
|
consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit))
|
||||||
gasPrice,
|
|
||||||
new(big.Int).Add(
|
|
||||||
new(big.Int).SetUint64(intrinsicGas),
|
|
||||||
new(big.Int).SetUint64(gas),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
|
fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
|
||||||
t.prestate[from].Balance = hexutil.EncodeBig(fromBal)
|
t.prestate[from].Balance = hexutil.EncodeBig(fromBal)
|
||||||
t.prestate[from].Nonce--
|
t.prestate[from].Nonce--
|
||||||
|
@ -145,6 +131,12 @@ func (t *prestateTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
|
||||||
func (t *prestateTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
func (t *prestateTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *prestateTracer) CaptureTxStart(gasLimit uint64) {
|
||||||
|
t.gasLimit = gasLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *prestateTracer) CaptureTxEnd(restGas uint64) {}
|
||||||
|
|
||||||
// GetResult returns the json-encoded nested list of call traces, and any
|
// GetResult returns the json-encoded nested list of call traces, and any
|
||||||
// error arising from the encoding or forceful termination (via `Stop`).
|
// error arising from the encoding or forceful termination (via `Stop`).
|
||||||
func (t *prestateTracer) GetResult() (json.RawMessage, error) {
|
func (t *prestateTracer) GetResult() (json.RawMessage, error) {
|
||||||
|
|
Loading…
Reference in New Issue