cmd/geth: implement debug_batchGetStorageAt RPC (Closes #32591)

This commit is contained in:
Tinu280 2025-11-21 15:09:26 +07:00
parent a541f84fa3
commit 95a0ff03f4
2 changed files with 99 additions and 0 deletions

View file

@ -0,0 +1,63 @@
package ethapi
import (
"context"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
)
type StorageBatchRequest struct {
Address common.Address `json:"address"`
Slots []common.Hash `json:"slots"`
}
type StorageBatchResponse map[string]string
type DebugAPI struct {
b Backend
}
type Backend interface {
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (Block, error)
StateAt(root common.Hash) (StateDB, error)
}
type Block interface {
Root() common.Hash
}
type StateDB interface {
GetState(addr common.Address, slot common.Hash) common.Hash
}
func (api *DebugAPI) BatchGetStorageAt(ctx context.Context, reqs []StorageBatchRequest, blockNr rpc.BlockNumber) (map[string]StorageBatchResponse, error) {
res := make(map[string]StorageBatchResponse)
block, err := api.b.BlockByNumber(ctx, blockNr)
if err != nil { return nil, err }
statedb, err := api.b.StateAt(block.Root())
if err != nil { return nil, err }
var wg sync.WaitGroup
var mu sync.Mutex
for _, req := range reqs {
wg.Add(1)
go func(req StorageBatchRequest) {
defer wg.Done()
batchRes := make(StorageBatchResponse)
for _, slot := range req.Slots {
value := statedb.GetState(req.Address, slot)
batchRes[slot.Hex()] = value.Hex()
}
mu.Lock()
res[req.Address.Hex()] = batchRes
mu.Unlock()
}(req)
}
wg.Wait()
return res, nil
}

View file

@ -0,0 +1,36 @@
package ethapi
import (
"context"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
)
type dummyBackend struct{}
func (b *dummyBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (Block, error) { return &dummyBlock{}, nil }
func (b *dummyBackend) StateAt(root common.Hash) (StateDB, error) { return &dummyState{}, nil }
type dummyBlock struct{}
func (b *dummyBlock) Root() common.Hash { return common.Hash{} }
type dummyState struct{}
func (s *dummyState) GetState(addr common.Address, slot common.Hash) common.Hash {
return common.HexToHash("0x1234")
}
func TestBatchGetStorageAt(t *testing.T) {
api := &DebugAPI{b: &dummyBackend{}}
reqs := []StorageBatchRequest{
{Address: common.HexToAddress("0xabc"), Slots: []common.Hash{common.HexToHash("0x0"), common.HexToHash("0x1")}},
{Address: common.HexToAddress("0xdef"), Slots: []common.Hash{common.HexToHash("0x0")}},
}
res, err := api.BatchGetStorageAt(context.Background(), reqs, "latest")
if err != nil { t.Fatal(err) }
if res["0xabc"]["0x0"] != "0x0000000000000000000000000000000000001234" {
t.Errorf("unexpected value for 0xabc 0x0: %s", res["0xabc"]["0x0"])
}
}