代码拉取完成,页面将自动刷新
Based on erigon and erigon-lib, parsing the full-node data from erigon clients.
Replace the accessors_chain.go ReadBody function
//github.com/erigon/core/rawdb/accessors_chain.go
func ReadBody(db kv.Getter, hash common.Hash, number uint64) (*types.Body, uint64, uint32) {
data := ReadStorageBodyRLP(db, hash, number)
if len(data) == 0 {
return nil, 0, 0
}
bodyForStorage := new(types.BodyForStorage)
err := rlp.DecodeBytes(data, bodyForStorage)
if err != nil {
log.Error("Invalid block body RLP", "hash", hash, "err", err)
return nil, 0, 0
}
body := new(types.Body)
body.Uncles = bodyForStorage.Uncles
return body, bodyForStorage.BaseTxId + 1, bodyForStorage.TxAmount
}
Add the trace-filtering.go FilterWithoutStream function
// github.com/erigon/cmd/rpcdaemon/commands/trace_filtering.go
func (api *TraceAPIImpl) FilterWithoutStream(ctx context.Context, req TraceFilterRequest) ([][]byte, error) {
dbtx, err1 := api.kv.BeginRo(ctx)
if err1 != nil {
return nil, fmt.Errorf("traceFilter cannot open tx: %w", err1)
}
defer dbtx.Rollback()
var fromBlock uint64
var toBlock uint64
if req.FromBlock == nil {
fromBlock = 0
} else {
fromBlock = uint64(*req.FromBlock)
}
if req.ToBlock == nil {
headNumber := rawdb.ReadHeaderNumber(dbtx, rawdb.ReadHeadHeaderHash(dbtx))
toBlock = *headNumber
} else {
toBlock = uint64(*req.ToBlock)
}
if fromBlock > toBlock {
return nil, fmt.Errorf("invalid parameters: fromBlock cannot be greater than toBlock")
}
fromAddresses := make(map[common.Address]struct{}, len(req.FromAddress))
toAddresses := make(map[common.Address]struct{}, len(req.ToAddress))
var (
allBlocks roaring64.Bitmap
blocksTo roaring64.Bitmap
)
for _, addr := range req.FromAddress {
if addr != nil {
b, err := bitmapdb.Get64(dbtx, kv.CallFromIndex, addr.Bytes(), fromBlock, toBlock)
if err != nil {
if errors.Is(err, ethdb.ErrKeyNotFound) {
continue
}
return nil, err
}
allBlocks.Or(b)
fromAddresses[*addr] = struct{}{}
}
}
for _, addr := range req.ToAddress {
if addr != nil {
b, err := bitmapdb.Get64(dbtx, kv.CallToIndex, addr.Bytes(), fromBlock, toBlock)
if err != nil {
if errors.Is(err, ethdb.ErrKeyNotFound) {
continue
}
return nil, err
}
blocksTo.Or(b)
toAddresses[*addr] = struct{}{}
}
}
switch req.Mode {
case TraceFilterModeIntersection:
allBlocks.And(&blocksTo)
case TraceFilterModeUnion:
fallthrough
default:
allBlocks.Or(&blocksTo)
}
// Special case - if no addresses specified, take all traces
if len(req.FromAddress) == 0 && len(req.ToAddress) == 0 {
allBlocks.AddRange(fromBlock, toBlock+1)
} else {
allBlocks.RemoveRange(0, fromBlock)
allBlocks.RemoveRange(toBlock+1, uint64(0x100000000))
}
chainConfig, err := api.chainConfig(dbtx)
if err != nil {
return nil, err
}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
first := true
// Execute all transactions in picked blocks
count := uint64(^uint(0)) // this just makes it easier to use below
if req.Count != nil {
count = *req.Count
}
after := uint64(0) // this just makes it easier to use below
if req.After != nil {
after = *req.After
}
nSeen := uint64(0)
nExported := uint64(0)
it := allBlocks.Iterator()
for it.HasNext() {
b := uint64(it.Next())
// Extract transactions from block
hash, hashErr := rawdb.ReadCanonicalHash(dbtx, b)
if hashErr != nil {
return nil, hashErr
}
block, bErr := api.blockWithSenders(dbtx, hash, b)
if bErr != nil {
return nil, bErr
}
if block == nil {
return nil, fmt.Errorf("could not find block %x %d", hash, b)
}
blockHash := block.Hash()
blockNumber := block.NumberU64()
txs := block.Transactions()
t, tErr := api.callManyTransactions(ctx, dbtx, txs, []string{TraceTypeTrace}, block.ParentHash(), rpc.BlockNumber(block.NumberU64()-1), block.Header(), -1 /* all tx indices */, types.MakeSigner(chainConfig, b))
if tErr != nil {
return nil, tErr
}
includeAll := len(fromAddresses) == 0 && len(toAddresses) == 0
tracesResultBytes := make([][]byte, 0)
for i, trace := range t {
txPosition := uint64(i)
txHash := txs[i].Hash()
// Check if transaction concerns any of the addresses we wanted
for _, pt := range trace.Trace {
if includeAll || filter_trace(pt, fromAddresses, toAddresses) {
nSeen++
pt.BlockHash = &blockHash
pt.BlockNumber = &blockNumber
pt.TransactionHash = &txHash
pt.TransactionPosition = &txPosition
b, err := json.Marshal(pt)
if err != nil {
return nil, err
}
if nSeen > after && nExported < count {
if first {
first = false
}
tracesResultBytes = append(tracesResultBytes, b)
nExported++
}
}
}
}
minerReward, uncleRewards := ethash.AccumulateRewards(chainConfig, block.Header(), block.Uncles())
if _, ok := toAddresses[block.Coinbase()]; ok || includeAll {
nSeen++
var tr ParityTrace
var rewardAction = &RewardTraceAction{}
rewardAction.Author = block.Coinbase()
rewardAction.RewardType = "block" // nolint: goconst
rewardAction.Value.ToInt().Set(minerReward.ToBig())
tr.Action = rewardAction
tr.BlockHash = &common.Hash{}
copy(tr.BlockHash[:], block.Hash().Bytes())
tr.BlockNumber = new(uint64)
*tr.BlockNumber = block.NumberU64()
tr.Type = "reward" // nolint: goconst
tr.TraceAddress = []int{}
b, err := json.Marshal(tr)
if err != nil {
return nil, err
}
if nSeen > after && nExported < count {
if first {
first = false
}
tracesResultBytes = append(tracesResultBytes, b)
nExported++
}
}
for i, uncle := range block.Uncles() {
if _, ok := toAddresses[uncle.Coinbase]; ok || includeAll {
if i < len(uncleRewards) {
nSeen++
var tr ParityTrace
rewardAction := &RewardTraceAction{}
rewardAction.Author = uncle.Coinbase
rewardAction.RewardType = "uncle" // nolint: goconst
rewardAction.Value.ToInt().Set(uncleRewards[i].ToBig())
tr.Action = rewardAction
tr.BlockHash = &common.Hash{}
copy(tr.BlockHash[:], block.Hash().Bytes())
tr.BlockNumber = new(uint64)
*tr.BlockNumber = block.NumberU64()
tr.Type = "reward" // nolint: goconst
tr.TraceAddress = []int{}
b, err := json.Marshal(tr)
if err != nil {
return nil, err
}
if nSeen > after && nExported < count {
if first {
first = false
}
tracesResultBytes = append(tracesResultBytes, b)
nExported++
}
}
}
}
}
return tracesResultBytes, nil
}
require:
go 1.18+
Linux platform
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./dist/bin/erigon-etl
Windows platform
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o .\dist\bin\erigon-etl
Export blocks and transactions
erigon-etl export_blocks_and_transactions --start-block 0 --end-block 1000 \
--blocks-output blocks.csv --transactions-output transactions.csv \
--provider-file ./mdbx.dat
Export token transfers
erigon-etl export_token_transfers --start-block 0 --end-block 1000 \
--output transfers.csv --provider-file ./mdbx.dat
Export traces
erigon-etl export_traces --start-block 0 --end-block 1000 \
--output transfers.csv --provider-file ./mdbx.dat
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。