mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 12:46:44 +00:00
cmd/geth: implement debug_batchGetStorageAt RPC (Closes #32591)
This commit is contained in:
parent
a541f84fa3
commit
95a0ff03f4
2 changed files with 99 additions and 0 deletions
63
internal/ethapi/debug_api.go
Normal file
63
internal/ethapi/debug_api.go
Normal 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
|
||||
}
|
||||
36
internal/ethapi/debug_api_test.go
Normal file
36
internal/ethapi/debug_api_test.go
Normal 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"])
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue