[tracer] change tracer to apply to block instead of tx

pull/3818/head
peekpi 3 years ago
parent 61263c6572
commit b2472d87c0
  1. 3
      api/service/explorer/storage.go
  2. 112
      hmy/tracers/block_tracer.go

@ -180,6 +180,7 @@ type taskManager struct {
func newTaskManager() *taskManager { func newTaskManager() *taskManager {
return &taskManager{ return &taskManager{
C: make(chan struct{}, numWorker), C: make(chan struct{}, numWorker),
T: make(chan *traceResult, numWorker),
} }
} }
@ -292,7 +293,7 @@ LOOP:
} }
case traceData := <-bc.tm.T: case traceData := <-bc.tm.T:
if exist, err := isTraceDataInDB(bc.db, traceData.hash); exist || err != nil { if exist, err := isTraceDataInDB(bc.db, traceData.hash); exist || err != nil {
break continue
} }
traceData.btc = bc.db.NewBatch() traceData.btc = bc.db.NewBatch()
_ = writeTraceData(traceData.btc, traceData.hash, traceData.data) _ = writeTraceData(traceData.btc, traceData.hash, traceData.data)

@ -186,7 +186,7 @@ func (c action) toJsonStr() (string, *string, *string) {
return "unkonw", nil, nil return "unkonw", nil, nil
} }
type ParityBlockTracer struct { type ParityTxTracer struct {
blockNumber uint64 blockNumber uint64
blockHash common.Hash blockHash common.Hash
transactionPosition uint64 transactionPosition uint64
@ -195,49 +195,54 @@ type ParityBlockTracer struct {
calls []*action calls []*action
action action
} }
type ParityBlockTracer struct {
cur *ParityTxTracer
tracers []*ParityTxTracer
}
func (jst *ParityBlockTracer) push(ac *action) { func (ptt *ParityTxTracer) push(ac *action) {
jst.calls = append(jst.calls, ac) ptt.calls = append(ptt.calls, ac)
} }
func (jst *ParityBlockTracer) pop() *action { func (ptt *ParityTxTracer) pop() *action {
popIndex := len(jst.calls) - 1 popIndex := len(ptt.calls) - 1
ac := jst.calls[popIndex] ac := ptt.calls[popIndex]
jst.calls = jst.calls[:popIndex] ptt.calls = ptt.calls[:popIndex]
return ac return ac
} }
func (jst *ParityBlockTracer) last() *action { func (ptt *ParityTxTracer) last() *action {
return jst.calls[len(jst.calls)-1] return ptt.calls[len(ptt.calls)-1]
} }
func (jst *ParityBlockTracer) len() int { func (ptt *ParityTxTracer) len() int {
return len(jst.calls) return len(ptt.calls)
} }
// CaptureStart implements the ParityBlockTracer interface to initialize the tracing operation. // CaptureStart implements the ParityBlockTracer interface to initialize the tracing operation.
func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { func (jst *ParityBlockTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error {
jst.op = vm.CALL // vritual call jst.cur = &ParityTxTracer{}
jst.cur.op = vm.CALL // vritual call
if create { if create {
jst.op = vm.CREATE // virtual create jst.cur.op = vm.CREATE // virtual create
} }
jst.from = from jst.cur.from = from
jst.to = to jst.cur.to = to
jst.input = input jst.cur.input = input
jst.gas = gas jst.cur.gas = gas
jst.value = (&big.Int{}).Set(value) jst.cur.value = (&big.Int{}).Set(value)
jst.blockHash = env.StateDB.BlockHash() jst.cur.blockHash = env.StateDB.BlockHash()
jst.transactionPosition = uint64(env.StateDB.TxIndex()) jst.cur.transactionPosition = uint64(env.StateDB.TxIndex())
jst.transactionHash = env.StateDB.TxHash() jst.cur.transactionHash = env.StateDB.TxHash()
jst.blockNumber = env.BlockNumber.Uint64() jst.cur.blockNumber = env.BlockNumber.Uint64()
jst.descended = false jst.cur.descended = false
jst.push(&jst.action) jst.cur.push(&jst.cur.action)
return nil return nil
} }
// CaptureState implements the ParityBlockTracer interface to trace a single step of VM execution. // CaptureState implements the ParityBlockTracer interface to trace a single step of VM execution.
func (jst *ParityBlockTracer) 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 *ParityBlockTracer) 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 {
//if op < vm.CREATE && !jst.descended { //if op < vm.CREATE && !jst.cur.descended {
// return nil // return nil
//} //}
var retErr error var retErr error
@ -259,7 +264,7 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
if op == vm.CREATE || op == vm.CREATE2 { if op == vm.CREATE || op == vm.CREATE2 {
inOff := stackPeek(1).Int64() inOff := stackPeek(1).Int64()
inSize := stackPeek(2).Int64() inSize := stackPeek(2).Int64()
jst.push(&action{ jst.cur.push(&action{
op: op, op: op,
from: contract.Address(), from: contract.Address(),
input: memoryCopy(inOff, inSize), input: memoryCopy(inOff, inSize),
@ -267,11 +272,11 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
gasCost: cost, gasCost: cost,
value: (&big.Int{}).Set(stackPeek(0)), value: (&big.Int{}).Set(stackPeek(0)),
}) })
jst.descended = true jst.cur.descended = true
return retErr return retErr
} }
if op == vm.SELFDESTRUCT { if op == vm.SELFDESTRUCT {
ac := jst.last() ac := jst.cur.last()
ac.push(&action{ ac.push(&action{
op: op, op: op,
from: contract.Address(), from: contract.Address(),
@ -307,26 +312,26 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
if op != vm.DELEGATECALL && op != vm.STATICCALL { if op != vm.DELEGATECALL && op != vm.STATICCALL {
callObj.value = (&big.Int{}).Set(stackPeek(2)) callObj.value = (&big.Int{}).Set(stackPeek(2))
} }
jst.push(callObj) jst.cur.push(callObj)
jst.descended = true jst.cur.descended = true
return retErr return retErr
} }
if jst.descended { if jst.cur.descended {
jst.descended = false jst.cur.descended = false
if depth >= jst.len() { // >= to > if depth >= jst.cur.len() { // >= to >
jst.last().gas = gas jst.cur.last().gas = gas
} }
} }
if op == vm.REVERT { if op == vm.REVERT {
last := jst.last() last := jst.cur.last()
last.err = errors.New("execution reverted") last.err = errors.New("execution reverted")
revertOff := stackPeek(0).Int64() revertOff := stackPeek(0).Int64()
revertLen := stackPeek(1).Int64() revertLen := stackPeek(1).Int64()
last.revert = memoryCopy(revertOff, revertLen) last.revert = memoryCopy(revertOff, revertLen)
return retErr return retErr
} }
if depth == jst.len()-1 { // depth == len - 1 if depth == jst.cur.len()-1 { // depth == len - 1
call := jst.pop() call := jst.cur.pop()
if call.op == vm.CREATE || call.op == vm.CREATE2 { if call.op == vm.CREATE || call.op == vm.CREATE2 {
call.gasUsed = call.gasIn - call.gasCost - gas call.gasUsed = call.gasIn - call.gasCost - gas
@ -348,7 +353,7 @@ func (jst *ParityBlockTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
call.err = errors.New("internal failure") call.err = errors.New("internal failure")
} }
} }
jst.last().push(call) jst.cur.last().push(call)
} }
return retErr return retErr
} }
@ -359,7 +364,7 @@ func (jst *ParityBlockTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode,
if op == vm.REVERT { if op == vm.REVERT {
return nil return nil
} }
call := jst.pop() call := jst.cur.pop()
if call.err == nil { if call.err == nil {
// Consume all available gas and clean any leftovers // Consume all available gas and clean any leftovers
if call.gas != 0 { if call.gas != 0 {
@ -367,35 +372,31 @@ func (jst *ParityBlockTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode,
} }
// Flatten the failed call into its parent // Flatten the failed call into its parent
if jst.len() > 0 { if jst.cur.len() > 0 {
jst.last().push(call) jst.cur.last().push(call)
return nil return nil
} }
} }
jst.push(call) jst.cur.push(call)
return nil return nil
} }
// CaptureEnd is called after the call finishes to finalize the tracing. // CaptureEnd is called after the call finishes to finalize the tracing.
func (jst *ParityBlockTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { func (jst *ParityBlockTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error {
jst.output = output jst.cur.output = output
jst.gasUsed = gasUsed jst.cur.gasUsed = gasUsed
if err != nil { if err != nil {
jst.err = err jst.cur.err = err
} }
jst.tracers = append(jst.tracers, jst.cur)
return nil return nil
} }
// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error // GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) { func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) {
root := &jst.action
headPiece := fmt.Sprintf(
`"blockNumber":%d,"blockHash":"%s","transactionHash":"%s","transactionPosition":%d`,
jst.blockNumber, jst.blockHash.Hex(), jst.transactionHash.Hex(), jst.transactionPosition,
)
var results []json.RawMessage var results []json.RawMessage
var err error var err error
var headPiece string
var finalize func(ac *action, traceAddress []int) var finalize func(ac *action, traceAddress []int)
finalize = func(ac *action, traceAddress []int) { finalize = func(ac *action, traceAddress []int) {
typStr, acStr, outStr := ac.toJsonStr() typStr, acStr, outStr := ac.toJsonStr()
@ -424,6 +425,13 @@ func (jst *ParityBlockTracer) GetResult() ([]json.RawMessage, error) {
finalize(subAc, append(traceAddress[:], i)) finalize(subAc, append(traceAddress[:], i))
} }
} }
for _, curTx := range jst.tracers {
root := &curTx.action
headPiece = fmt.Sprintf(
`"blockNumber":%d,"blockHash":"%s","transactionHash":"%s","transactionPosition":%d`,
curTx.blockNumber, curTx.blockHash.Hex(), curTx.transactionHash.Hex(), curTx.transactionPosition,
)
finalize(root, make([]int, 0)) finalize(root, make([]int, 0))
}
return results, err return results, err
} }

Loading…
Cancel
Save