mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
eth/tracers/live: rename filter to live
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
parent
5bb32c5a6f
commit
f4114d4047
7 changed files with 138 additions and 194 deletions
|
|
@ -26,7 +26,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
tracers.LiveDirectory.Register("filter", newFilter)
|
||||
tracers.LiveDirectory.Register("live", newLive)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -57,7 +57,7 @@ func (tr *traceResult) DecodeRLP(s *rlp.Stream) error {
|
|||
return json.Unmarshal(temp.Result, &tr.Result)
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
type live struct {
|
||||
backend tracing.Backend
|
||||
kvdb ethdb.Database
|
||||
frdb *rawdb.Freezer
|
||||
|
|
@ -74,7 +74,7 @@ type filter struct {
|
|||
offsetFile string
|
||||
}
|
||||
|
||||
type filterTracerConfig struct {
|
||||
type liveTracerConfig struct {
|
||||
Path string `json:"path"` // Path to the directory where the tracer logs will be stored
|
||||
Config json.RawMessage `json:"config"`
|
||||
}
|
||||
|
|
@ -111,15 +111,15 @@ func toKVKey(name string, number uint64, hash common.Hash) []byte {
|
|||
return key
|
||||
}
|
||||
|
||||
func newFilter(cfg json.RawMessage, stack tracers.LiveApiRegister, backend tracing.Backend) (*tracing.Hooks, error) {
|
||||
var config filterTracerConfig
|
||||
func newLive(cfg json.RawMessage, stack tracers.LiveApiRegister, backend tracing.Backend) (*tracing.Hooks, error) {
|
||||
var config liveTracerConfig
|
||||
if cfg != nil {
|
||||
if err := json.Unmarshal(cfg, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config: %v", err)
|
||||
}
|
||||
}
|
||||
if config.Path == "" {
|
||||
return nil, errors.New("filter tracer output path is required")
|
||||
return nil, errors.New("live tracer output path is required")
|
||||
}
|
||||
|
||||
t, err := native.NewMuxTracer(config.Config)
|
||||
|
|
@ -159,7 +159,7 @@ func newFilter(cfg json.RawMessage, stack tracers.LiveApiRegister, backend traci
|
|||
return nil, fmt.Errorf("failed to read the frozen block numbers from the freezer db: %v", err)
|
||||
}
|
||||
|
||||
f := &filter{
|
||||
l := &live{
|
||||
backend: backend,
|
||||
kvdb: kvdb,
|
||||
frdb: frdb,
|
||||
|
|
@ -171,8 +171,8 @@ func newFilter(cfg json.RawMessage, stack tracers.LiveApiRegister, backend traci
|
|||
offsetFile: path.Join(frpath, "OFFSET"),
|
||||
}
|
||||
offset := 0
|
||||
if _, err := os.Stat(f.offsetFile); err == nil || os.IsExist(err) {
|
||||
data, err := os.ReadFile(f.offsetFile)
|
||||
if _, err := os.Stat(l.offsetFile); err == nil || os.IsExist(err) {
|
||||
data, err := os.ReadFile(l.offsetFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read the offset from the freezer db: %v", err)
|
||||
}
|
||||
|
|
@ -181,15 +181,15 @@ func newFilter(cfg json.RawMessage, stack tracers.LiveApiRegister, backend traci
|
|||
return nil, fmt.Errorf("failed to convert offset: %v", err)
|
||||
}
|
||||
}
|
||||
log.Info("Open filter tracer", "path", config.Path, "offset", offset, "tables", tables)
|
||||
log.Info("Open live tracer", "path", config.Path, "offset", offset, "tables", tables)
|
||||
|
||||
f.latest.Store(tail + frozen + uint64(offset))
|
||||
f.offset.Store(uint64(offset))
|
||||
l.latest.Store(tail + frozen + uint64(offset))
|
||||
l.offset.Store(uint64(offset))
|
||||
hooks := &tracing.Hooks{
|
||||
OnBlockStart: f.OnBlockStart,
|
||||
OnBlockEnd: f.OnBlockEnd,
|
||||
OnTxStart: f.OnTxStart,
|
||||
OnTxEnd: f.OnTxEnd,
|
||||
OnBlockStart: l.OnBlockStart,
|
||||
OnBlockEnd: l.OnBlockEnd,
|
||||
OnTxStart: l.OnTxStart,
|
||||
OnTxEnd: l.OnTxEnd,
|
||||
|
||||
// reuse the mux's hooks
|
||||
OnEnter: t.OnEnter,
|
||||
|
|
@ -206,17 +206,21 @@ func newFilter(cfg json.RawMessage, stack tracers.LiveApiRegister, backend traci
|
|||
apis := []rpc.API{
|
||||
{
|
||||
Namespace: "trace",
|
||||
Service: &filterAPI{backend: backend, filter: f},
|
||||
Service: &traceAPI{backend: backend, live: l},
|
||||
},
|
||||
{
|
||||
Namespace: "eth",
|
||||
Service: ðAPI{backend: backend, live: l},
|
||||
},
|
||||
}
|
||||
stack.RegisterAPIs(apis)
|
||||
|
||||
go f.freeze()
|
||||
go l.freeze()
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func (f *filter) OnBlockStart(ev tracing.BlockEvent) {
|
||||
func (f *live) OnBlockStart(ev tracing.BlockEvent) {
|
||||
// track the latest block number
|
||||
blknum := ev.Block.NumberU64()
|
||||
f.latest.Store(blknum)
|
||||
|
|
@ -240,11 +244,16 @@ func (f *filter) OnBlockStart(ev tracing.BlockEvent) {
|
|||
})
|
||||
}
|
||||
|
||||
func (f *filter) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||
func (f *live) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||
key := append(from.Bytes(), encodeNumber(tx.Nonce())...)
|
||||
val := tx.Hash().Bytes()
|
||||
if err := f.kvdb.Put(key, val); err != nil {
|
||||
log.Warn("Failed to put nonce into kvdb", "err", err)
|
||||
}
|
||||
f.tracer.OnTxStart(env, tx, from)
|
||||
}
|
||||
|
||||
func (f *filter) OnTxEnd(receipt *types.Receipt, err error) {
|
||||
func (f *live) OnTxEnd(receipt *types.Receipt, err error) {
|
||||
f.tracer.OnTxEnd(receipt, err)
|
||||
|
||||
for name, tt := range f.tracer.Tracers() {
|
||||
|
|
@ -260,7 +269,7 @@ func (f *filter) OnTxEnd(receipt *types.Receipt, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *filter) OnBlockEnd(err error) {
|
||||
func (f *live) OnBlockEnd(err error) {
|
||||
if err != nil {
|
||||
log.Warn("OnBlockEnd", "latest", f.latest.Load(), "error", err)
|
||||
}
|
||||
|
|
@ -289,7 +298,7 @@ func (f *filter) OnBlockEnd(err error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *filter) readBlockTraces(ctx context.Context, name string, blknum uint64) ([]*traceResult, error) {
|
||||
func (f *live) readBlockTraces(ctx context.Context, name string, blknum uint64) ([]*traceResult, error) {
|
||||
if blknum > f.latest.Load() {
|
||||
return nil, errors.New("notfound")
|
||||
}
|
||||
|
|
@ -320,7 +329,7 @@ func (f *filter) readBlockTraces(ctx context.Context, name string, blknum uint64
|
|||
return traces, err
|
||||
}
|
||||
|
||||
func (f *filter) readFromKVDB(ctx context.Context, name string, blknum uint64) ([]byte, error) {
|
||||
func (f *live) readFromKVDB(ctx context.Context, name string, blknum uint64) ([]byte, error) {
|
||||
header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(blknum))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -334,7 +343,7 @@ func (f *filter) readFromKVDB(ctx context.Context, name string, blknum uint64) (
|
|||
return data, err
|
||||
}
|
||||
|
||||
func (f *filter) readFromFRDB(name string, blknum uint64) ([]byte, error) {
|
||||
func (f *live) readFromFRDB(name string, blknum uint64) ([]byte, error) {
|
||||
table := toTraceTable(name)
|
||||
var data []byte
|
||||
err := f.frdb.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
|
|
@ -348,7 +357,7 @@ func (f *filter) readFromFRDB(name string, blknum uint64) ([]byte, error) {
|
|||
return data, nil
|
||||
}
|
||||
|
||||
func (f *filter) Close() {
|
||||
func (f *live) Close() {
|
||||
close(f.stopCh)
|
||||
|
||||
if err := f.kvdb.Close(); err != nil {
|
||||
40
eth/tracers/live/live_api_eth.go
Normal file
40
eth/tracers/live/live_api_eth.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package live
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
)
|
||||
|
||||
type ethAPI struct {
|
||||
backend tracing.Backend
|
||||
live *live
|
||||
}
|
||||
|
||||
func (n *ethAPI) GetTransactionBySenderAndNonce(ctx context.Context, sender common.Address, nonce hexutil.Uint) (*ethapi.RPCTransaction, error) {
|
||||
// TODO:
|
||||
// 1. return nil if sender is a contract
|
||||
// 2. check with txpool first
|
||||
txHash, err := n.live.kvdb.Get(append(sender.Bytes(), encodeNumber(uint64(nonce))...))
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
found, tx, blockHash, blockNumber, index, err := n.backend.GetTransaction(ctx, common.BytesToHash(txHash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.New("transaction not found")
|
||||
}
|
||||
|
||||
header, err := n.backend.HeaderByHash(ctx, blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ethapi.NewRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, n.backend.ChainConfig()), nil
|
||||
}
|
||||
|
|
@ -14,9 +14,9 @@ import (
|
|||
|
||||
var errTxNotFound = errors.New("transaction not found")
|
||||
|
||||
type filterAPI struct {
|
||||
type traceAPI struct {
|
||||
backend tracing.Backend
|
||||
filter *filter
|
||||
live *live
|
||||
}
|
||||
|
||||
type traceConfig struct {
|
||||
|
|
@ -27,12 +27,12 @@ var defaultTraceConfig = &traceConfig{
|
|||
Tracer: "callTracer",
|
||||
}
|
||||
|
||||
func (api *filterAPI) isSupportedTracer(tracer string) bool {
|
||||
_, ok := api.filter.tracer.Tracers()[tracer]
|
||||
func (api *traceAPI) isSupportedTracer(tracer string) bool {
|
||||
_, ok := api.live.tracer.Tracers()[tracer]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (api *filterAPI) Block(ctx context.Context, blockNr rpc.BlockNumber, cfg *traceConfig) ([]interface{}, error) {
|
||||
func (api *traceAPI) Block(ctx context.Context, blockNr rpc.BlockNumber, cfg *traceConfig) ([]interface{}, error) {
|
||||
tracer, err := api.getTracerOrDefault(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -40,14 +40,14 @@ func (api *filterAPI) Block(ctx context.Context, blockNr rpc.BlockNumber, cfg *t
|
|||
|
||||
blknum := uint64(blockNr.Int64())
|
||||
if blockNr == rpc.LatestBlockNumber {
|
||||
blknum = api.filter.latest.Load()
|
||||
blknum = api.live.latest.Load()
|
||||
}
|
||||
|
||||
return api.readBlockTraces(ctx, tracer, blknum, tracer == "parityTracer")
|
||||
}
|
||||
|
||||
func (api *filterAPI) readBlockTraces(ctx context.Context, tracer string, blknum uint64, isParity bool) ([]interface{}, error) {
|
||||
traces, err := api.filter.readBlockTraces(ctx, tracer, blknum)
|
||||
func (api *traceAPI) readBlockTraces(ctx context.Context, tracer string, blknum uint64, isParity bool) ([]interface{}, error) {
|
||||
traces, err := api.live.readBlockTraces(ctx, tracer, blknum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ func (api *filterAPI) readBlockTraces(ctx context.Context, tracer string, blknum
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func (api *filterAPI) Transaction(ctx context.Context, hash common.Hash, cfg *traceConfig) (interface{}, error) {
|
||||
func (api *traceAPI) Transaction(ctx context.Context, hash common.Hash, cfg *traceConfig) (interface{}, error) {
|
||||
tracer, err := api.getTracerOrDefault(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -98,7 +98,7 @@ func (api *filterAPI) Transaction(ctx context.Context, hash common.Hash, cfg *tr
|
|||
if !found {
|
||||
return nil, errTxNotFound
|
||||
}
|
||||
traces, err := api.filter.readBlockTraces(ctx, tracer, blknum)
|
||||
traces, err := api.live.readBlockTraces(ctx, tracer, blknum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ const (
|
|||
)
|
||||
|
||||
// Filter returns traces for the given filter configuration.
|
||||
func (api *filterAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *traceConfig) (interface{}, error) {
|
||||
func (api *traceAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *traceConfig) (interface{}, error) {
|
||||
tracer, err := api.getTracerOrDefault(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -158,7 +158,7 @@ func (api *filterAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *tr
|
|||
if req.ToBlock != nil {
|
||||
toBlock = uint64(*req.ToBlock)
|
||||
} else {
|
||||
toBlock = api.filter.latest.Load()
|
||||
toBlock = api.live.latest.Load()
|
||||
}
|
||||
|
||||
if fromBlock > toBlock {
|
||||
|
|
@ -175,7 +175,7 @@ func (api *filterAPI) Filter(ctx context.Context, req traceFilterConfig, cfg *tr
|
|||
return exportLimitedTraces(func(blknum uint64) ([]interface{}, error) { return api.readBlockTraces(ctx, tracer, blknum, isParity) }, fromBlock, toBlock, count, after)
|
||||
}
|
||||
|
||||
func (api *filterAPI) getTracerOrDefault(cfg *traceConfig) (string, error) {
|
||||
func (api *traceAPI) getTracerOrDefault(cfg *traceConfig) (string, error) {
|
||||
if cfg == nil {
|
||||
return defaultTraceConfig.Tracer, nil
|
||||
}
|
||||
|
|
@ -186,45 +186,3 @@ func (api *filterAPI) getTracerOrDefault(cfg *traceConfig) (string, error) {
|
|||
}
|
||||
return tracer, nil
|
||||
}
|
||||
|
||||
func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
||||
result := make(map[common.Address]struct{}, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
if addr != nil {
|
||||
result[*addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func exportLimitedTraces(gen func(blknum uint64) ([]interface{}, error), fromBlock, toBlock, count, after uint64) ([]interface{}, error) {
|
||||
var (
|
||||
nExported uint64 // Number of traces exported
|
||||
nSkipped uint64 // Number of traces skipped
|
||||
results = make([]interface{}, 0, 1024) // 1024 is the initial capacity
|
||||
)
|
||||
|
||||
for blknum := fromBlock; blknum <= toBlock && nExported < count; blknum++ {
|
||||
traces, err := gen(uint64(blknum))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nTraces := uint64(len(traces))
|
||||
if after > nSkipped {
|
||||
skip := min(after-nSkipped, nTraces)
|
||||
nSkipped += skip
|
||||
if skip == nTraces {
|
||||
// Skip if the whole block is skipped
|
||||
continue
|
||||
}
|
||||
traces = traces[skip:]
|
||||
}
|
||||
|
||||
// Export at most the remaining traces
|
||||
maxExport := min(count-nExported, uint64(len(traces)))
|
||||
results = append(results, traces[:maxExport]...)
|
||||
nExported += maxExport
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ const (
|
|||
kvdbTailKey = "FilterFreezerTail"
|
||||
)
|
||||
|
||||
func (f *filter) freeze() {
|
||||
func (f *live) freeze() {
|
||||
var lastFinalized uint64
|
||||
for {
|
||||
select {
|
||||
|
|
@ -52,7 +52,7 @@ func (f *filter) freeze() {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *filter) getFreezerTail() (tail uint64) {
|
||||
func (f *live) getFreezerTail() (tail uint64) {
|
||||
tailBytes, _ := f.kvdb.Get([]byte(kvdbTailKey))
|
||||
|
||||
if len(tailBytes) > 0 {
|
||||
|
|
@ -64,13 +64,13 @@ func (f *filter) getFreezerTail() (tail uint64) {
|
|||
return
|
||||
}
|
||||
|
||||
func (f *filter) updateFreezerTail(tail uint64) error {
|
||||
func (f *live) updateFreezerTail(tail uint64) error {
|
||||
tailBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(tailBytes, tail)
|
||||
return f.kvdb.Put([]byte(kvdbTailKey), tailBytes)
|
||||
}
|
||||
|
||||
func (f *filter) moveBlockToFreezer(blknum uint64) error {
|
||||
func (f *live) moveBlockToFreezer(blknum uint64) error {
|
||||
header, err := f.backend.HeaderByNumber(context.Background(), rpc.BlockNumber(blknum))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -107,7 +107,7 @@ func (f *filter) moveBlockToFreezer(blknum uint64) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *filter) deleteKVDBEntriesWithPrefix(blknum uint64) error {
|
||||
func (f *live) deleteKVDBEntriesWithPrefix(blknum uint64) error {
|
||||
prefix := encodeNumber(blknum)
|
||||
batch := f.kvdb.NewBatch()
|
||||
it := f.kvdb.NewIterator(prefix, nil)
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
package live
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
tracers.LiveDirectory.Register("nonce", newNonce)
|
||||
}
|
||||
|
||||
type nonce struct {
|
||||
backend tracing.Backend
|
||||
kvdb ethdb.Database
|
||||
latest atomic.Uint64
|
||||
}
|
||||
|
||||
type nonceTracerConfig struct {
|
||||
Path string `json:"path"` // Path to the directory where the tracer logs will be stored
|
||||
}
|
||||
|
||||
func newNonce(cfg json.RawMessage, stack tracers.LiveApiRegister, backend tracing.Backend) (*tracing.Hooks, error) {
|
||||
var config nonceTracerConfig
|
||||
if cfg != nil {
|
||||
if err := json.Unmarshal(cfg, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config: %v", err)
|
||||
}
|
||||
}
|
||||
if config.Path == "" {
|
||||
return nil, errors.New("nonce tracer output path is required")
|
||||
}
|
||||
|
||||
kvdb, err := rawdb.NewPebbleDBDatabase(config.Path, 128, 1024, "nonce", false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := &nonce{
|
||||
backend: backend,
|
||||
kvdb: kvdb,
|
||||
}
|
||||
log.Info("Open nonce tracer", "path", config.Path)
|
||||
|
||||
apis := []rpc.API{{Namespace: "eth", Service: n}}
|
||||
stack.RegisterAPIs(apis)
|
||||
|
||||
return &tracing.Hooks{
|
||||
OnBlockStart: n.onBlockStart,
|
||||
OnTxStart: n.onTxStart,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *nonce) onBlockStart(ev tracing.BlockEvent) {
|
||||
blknum := ev.Block.NumberU64()
|
||||
n.latest.Store(blknum)
|
||||
}
|
||||
|
||||
func (n *nonce) onTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||
key := append(from.Bytes(), encodeNumber(tx.Nonce())...)
|
||||
val := tx.Hash().Bytes()
|
||||
if err := n.kvdb.Put(key, val); err != nil {
|
||||
log.Warn("Failed to put nonce kvdb", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *nonce) GetTransactionBySenderAndNonce(ctx context.Context, sender common.Address, nonce hexutil.Uint) (*ethapi.RPCTransaction, error) {
|
||||
// TODO:
|
||||
// 1. return nil if sender is a contract
|
||||
// 2. check with txpool first
|
||||
txHash, err := n.kvdb.Get(append(sender.Bytes(), encodeNumber(uint64(nonce))...))
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
found, tx, blockHash, blockNumber, index, err := n.backend.GetTransaction(ctx, common.BytesToHash(txHash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.New("transaction not found")
|
||||
}
|
||||
|
||||
header, err := n.backend.HeaderByHash(ctx, blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ethapi.NewRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, n.backend.ChainConfig()), nil
|
||||
}
|
||||
|
||||
func (n *nonce) Close() {
|
||||
if err := n.kvdb.Close(); err != nil {
|
||||
log.Error("Close kvdb failed", "err", err)
|
||||
}
|
||||
}
|
||||
45
eth/tracers/live/utils.go
Normal file
45
eth/tracers/live/utils.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package live
|
||||
|
||||
import "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
func extractAddres(addrs []*common.Address) map[common.Address]struct{} {
|
||||
result := make(map[common.Address]struct{}, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
if addr != nil {
|
||||
result[*addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func exportLimitedTraces(gen func(blknum uint64) ([]interface{}, error), fromBlock, toBlock, count, after uint64) ([]interface{}, error) {
|
||||
var (
|
||||
nExported uint64 // Number of traces exported
|
||||
nSkipped uint64 // Number of traces skipped
|
||||
results = make([]interface{}, 0, 1024) // 1024 is the initial capacity
|
||||
)
|
||||
|
||||
for blknum := fromBlock; blknum <= toBlock && nExported < count; blknum++ {
|
||||
traces, err := gen(uint64(blknum))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nTraces := uint64(len(traces))
|
||||
if after > nSkipped {
|
||||
skip := min(after-nSkipped, nTraces)
|
||||
nSkipped += skip
|
||||
if skip == nTraces {
|
||||
// Skip if the whole block is skipped
|
||||
continue
|
||||
}
|
||||
traces = traces[skip:]
|
||||
}
|
||||
|
||||
// Export at most the remaining traces
|
||||
maxExport := min(count-nExported, uint64(len(traces)))
|
||||
results = append(results, traces[:maxExport]...)
|
||||
nExported += maxExport
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
Loading…
Reference in a new issue