forked from cerc-io/plugeth
158 lines
4.0 KiB
Go
158 lines
4.0 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"math/big"
|
||
|
"time"
|
||
|
|
||
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||
|
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
||
|
)
|
||
|
|
||
|
type LiveTracerResult struct {
|
||
|
CallStack []CallStack
|
||
|
Results []CallStack
|
||
|
}
|
||
|
|
||
|
type CallStack struct {
|
||
|
Type string `json:"type"`
|
||
|
From core.Address `json:"from"`
|
||
|
To core.Address `json:"to"`
|
||
|
Value *big.Int `json:"value,omitempty"`
|
||
|
Gas hexutil.Uint64 `json:"gas"`
|
||
|
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
||
|
Input hexutil.Bytes `json:"input"`
|
||
|
Output hexutil.Bytes `json:"output"`
|
||
|
Time string `json:"time,omitempty"`
|
||
|
Calls []CallStack `json:"calls,omitempty"`
|
||
|
Results []CallStack `json:"results,omitempty"`
|
||
|
Error string `json:"error,omitempty"`
|
||
|
}
|
||
|
|
||
|
func (t *LiveTracerResult) TraceBlock(ctx context.Context) (<-chan []CallStack, error) {
|
||
|
subch := make(chan []CallStack, 1000)
|
||
|
rtrnch := make(chan []CallStack, 1000)
|
||
|
go func() {
|
||
|
log.Info("Subscription Block Tracer setup")
|
||
|
sub := events.Subscribe(subch)
|
||
|
for {
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
sub.Unsubscribe()
|
||
|
close(subch)
|
||
|
close(rtrnch)
|
||
|
return
|
||
|
case t := <-subch:
|
||
|
rtrnch <- t
|
||
|
case <-sub.Err():
|
||
|
sub.Unsubscribe()
|
||
|
close(subch)
|
||
|
close(rtrnch)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
return rtrnch, nil
|
||
|
}
|
||
|
|
||
|
func GetLiveTracer(core.Hash, core.StateDB) core.BlockTracer {
|
||
|
return &LiveTracerResult{}
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) PreProcessBlock(hash core.Hash, number uint64, encoded []byte) {
|
||
|
m := map[string]struct{}{
|
||
|
"LivePreProcessBlock":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
r.Results = []CallStack{}
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) PreProcessTransaction(tx core.Hash, block core.Hash, i int) {
|
||
|
m := map[string]struct{}{
|
||
|
"LivePreProcessTransaction":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) BlockProcessingError(tx core.Hash, block core.Hash, err error) {
|
||
|
m := map[string]struct{}{
|
||
|
"LiveBlockProcessingError":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) PostProcessTransaction(tx core.Hash, block core.Hash, i int, receipt []byte) {
|
||
|
m := map[string]struct{}{
|
||
|
"LivePostProcessTransaction":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) PostProcessBlock(block core.Hash) {
|
||
|
m := map[string]struct{}{
|
||
|
"LivePostProcessBlock":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
if len(r.Results) > 0 {
|
||
|
events.Send(r.Results)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) CaptureStart(from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||
|
r.CallStack = []CallStack{}
|
||
|
m := map[string]struct{}{
|
||
|
"LiveCaptureStart":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
}
|
||
|
func (r *LiveTracerResult) CaptureState(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, rData []byte, depth int, err error) {
|
||
|
m := map[string]struct{}{
|
||
|
"LiveCaptureState":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) CaptureFault(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, depth int, err error) {
|
||
|
// this method is not covered by tests at this time
|
||
|
// m := map[string]struct{}{
|
||
|
// "LiveCaptureFault":struct{}{},
|
||
|
// }
|
||
|
// hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
||
|
m := map[string]struct{}{
|
||
|
"LiveCaptureEnd":struct{}{},
|
||
|
}
|
||
|
hookChan <- m
|
||
|
if len(r.CallStack) > 0 {
|
||
|
r.Results = append(r.CallStack)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) CaptureEnter(typ core.OpCode, from core.Address, to core.Address, input []byte, gas uint64, value *big.Int) {
|
||
|
// this method is not covered by tests at this time
|
||
|
// m := map[string]struct{}{
|
||
|
// "LiveCaptureEnter":struct{}{},
|
||
|
// }
|
||
|
// hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||
|
// this method is not covered by tests at this time
|
||
|
// m := map[string]struct{}{
|
||
|
// "LiveCaptureExit":struct{}{},
|
||
|
// }
|
||
|
// hookChan <- m
|
||
|
}
|
||
|
|
||
|
func (r *LiveTracerResult) Result() (interface{}, error) {
|
||
|
// this method is not covered by tests at this time
|
||
|
// m := map[string]struct{}{
|
||
|
// "LiveTracerResult":struct{}{},
|
||
|
// }
|
||
|
// hookChan <- m
|
||
|
return "", nil
|
||
|
}
|
||
|
|