mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-24 20:47:16 +00:00
issue/2028-support_parity_listStorageKeys (#3235)
This commit is contained in:
parent
db7fa3d0ed
commit
7ac165d462
@ -36,6 +36,7 @@ func APIList(ctx context.Context, db kv.RoDB,
|
||||
dbImpl := NewDBAPIImpl() /* deprecated */
|
||||
engineImpl := NewEngineAPI(base, db, eth)
|
||||
adminImpl := NewAdminAPI(eth)
|
||||
parityImpl := NewParityAPIImpl(db)
|
||||
|
||||
for _, enabledAPI := range cfg.API {
|
||||
switch enabledAPI {
|
||||
@ -116,6 +117,13 @@ func APIList(ctx context.Context, db kv.RoDB,
|
||||
Service: AdminAPI(adminImpl),
|
||||
Version: "1.0",
|
||||
})
|
||||
case "parity":
|
||||
defaultAPIList = append(defaultAPIList, rpc.API{
|
||||
Namespace: "parity",
|
||||
Public: false,
|
||||
Service: ParityAPI(parityImpl),
|
||||
Version: "1.0",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
72
cmd/rpcdaemon/commands/parity_api.go
Normal file
72
cmd/rpcdaemon/commands/parity_api.go
Normal file
@ -0,0 +1,72 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/ledgerwatch/erigon-lib/kv"
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/common/hexutil"
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
)
|
||||
|
||||
// ParityAPI the interface for the parity_ RPC commands
|
||||
type ParityAPI interface {
|
||||
ListStorageKeys(ctx context.Context, account common.Address, quantity int, offset *hexutil.Bytes) ([]hexutil.Bytes, error)
|
||||
}
|
||||
|
||||
// ParityAPIImpl data structure to store things needed for parity_ commands
|
||||
type ParityAPIImpl struct {
|
||||
db kv.RoDB
|
||||
}
|
||||
|
||||
// NewParityAPIImpl returns ParityAPIImpl instance
|
||||
func NewParityAPIImpl(db kv.RoDB) *ParityAPIImpl {
|
||||
return &ParityAPIImpl{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// ListStorageKeys implements parity_listStorageKeys. Returns all storage keys of the given address
|
||||
func (api *ParityAPIImpl) ListStorageKeys(ctx context.Context, account common.Address, quantity int, offset *hexutil.Bytes) ([]hexutil.Bytes, error) {
|
||||
tx, err := api.db.BeginRo(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listStorageKeys cannot open tx: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
a, err := state.NewPlainStateReader(tx).ReadAccountData(account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if a == nil {
|
||||
return nil, fmt.Errorf("acc not found")
|
||||
}
|
||||
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, a.GetIncarnation())
|
||||
seekBytes := append(account.Bytes(), b...)
|
||||
|
||||
c, err := tx.CursorDupSort(kv.PlainState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer c.Close()
|
||||
keys := make([]hexutil.Bytes, 0)
|
||||
var v []byte
|
||||
var seekVal []byte
|
||||
if offset != nil {
|
||||
seekVal = *offset
|
||||
}
|
||||
|
||||
for v, err = c.SeekBothRange(seekBytes, seekVal); v != nil && len(keys) != quantity && err == nil; _, v, err = c.NextDup() {
|
||||
if len(v) > common.HashLength {
|
||||
keys = append(keys, v[:common.HashLength])
|
||||
} else {
|
||||
keys = append(keys, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keys, nil
|
||||
}
|
102
cmd/rpcdaemon/commands/parity_api_test.go
Normal file
102
cmd/rpcdaemon/commands/parity_api_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
|
||||
"github.com/ledgerwatch/erigon/common"
|
||||
"github.com/ledgerwatch/erigon/common/hexutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParityAPIImpl_ListStorageKeys_NoOffset(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
api := NewParityAPIImpl(db)
|
||||
answers := []string{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"0a2127994676ca91e4eb3d2a1e46ec9dcee074dc2643bb5ebd4e9ac6541a3148",
|
||||
"0fe673b4bc06161f39bc26f4e8831c810a72ffe69e5c8cb26f7f54752618e696",
|
||||
"120e23dcb7e4437386073613853db77b10011a2404eefc716b97c7767e37f8eb",
|
||||
}
|
||||
addr := common.HexToAddress("0x920fd5070602feaea2e251e9e7238b6c376bcae5")
|
||||
result, err := api.ListStorageKeys(context.Background(), addr, 5, nil)
|
||||
if err != nil {
|
||||
t.Errorf("calling ListStorageKeys: %v", err)
|
||||
}
|
||||
assert.Equal(len(answers), len(result))
|
||||
for k, v := range result {
|
||||
assert.Equal(answers[k], common.Bytes2Hex(v))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParityAPIImpl_ListStorageKeys_WithOffset_ExistingPrefix(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
api := NewParityAPIImpl(db)
|
||||
answers := []string{
|
||||
"29d05770ca9ee7088a64e18c8e5160fc62c3c2179dc8ef9b4dbc970c9e51b4d8",
|
||||
"29edc84535d98b29835079d685b97b41ee8e831e343cc80793057e462353a26d",
|
||||
"2c05ac60f9aa2df5e64ef977f271e4b9a2d13951f123a2cb5f5d4ad5eb344f1a",
|
||||
"4644be453c81744b6842ddf615d7fca0e14a23b09734be63d44c23452de95631",
|
||||
"4974416255391052161ba8184fe652f3bf8c915592c65f7de127af8e637dce5d",
|
||||
}
|
||||
addr := common.HexToAddress("0x920fd5070602feaea2e251e9e7238b6c376bcae5")
|
||||
offset := common.Hex2Bytes("29")
|
||||
b := hexutil.Bytes(offset)
|
||||
result, err := api.ListStorageKeys(context.Background(), addr, 5, &b)
|
||||
if err != nil {
|
||||
t.Errorf("calling ListStorageKeys: %v", err)
|
||||
}
|
||||
assert.Equal(len(answers), len(result))
|
||||
for k, v := range result {
|
||||
assert.Equal(answers[k], common.Bytes2Hex(v))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParityAPIImpl_ListStorageKeys_WithOffset_NonExistingPrefix(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
api := NewParityAPIImpl(db)
|
||||
answers := []string{
|
||||
"4644be453c81744b6842ddf615d7fca0e14a23b09734be63d44c23452de95631",
|
||||
"4974416255391052161ba8184fe652f3bf8c915592c65f7de127af8e637dce5d",
|
||||
}
|
||||
addr := common.HexToAddress("0x920fd5070602feaea2e251e9e7238b6c376bcae5")
|
||||
offset := common.Hex2Bytes("30")
|
||||
b := hexutil.Bytes(offset)
|
||||
result, err := api.ListStorageKeys(context.Background(), addr, 2, &b)
|
||||
if err != nil {
|
||||
t.Errorf("calling ListStorageKeys: %v", err)
|
||||
}
|
||||
assert.Equal(len(answers), len(result))
|
||||
for k, v := range result {
|
||||
assert.Equal(answers[k], common.Bytes2Hex(v))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParityAPIImpl_ListStorageKeys_WithOffset_EmptyResponse(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
api := NewParityAPIImpl(db)
|
||||
addr := common.HexToAddress("0x920fd5070602feaea2e251e9e7238b6c376bcae5")
|
||||
offset := common.Hex2Bytes("ff")
|
||||
b := hexutil.Bytes(offset)
|
||||
result, err := api.ListStorageKeys(context.Background(), addr, 2, &b)
|
||||
if err != nil {
|
||||
t.Errorf("calling ListStorageKeys: %v", err)
|
||||
}
|
||||
assert.Equal(0, len(result))
|
||||
}
|
||||
|
||||
func TestParityAPIImpl_ListStorageKeys_AccNotFound(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
db := rpcdaemontest.CreateTestKV(t)
|
||||
api := NewParityAPIImpl(db)
|
||||
addr := common.HexToAddress("0x920fd5070602feaea2e251e9e7238b6c376bcaef")
|
||||
_, err := api.ListStorageKeys(context.Background(), addr, 2, nil)
|
||||
assert.Error(err, fmt.Errorf("acc not found"))
|
||||
}
|
Loading…
Reference in New Issue
Block a user