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()
|
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)
|
traces, err := api.live.readBlockTraces(ctx, tracer, blknum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -52,10 +52,17 @@ func (api *traceAPI) readBlockTraces(ctx context.Context, tracer string, blknum
|
||||||
|
|
||||||
results := make([]interface{}, 0, len(traces))
|
results := make([]interface{}, 0, len(traces))
|
||||||
if isParity {
|
if isParity {
|
||||||
// Convert from []interface{} to []traceResult
|
|
||||||
for i, trace := range traces {
|
for i, trace := range traces {
|
||||||
if parityTraces, ok := trace.Result.([]interface{}); ok {
|
if parityTraces, ok := trace.Result.([]interface{}); ok {
|
||||||
results = append(results, parityTraces...)
|
if parityTraceMatcher == nil {
|
||||||
|
results = append(results, parityTraces...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, parityTrace := range parityTraces {
|
||||||
|
if parityTraceMatcher(parityTrace) {
|
||||||
|
results = append(results, parityTrace)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("invalid trace result type at index: %d", i)
|
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)
|
toBlock = uint64(0)
|
||||||
count = uint64(^uint(0))
|
count = uint64(^uint(0))
|
||||||
after = uint64(0)
|
after = uint64(0)
|
||||||
// fromAddrs = extractAddres(req.FromAddress)
|
fromAddrs = extractAddres(req.FromAddress)
|
||||||
// toAddrs = extractAddres(req.ToAddress)
|
toAddrs = extractAddres(req.ToAddress)
|
||||||
)
|
)
|
||||||
|
|
||||||
if req.FromBlock != nil {
|
if req.FromBlock != nil {
|
||||||
|
|
@ -170,7 +177,18 @@ func (api *traceAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *tra
|
||||||
after = *req.After
|
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) {
|
func (api *traceAPI) getTracerOrDefault(cfg *traceConfig) (string, error) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
package live
|
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{} {
|
func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
||||||
result := make(map[common.Address]struct{}, len(addrs))
|
result := make(map[common.Address]struct{}, len(addrs))
|
||||||
|
|
@ -12,6 +17,47 @@ func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
||||||
return result
|
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) {
|
func exportLimitedTraces(gen func(blknum uint64) ([]interface{}, error), fromBlock, toBlock, count, after uint64) ([]interface{}, error) {
|
||||||
var (
|
var (
|
||||||
nExported uint64 // Number of traces exported
|
nExported uint64 // Number of traces exported
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ var parityErrorMappingStartingWith = map[string]string{
|
||||||
"stack underflow": "Stack underflow",
|
"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.
|
// flatCallFrame is a standalone callframe.
|
||||||
type flatCallFrame struct {
|
type flatCallFrame struct {
|
||||||
Action flatCallAction `json:"action"`
|
Action flatCallAction `json:"action"`
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue