mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
0a31f5ac2a
Works around a flaw in the upgrade logic of the system contracts. Since they are updated directly, without first being self-destructed and then re-created, the usual incarnation logic does not get activated, and all historical records of the code of these contracts are retrieved as the most recent version. This problem will not exist in erigon3, but until then, a workaround will be used to access code of such contracts through a special structure, `SystemContractCodeLookup` Fixes https://github.com/ledgerwatch/erigon/issues/5865 Co-authored-by: Alexey Sharp <alexeysharp@Alexeys-iMac.local>
105 lines
3.5 KiB
Go
105 lines
3.5 KiB
Go
package commands
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
|
"github.com/ledgerwatch/erigon/common"
|
|
"github.com/ledgerwatch/erigon/core"
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
"github.com/ledgerwatch/erigon/core/state"
|
|
"github.com/ledgerwatch/erigon/core/systemcontracts"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/core/vm"
|
|
"github.com/ledgerwatch/erigon/params"
|
|
"github.com/ledgerwatch/erigon/turbo/shards"
|
|
"github.com/ledgerwatch/log/v3"
|
|
)
|
|
|
|
func (api *OtterscanAPIImpl) searchTraceBlock(ctx context.Context, wg *sync.WaitGroup, addr common.Address, chainConfig *params.ChainConfig, idx int, bNum uint64, results []*TransactionsWithReceipts) {
|
|
defer wg.Done()
|
|
|
|
// Trace block for Txs
|
|
newdbtx, err := api.db.BeginRo(ctx)
|
|
if err != nil {
|
|
log.Error("Search trace error", "err", err)
|
|
results[idx] = nil
|
|
return
|
|
}
|
|
defer newdbtx.Rollback()
|
|
|
|
_, result, err := api.traceBlock(newdbtx, ctx, bNum, addr, chainConfig)
|
|
if err != nil {
|
|
log.Error("Search trace error", "err", err)
|
|
results[idx] = nil
|
|
return
|
|
}
|
|
results[idx] = result
|
|
}
|
|
|
|
func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNum uint64, searchAddr common.Address, chainConfig *params.ChainConfig) (bool, *TransactionsWithReceipts, error) {
|
|
rpcTxs := make([]*RPCTransaction, 0)
|
|
receipts := make([]map[string]interface{}, 0)
|
|
|
|
// Retrieve the transaction and assemble its EVM context
|
|
blockHash, err := rawdb.ReadCanonicalHash(dbtx, blockNum)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
|
|
block, senders, err := api._blockReader.BlockWithSenders(ctx, dbtx, blockHash, blockNum)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
|
|
reader := state.NewPlainState(dbtx, blockNum, systemcontracts.SystemContractCodeLookup[chainConfig.ChainName])
|
|
stateCache := shards.NewStateCache(32, 0 /* no limit */)
|
|
cachedReader := state.NewCachedReader(reader, stateCache)
|
|
noop := state.NewNoopWriter()
|
|
cachedWriter := state.NewCachedWriter(noop, stateCache)
|
|
|
|
ibs := state.New(cachedReader)
|
|
signer := types.MakeSigner(chainConfig, blockNum)
|
|
|
|
getHeader := func(hash common.Hash, number uint64) *types.Header {
|
|
h, e := api._blockReader.Header(ctx, dbtx, hash, number)
|
|
if e != nil {
|
|
log.Error("getHeader error", "number", number, "hash", hash, "err", e)
|
|
}
|
|
return h
|
|
}
|
|
engine := api.engine()
|
|
|
|
blockReceipts := rawdb.ReadReceipts(dbtx, block, senders)
|
|
header := block.Header()
|
|
rules := chainConfig.Rules(block.NumberU64(), header.Time)
|
|
found := false
|
|
for idx, tx := range block.Transactions() {
|
|
ibs.Prepare(tx.Hash(), block.Hash(), idx)
|
|
|
|
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)
|
|
|
|
tracer := NewTouchTracer(searchAddr)
|
|
BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil)
|
|
TxContext := core.NewEVMTxContext(msg)
|
|
|
|
vmenv := vm.NewEVM(BlockContext, TxContext, ibs, chainConfig, vm.Config{Debug: true, Tracer: tracer})
|
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.GetGas()), true /* refunds */, false /* gasBailout */); err != nil {
|
|
return false, nil, err
|
|
}
|
|
_ = ibs.FinalizeTx(rules, cachedWriter)
|
|
|
|
if tracer.Found {
|
|
rpcTx := newRPCTransaction(tx, block.Hash(), blockNum, uint64(idx), block.BaseFee())
|
|
mReceipt := marshalReceipt(blockReceipts[idx], tx, chainConfig, block, tx.Hash(), true)
|
|
mReceipt["timestamp"] = block.Time()
|
|
rpcTxs = append(rpcTxs, rpcTx)
|
|
receipts = append(receipts, mReceipt)
|
|
found = true
|
|
}
|
|
}
|
|
|
|
return found, &TransactionsWithReceipts{rpcTxs, receipts, false, false}, nil
|
|
}
|