mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
trace/live: filter with address
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
parent
186d6d8d69
commit
3cbadcdf3d
3 changed files with 76 additions and 8 deletions
|
|
@ -41,10 +41,10 @@ func (api *traceAPI) Block(ctx context.Context, blockNr rpc.BlockNumber, cfg *tr
|
|||
blknum = api.live.latest.Load()
|
||||
}
|
||||
|
||||
return api.readBlockTraces(ctx, tracer, blknum, tracer == "parityTracer")
|
||||
return api.readBlockTraces(ctx, tracer, blknum, tracer == "parityTracer", nil)
|
||||
}
|
||||
|
||||
func (api *traceAPI) readBlockTraces(ctx context.Context, tracer string, blknum uint64, isParity bool) ([]interface{}, error) {
|
||||
func (api *traceAPI) readBlockTraces(ctx context.Context, tracer string, blknum uint64, isParity bool, parityTraceMatcher func(interface{}) bool) ([]interface{}, error) {
|
||||
traces, err := api.live.readBlockTraces(ctx, tracer, blknum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -52,10 +52,17 @@ func (api *traceAPI) readBlockTraces(ctx context.Context, tracer string, blknum
|
|||
|
||||
results := make([]interface{}, 0, len(traces))
|
||||
if isParity {
|
||||
// Convert from []interface{} to []traceResult
|
||||
for i, trace := range traces {
|
||||
if parityTraces, ok := trace.Result.([]interface{}); ok {
|
||||
if parityTraceMatcher == nil {
|
||||
results = append(results, parityTraces...)
|
||||
continue
|
||||
}
|
||||
for _, parityTrace := range parityTraces {
|
||||
if parityTraceMatcher(parityTrace) {
|
||||
results = append(results, parityTrace)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid trace result type at index: %d", i)
|
||||
}
|
||||
|
|
@ -146,8 +153,8 @@ func (api *traceAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *tra
|
|||
toBlock = uint64(0)
|
||||
count = uint64(^uint(0))
|
||||
after = uint64(0)
|
||||
// fromAddrs = extractAddres(req.FromAddress)
|
||||
// toAddrs = extractAddres(req.ToAddress)
|
||||
fromAddrs = extractAddres(req.FromAddress)
|
||||
toAddrs = extractAddres(req.ToAddress)
|
||||
)
|
||||
|
||||
if req.FromBlock != nil {
|
||||
|
|
@ -170,7 +177,18 @@ func (api *traceAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *tra
|
|||
after = *req.After
|
||||
}
|
||||
|
||||
return exportLimitedTraces(func(blknum uint64) ([]interface{}, error) { return api.readBlockTraces(ctx, tracer, blknum, isParity) }, fromBlock, toBlock, count, after)
|
||||
var parityTraceMatcher func(interface{}) bool
|
||||
if isParity && (len(fromAddrs) > 0 || len(toAddrs) > 0) {
|
||||
parityTraceMatcher = func(trace interface{}) bool {
|
||||
return filterParityTrace(trace, fromAddrs, toAddrs, req.Mode)
|
||||
}
|
||||
}
|
||||
|
||||
traceGen := func(blknum uint64) ([]interface{}, error) {
|
||||
return api.readBlockTraces(ctx, tracer, blknum, isParity, parityTraceMatcher)
|
||||
}
|
||||
|
||||
return exportLimitedTraces(traceGen, fromBlock, toBlock, count, after)
|
||||
}
|
||||
|
||||
func (api *traceAPI) getTracerOrDefault(cfg *traceConfig) (string, error) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
package live
|
||||
|
||||
import "github.com/ethereum/go-ethereum/common"
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
||||
result := make(map[common.Address]struct{}, len(addrs))
|
||||
|
|
@ -12,6 +17,47 @@ func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
|||
return result
|
||||
}
|
||||
|
||||
func containsAddress(addrs map[common.Address]struct{}, addr *common.Address) bool {
|
||||
if addr == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := addrs[*addr]
|
||||
return ok
|
||||
}
|
||||
|
||||
func filterParityTrace(trace interface{}, fromAddrs, toAddrs map[common.Address]struct{}, mode TraceFilterMode) bool {
|
||||
var pt native.ParityTrace
|
||||
if err := mapstructure.Decode(trace, &pt); err != nil {
|
||||
log.Error("Failed to convert into ParityTrace", "err", err)
|
||||
return false
|
||||
}
|
||||
var fromAddr, toAddr *common.Address
|
||||
switch pt.Type {
|
||||
case "call":
|
||||
fromAddr = pt.Action.From
|
||||
toAddr = pt.Action.To
|
||||
case "create":
|
||||
fromAddr = pt.Action.From
|
||||
if pt.Result != nil {
|
||||
toAddr = pt.Result.Address
|
||||
}
|
||||
case "suicide":
|
||||
fromAddr = pt.Action.SelfDestructed
|
||||
toAddr = pt.Action.RefundAddress
|
||||
default:
|
||||
// No matching for other types
|
||||
return false
|
||||
}
|
||||
|
||||
fromMatch := len(fromAddrs) == 0 || containsAddress(fromAddrs, fromAddr)
|
||||
toMatch := len(toAddrs) == 0 || containsAddress(toAddrs, toAddr)
|
||||
|
||||
if mode == TraceFilterModeIntersection {
|
||||
return fromMatch && toMatch
|
||||
}
|
||||
return fromMatch || toMatch
|
||||
}
|
||||
|
||||
func exportLimitedTraces(gen func(blknum uint64) ([]interface{}, error), fromBlock, toBlock, count, after uint64) ([]interface{}, error) {
|
||||
var (
|
||||
nExported uint64 // Number of traces exported
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ var parityErrorMappingStartingWith = map[string]string{
|
|||
"stack underflow": "Stack underflow",
|
||||
}
|
||||
|
||||
// ParityTrace represents a single trace item in Parity format.
|
||||
// It is an alias for flatCallFrame, providing Parity-compatible naming.
|
||||
type ParityTrace flatCallFrame
|
||||
|
||||
// flatCallFrame is a standalone callframe.
|
||||
type flatCallFrame struct {
|
||||
Action flatCallAction `json:"action"`
|
||||
|
|
|
|||
Loading…
Reference in a new issue