Get storage API, with storage leaf CID and raw IPLD block.
This commit is contained in:
parent
b90fcb53e6
commit
a284a566d5
@ -767,7 +767,7 @@ func (b *Backend) GetStorageByHash(ctx context.Context, address common.Address,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, storageRlp, err := b.IPLDRetriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address, key, hash)
|
_, _, storageRlp, err := b.IPLDRetriever.RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address, key, hash)
|
||||||
return storageRlp, err
|
return storageRlp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +29,15 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
RetrieveHeadersByHashesPgStr = `SELECT cid, data
|
RetrieveHeadersByHashesPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
||||||
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveHeadersByBlockNumberPgStr = `SELECT cid, data
|
RetrieveHeadersByBlockNumberPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
||||||
WHERE block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (header_cids.mh_key = blocks.key)
|
||||||
WHERE block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveUnclesByHashesPgStr = `SELECT cid, data
|
RetrieveUnclesByHashesPgStr = `SELECT cid, data
|
||||||
@ -429,25 +429,25 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveStorageAtByAddressAndStorageSlotAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage slot, and block hash
|
// RetrieveStorageAtByAddressAndStorageSlotAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage slot, and block hash
|
||||||
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address common.Address, key, hash common.Hash) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageSlotAndBlockHash(address common.Address, key, hash common.Hash) (string, []byte, []byte, error) {
|
||||||
storageResult := new(nodeInfo)
|
storageResult := new(nodeInfo)
|
||||||
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
storageHash := crypto.Keccak256Hash(key.Bytes())
|
storageHash := crypto.Keccak256Hash(key.Bytes())
|
||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
||||||
return "", nil, err
|
return "", nil, nil, err
|
||||||
}
|
}
|
||||||
if storageResult.Removed {
|
if storageResult.Removed {
|
||||||
return "", []byte{}, nil
|
return "", []byte{}, []byte{}, nil
|
||||||
}
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
||||||
err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
|
err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
|
||||||
return "", nil, err
|
return "", nil, nil, err
|
||||||
}
|
}
|
||||||
if len(i) != 2 {
|
if len(i) != 2 {
|
||||||
return "", nil, fmt.Errorf("eth IPLDRetriever expected storage leaf node rlp to decode into two elements")
|
return "", nil, nil, fmt.Errorf("eth IPLDRetriever expected storage leaf node rlp to decode into two elements")
|
||||||
}
|
}
|
||||||
return storageResult.CID, i[1].([]byte), nil
|
return storageResult.CID, storageResult.Data, i[1].([]byte), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber returns the cid and rlp bytes for the storage value corresponding to the provided address, storage key, and block number
|
// RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber returns the cid and rlp bytes for the storage value corresponding to the provided address, storage key, and block number
|
||||||
|
@ -956,12 +956,47 @@ func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria
|
|||||||
return runFilter(ctx, r.backend, filter)
|
return runFilter(ctx, r.backend, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StorageResult represents a storage slot value. All arguments are mandatory.
|
||||||
|
type StorageResult struct {
|
||||||
|
value []byte
|
||||||
|
cid string
|
||||||
|
ipldBlock []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorageResult) Value(ctx context.Context) common.Hash {
|
||||||
|
return common.BytesToHash(s.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorageResult) Cid(ctx context.Context) string {
|
||||||
|
return s.cid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StorageResult) IpldBlock(ctx context.Context) hexutil.Bytes {
|
||||||
|
return hexutil.Bytes(s.ipldBlock)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
|
func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
|
||||||
BlockHash common.Hash
|
BlockHash common.Hash
|
||||||
Contract common.Address
|
Contract common.Address
|
||||||
Slot common.Hash
|
Slot common.Hash
|
||||||
}) (*common.Hash, error) {
|
}) (*StorageResult, error) {
|
||||||
ret := common.BytesToHash([]byte{})
|
cid, ipldBlock, rlpValue, err := r.backend.IPLDRetriever.RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(args.Contract, args.Slot, args.BlockHash)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var value interface{}
|
||||||
|
err = rlp.DecodeBytes(rlpValue, &value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := StorageResult{value: value.([]byte), cid: cid, ipldBlock: ipldBlock}
|
||||||
|
|
||||||
return &ret, nil
|
return &ret, nil
|
||||||
}
|
}
|
||||||
|
@ -265,6 +265,17 @@ const schema string = `
|
|||||||
topics: [[Bytes32!]!]
|
topics: [[Bytes32!]!]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Storage trie value with IPLD data.
|
||||||
|
type StorageResult {
|
||||||
|
value: Bytes32!
|
||||||
|
|
||||||
|
# CID for the storage trie IPLD block.
|
||||||
|
cid: String!
|
||||||
|
|
||||||
|
# Storage trie IPLD block.
|
||||||
|
ipldBlock: Bytes!
|
||||||
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
# Block fetches an Ethereum block by number or by hash. If neither is
|
# Block fetches an Ethereum block by number or by hash. If neither is
|
||||||
# supplied, the most recent known block is returned.
|
# supplied, the most recent known block is returned.
|
||||||
@ -281,7 +292,7 @@ const schema string = `
|
|||||||
logs(filter: FilterCriteria!): [Log!]!
|
logs(filter: FilterCriteria!): [Log!]!
|
||||||
|
|
||||||
# Get storage slot by block hash and contract address.
|
# Get storage slot by block hash and contract address.
|
||||||
getStorageAt(blockHash: Bytes32!, contract: Address!, slot: Bytes32!): Bytes32
|
getStorageAt(blockHash: Bytes32!, contract: Address!, slot: Bytes32!): StorageResult
|
||||||
|
|
||||||
# Get contract logs by block hash and contract address.
|
# Get contract logs by block hash and contract address.
|
||||||
getLogs(blockHash: Bytes32!, contract: Address!): [Log!]
|
getLogs(blockHash: Bytes32!, contract: Address!): [Log!]
|
||||||
|
Loading…
Reference in New Issue
Block a user