api feat: adds method to get accessList of txs in a block

This commit is contained in:
R-Niagra 2025-01-05 15:04:40 -05:00
parent 2ae2e331c9
commit 1bbd9879a4
3 changed files with 102 additions and 0 deletions

View file

@ -704,6 +704,81 @@ func (api *API) executeTx(ctx context.Context, index int, block *types.Block, tx
return nil
}
type txAccessList struct {
Accesslist *types.AccessList `json:"accessList"`
Error string `json:"error,omitempty"`
Hash common.Hash `json:"hash"`
}
func (api *API) GetBlockAccessLists(ctx context.Context, blockNum uint64) ([]txAccessList, error) {
if blockNum == 0 {
return []txAccessList{}, errors.New("genesis block is not applicable")
}
block, err := api.blockByNumber(ctx, rpc.BlockNumber(blockNum))
if err != nil {
return []txAccessList{}, err
}
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNum-1), block.ParentHash())
if err != nil {
return []txAccessList{}, fmt.Errorf("failed to get parent block: parent: %s, err %v", block.ParentHash().Hex(), err)
}
//generate the state at the parent block
statedb, release, err := api.backend.StateAtBlock(ctx, parent, defaultTraceReexec, nil, true, false)
if err != nil {
return []txAccessList{}, fmt.Errorf("failed to generate state at the parent block: err %v", err)
}
defer release()
return api.blockAccessLists(ctx, block, statedb)
}
func (api *API) blockAccessLists(ctx context.Context, block *types.Block, statedb *state.StateDB) ([]txAccessList, error) {
var (
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
postMerge = block.Difficulty().Sign() == 0
chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
precompiles = vm.ActivePrecompiles(api.backend.ChainConfig().Rules(block.Number(), postMerge, block.Time()))
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
acls []txAccessList
)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if chainConfig.IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
}
var to common.Address
for ind, tx := range block.Transactions() {
from, _ := types.Sender(signer, tx)
// create an access list tracer
if tx.To() != nil {
to = *tx.To()
}
tracer := logger.NewAccessListTracer(nil, from, to, precompiles)
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true})
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
statedb.SetTxContext(tx.Hash(), ind)
res, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
if err != nil {
return acls, fmt.Errorf("failed to apply tx: err %v", err)
}
acl := tracer.AccessList()
// tracer.PrintAccessList()
txAcl := txAccessList{Accesslist: &acl, Hash: tx.Hash()}
if res.Err != nil {
txAcl.Error = res.Err.Error()
}
acls = append(acls, txAcl)
}
return acls, nil
}
// StandardTraceBadBlockToFile dumps the structured logs created during the
// execution of EVM against a block pulled from the pool of bad ones to the
// local file system and returns a list of files to the caller.

View file

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/log"
)
// accessList is an accumulator for the set of accounts and storage slots an EVM
@ -93,6 +94,17 @@ func (al accessList) accessList() types.AccessList {
return acl
}
func (al accessList) Print() {
log.Info("printing access list")
for k, v := range al {
log.Info("entry", "address", k)
for s := range v {
log.Info("slot", "hash", s.Hex())
}
}
}
// AccessListTracer is a tracer that accumulates touched accounts and storage
// slots into an internal set.
type AccessListTracer struct {
@ -159,6 +171,15 @@ func (a *AccessListTracer) AccessList() types.AccessList {
return a.list.accessList()
}
func (a *AccessListTracer) PrintAccessList() {
log.Info("excluded access entries, this may contain precompiled contracts")
for k, _ := range a.excl {
log.Info("entry", "address", k.Hex())
}
log.Info("Printing other accesses")
a.list.Print()
}
// Equal returns if the content of two access list traces are equal.
func (a *AccessListTracer) Equal(other *AccessListTracer) bool {
return a.list.equal(other.list)

View file

@ -392,6 +392,12 @@ web3._extend({
params: 2,
inputFormatter: [null, null],
}),
new web3._extend.Method({
name: 'getBlockAccessLists',
call: 'debug_getBlockAccessLists',
params: 1,
inputFormatter: [null],
}),
new web3._extend.Method({
name: 'traceBlockByHash',
call: 'debug_traceBlockByHash',