postgres functions to check if node was removed (e.g. a la EIP158) in a range; update backend to use these to retrieve state and storage leafs in single (albeit complex) SELECT query
This commit is contained in:
parent
7c06d4b3a1
commit
b128f894c4
37
db/migrations/00018_create_check_if_removed_functions.sql
Normal file
37
db/migrations/00018_create_check_if_removed_functions.sql
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- +goose StatementBegin
|
||||||
|
-- returns if a storage node at the provided path was removed in the range > the provided height and <= the provided block hash
|
||||||
|
CREATE OR REPLACE FUNCTION was_storage_removed(path BYTEA, height BIGINT, hash VARCHAR(66)) RETURNS BOOLEAN
|
||||||
|
AS $$
|
||||||
|
SELECT exists(SELECT *
|
||||||
|
FROM eth.storage_cids
|
||||||
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
WHERE storage_path = path
|
||||||
|
AND block_number > height
|
||||||
|
AND block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = hash)
|
||||||
|
AND storage_cids.node_type = 3);
|
||||||
|
$$ LANGUAGE SQL;
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose StatementBegin
|
||||||
|
-- returns if a state node at the provided path was removed in the range > the provided height and <= the provided block hash
|
||||||
|
CREATE OR REPLACE FUNCTION was_state_removed(path BYTEA, height BIGINT, hash VARCHAR(66)) RETURNS BOOLEAN
|
||||||
|
AS $$
|
||||||
|
SELECT exists(SELECT *
|
||||||
|
FROM eth.state_cids
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
WHERE state_path = path
|
||||||
|
AND block_number > height
|
||||||
|
AND block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = hash)
|
||||||
|
AND state_cids.node_type = 3);
|
||||||
|
$$ LANGUAGE SQL;
|
||||||
|
-- +goose StatementEnd
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
DROP FUNCTION was_storage_removed;
|
||||||
|
DROP FUNCTION was_state_removed;
|
@ -100,6 +100,45 @@ CREATE FUNCTION public.header_weight(hash character varying) RETURNS bigint
|
|||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: was_state_removed(bytea, bigint, character varying); Type: FUNCTION; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE FUNCTION public.was_state_removed(path bytea, height bigint, hash character varying) RETURNS boolean
|
||||||
|
LANGUAGE sql
|
||||||
|
AS $$
|
||||||
|
SELECT exists(SELECT *
|
||||||
|
FROM eth.state_cids
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
WHERE state_path = path
|
||||||
|
AND block_number > height
|
||||||
|
AND block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = hash)
|
||||||
|
AND state_cids.node_type = 3);
|
||||||
|
$$;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: was_storage_removed(bytea, bigint, character varying); Type: FUNCTION; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE FUNCTION public.was_storage_removed(path bytea, height bigint, hash character varying) RETURNS boolean
|
||||||
|
LANGUAGE sql
|
||||||
|
AS $$
|
||||||
|
SELECT exists(SELECT *
|
||||||
|
FROM eth.storage_cids
|
||||||
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
WHERE storage_path = path
|
||||||
|
AND block_number > height
|
||||||
|
AND block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = hash)
|
||||||
|
AND storage_cids.node_type = 3);
|
||||||
|
$$;
|
||||||
|
|
||||||
|
|
||||||
SET default_tablespace = '';
|
SET default_tablespace = '';
|
||||||
|
|
||||||
SET default_table_access_method = heap;
|
SET default_table_access_method = heap;
|
||||||
|
@ -19,8 +19,6 @@ package eth
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
@ -34,7 +32,8 @@ const (
|
|||||||
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 FROM eth.header_cids
|
RetrieveHeadersByBlockNumberPgStr = `SELECT cid, data
|
||||||
|
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
|
||||||
@ -45,15 +44,16 @@ const (
|
|||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
||||||
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
WHERE block_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data FROM eth.uncle_cids, eth.header_cids, public.blocks
|
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data
|
||||||
WHERE uncle_cids.header_id = header_cids.id
|
FROM eth.uncle_cids
|
||||||
AND uncle_cids.mh_key = blocks.key
|
INNER JOIN eth.header_cids ON (uncle_cids.header_id = header_cids.id)
|
||||||
AND block_hash = $1`
|
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
||||||
|
WHERE block_hash = $1`
|
||||||
RetrieveUnclesByBlockNumberPgStr = `SELECT uncle_cids.cid, data
|
RetrieveUnclesByBlockNumberPgStr = `SELECT uncle_cids.cid, data
|
||||||
FROM eth.uncle_cids, eth.header_cids, public.blocks
|
FROM eth.uncle_cids
|
||||||
WHERE uncle_cids.header_id = header_cids.id
|
INNER JOIN eth.header_cids ON (uncle_cids.header_id = header_cids.id)
|
||||||
AND uncle_cids.mh_key = blocks.key
|
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
||||||
AND block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveUncleByHashPgStr = `SELECT cid, data
|
RetrieveUncleByHashPgStr = `SELECT cid, data
|
||||||
FROM eth.uncle_cids
|
FROM eth.uncle_cids
|
||||||
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (uncle_cids.mh_key = blocks.key)
|
||||||
@ -63,75 +63,90 @@ const (
|
|||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
||||||
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
||||||
FROM eth.transaction_cids, eth.header_cids, public.blocks
|
FROM eth.transaction_cids
|
||||||
WHERE transaction_cids.header_id = header_cids.id
|
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id)
|
||||||
AND transaction_cids.mh_key = blocks.key
|
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
||||||
AND block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveTransactionsByBlockNumberPgStr = `SELECT transaction_cids.cid, data
|
RetrieveTransactionsByBlockNumberPgStr = `SELECT transaction_cids.cid, data
|
||||||
FROM eth.transaction_cids, eth.header_cids, public.blocks
|
FROM eth.transaction_cids
|
||||||
WHERE transaction_cids.header_id = header_cids.id
|
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id)
|
||||||
AND transaction_cids.mh_key = blocks.key
|
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
||||||
AND block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveTransactionByHashPgStr = `SELECT cid, data FROM eth.transaction_cids
|
RetrieveTransactionByHashPgStr = `SELECT cid, data
|
||||||
|
FROM eth.transaction_cids
|
||||||
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
INNER JOIN public.blocks ON (transaction_cids.mh_key = blocks.key)
|
||||||
WHERE tx_hash = $1`
|
WHERE tx_hash = $1`
|
||||||
RetrieveReceiptsByTxHashesPgStr = `SELECT receipt_cids.cid, data
|
RetrieveReceiptsByTxHashesPgStr = `SELECT receipt_cids.cid, data
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, public.blocks
|
FROM eth.receipt_cids
|
||||||
WHERE receipt_cids.mh_key = blocks.key
|
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
|
||||||
AND receipt_cids.tx_id = transaction_cids.id
|
INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key)
|
||||||
AND tx_hash = ANY($1::VARCHAR(66)[])`
|
WHERE tx_hash = ANY($1::VARCHAR(66)[])`
|
||||||
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data
|
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks
|
FROM eth.receipt_cids
|
||||||
WHERE receipt_cids.tx_id = transaction_cids.id
|
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
|
||||||
AND transaction_cids.header_id = header_cids.id
|
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id)
|
||||||
AND receipt_cids.mh_key = blocks.key
|
INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key)
|
||||||
AND block_hash = $1`
|
WHERE block_hash = $1`
|
||||||
RetrieveReceiptsByBlockNumberPgStr = `SELECT receipt_cids.cid, data
|
RetrieveReceiptsByBlockNumberPgStr = `SELECT receipt_cids.cid, data
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks
|
FROM eth.receipt_cids
|
||||||
WHERE receipt_cids.tx_id = transaction_cids.id
|
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
|
||||||
AND transaction_cids.header_id = header_cids.id
|
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id)
|
||||||
AND receipt_cids.mh_key = blocks.key
|
INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key)
|
||||||
AND block_number = $1`
|
WHERE block_number = $1`
|
||||||
RetrieveReceiptByTxHashPgStr = `SELECT receipt_cids.cid, data
|
RetrieveReceiptByTxHashPgStr = `SELECT receipt_cids.cid, data
|
||||||
FROM eth.receipt_cids, eth.transaction_cids, eth.receipt_cids
|
FROM eth.receipt_cids
|
||||||
WHERE receipt_cids.mh_key = blocks.key
|
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
|
||||||
AND receipt_cids.tx_id = transaction_cids.id
|
INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key)
|
||||||
AND tx_hash = $1`
|
WHERE tx_hash = $1`
|
||||||
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, data
|
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid,
|
||||||
FROM eth.state_cids, eth.header_cids, public.blocks
|
data,
|
||||||
WHERE state_cids.header_id = header_cids.id
|
was_state_removed(state_path, block_number, $2) AS removed
|
||||||
AND state_cids.mh_key = blocks.key
|
FROM eth.state_cids
|
||||||
AND state_leaf_key = $1
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
INNER JOIN public.blocks ON (state_cids.mh_key = blocks.key)
|
||||||
|
WHERE state_leaf_key = $1
|
||||||
AND block_number <= (SELECT block_number
|
AND block_number <= (SELECT block_number
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
WHERE block_hash = $2)
|
WHERE block_hash = $2)
|
||||||
AND header_cids.id = (SELECT canonical_header(block_number))
|
AND header_cids.id = (SELECT canonical_header(block_number))
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveAccountByLeafKeyAndBlockNumberPgStr = `SELECT state_cids.cid, data
|
RetrieveAccountByLeafKeyAndBlockNumberPgStr = `SELECT state_cids.cid,
|
||||||
FROM eth.state_cids, eth.header_cids, public.blocks
|
data,
|
||||||
WHERE state_cids.header_id = header_cids.id
|
was_state_removed(state_path, block_number, (SELECT block_hash
|
||||||
AND state_cids.mh_key = blocks.key
|
FROM eth.header_cids
|
||||||
AND state_leaf_key = $1
|
WHERE block_number = $2
|
||||||
|
LIMIT 1)) AS removed
|
||||||
|
FROM eth.state_cids
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
INNER JOIN public.blocks ON (state_cids.mh_key = blocks.key)
|
||||||
|
WHERE state_leaf_key = $1
|
||||||
AND block_number <= $2
|
AND block_number <= $2
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid, data
|
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr = `SELECT storage_cids.cid,
|
||||||
FROM eth.storage_cids, eth.state_cids, eth.header_cids, public.blocks
|
data,
|
||||||
WHERE storage_cids.state_id = state_cids.id
|
was_storage_removed(storage_path, block_number, (SELECT block_hash
|
||||||
AND state_cids.header_id = header_cids.id
|
FROM eth.header_cids
|
||||||
AND storage_cids.mh_key = blocks.key
|
WHERE block_number = $3
|
||||||
AND state_leaf_key = $1
|
LIMIT 1)) AS removed
|
||||||
|
FROM eth.storage_cids
|
||||||
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
INNER JOIN public.blocks ON (storage_cids.mh_key = blocks.key)
|
||||||
|
WHERE state_leaf_key = $1
|
||||||
AND storage_leaf_key = $2
|
AND storage_leaf_key = $2
|
||||||
AND block_number <= $3
|
AND block_number <= $3
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
retrieveStorageInfoPgStr = `SELECT storage_cids.cid, data, storage_path, block_number
|
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT storage_cids.cid,
|
||||||
FROM eth.storage_cids, eth.state_cids, eth.header_cids, public.blocks
|
data,
|
||||||
WHERE storage_cids.state_id = state_cids.id
|
was_storage_removed(storage_path, block_number, $3) AS removed
|
||||||
AND state_cids.header_id = header_cids.id
|
FROM eth.storage_cids
|
||||||
AND storage_cids.mh_key = blocks.key
|
INNER JOIN eth.state_cids ON (storage_cids.state_id = state_cids.id)
|
||||||
AND state_leaf_key = $1
|
INNER JOIN eth.header_cids ON (state_cids.header_id = header_cids.id)
|
||||||
|
INNER JOIN public.blocks ON (storage_cids.mh_key = blocks.key)
|
||||||
|
WHERE state_leaf_key = $1
|
||||||
AND storage_leaf_key = $2
|
AND storage_leaf_key = $2
|
||||||
AND block_number <= (SELECT block_number
|
AND block_number <= (SELECT block_number
|
||||||
FROM eth.header_cids
|
FROM eth.header_cids
|
||||||
@ -139,15 +154,6 @@ const (
|
|||||||
AND header_cids.id = (SELECT canonical_header(block_number))
|
AND header_cids.id = (SELECT canonical_header(block_number))
|
||||||
ORDER BY block_number DESC
|
ORDER BY block_number DESC
|
||||||
LIMIT 1`
|
LIMIT 1`
|
||||||
wasNodeDeletedpgStr = `SELECT exists(SELECT *
|
|
||||||
FROM eth.storage_cids, eth.state_cids, eth.header_cids
|
|
||||||
WHERE storage_cids.state_id = state_cids.id
|
|
||||||
AND storage_path = $1
|
|
||||||
AND block_number > $2
|
|
||||||
AND block_number <= (SELECT block_number
|
|
||||||
FROM eth.header_cids
|
|
||||||
WHERE block_hash = $3)
|
|
||||||
AND storage_cids.node_type = 3)`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ipldResult struct {
|
type ipldResult struct {
|
||||||
@ -370,14 +376,23 @@ func (r *IPLDRetriever) RetrieveReceiptByHash(hash common.Hash) (string, []byte,
|
|||||||
return rctResult.CID, rctResult.Data, r.db.Get(rctResult, RetrieveReceiptByTxHashPgStr, hash.Hex())
|
return rctResult.CID, rctResult.Data, r.db.Get(rctResult, RetrieveReceiptByTxHashPgStr, hash.Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nodeInfo struct {
|
||||||
|
CID string `db:"cid"`
|
||||||
|
Data []byte `db:"data"`
|
||||||
|
Removed bool `db:"removed"`
|
||||||
|
}
|
||||||
|
|
||||||
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
|
// RetrieveAccountByAddressAndBlockHash returns the cid and rlp bytes for the account corresponding to the provided address and block hash
|
||||||
// TODO: ensure this handles deleted accounts appropriately
|
// TODO: ensure this handles deleted accounts appropriately
|
||||||
func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (string, []byte, error) {
|
||||||
accountResult := new(ipldResult)
|
accountResult := new(nodeInfo)
|
||||||
leafKey := crypto.Keccak256Hash(address.Bytes())
|
leafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
|
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
if accountResult.Removed {
|
||||||
|
return "", []byte{}, nil
|
||||||
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
||||||
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
||||||
@ -391,11 +406,14 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Addr
|
|||||||
// RetrieveAccountByAddressAndBlockNumber returns the cid and rlp bytes for the account corresponding to the provided address and block number
|
// RetrieveAccountByAddressAndBlockNumber returns the cid and rlp bytes for the account corresponding to the provided address and block number
|
||||||
// This can return a non-canonical account
|
// This can return a non-canonical account
|
||||||
func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Address, number uint64) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Address, number uint64) (string, []byte, error) {
|
||||||
accountResult := new(ipldResult)
|
accountResult := new(nodeInfo)
|
||||||
leafKey := crypto.Keccak256Hash(address.Bytes())
|
leafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockNumberPgStr, leafKey.Hex(), number); err != nil {
|
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockNumberPgStr, leafKey.Hex(), number); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
if accountResult.Removed {
|
||||||
|
return "", []byte{}, nil
|
||||||
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
||||||
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
||||||
@ -406,42 +424,14 @@ func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockNumber(address common.Ad
|
|||||||
return accountResult.CID, i[1].([]byte), nil
|
return accountResult.CID, i[1].([]byte), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageInfo struct {
|
|
||||||
CID string `db:"cid"`
|
|
||||||
Data []byte `db:"data"`
|
|
||||||
Path []byte `db:"storage_path"`
|
|
||||||
BlockNumber uint64 `db:"block_number"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveStorageAtByAddressAndStorageKeyAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage key, and block hash
|
// RetrieveStorageAtByAddressAndStorageKeyAndBlockHash returns the cid and rlp bytes for the storage value corresponding to the provided address, storage key, and block hash
|
||||||
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(address common.Address, storageLeafKey, hash common.Hash) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(address common.Address, storageLeafKey, hash common.Hash) (string, []byte, error) {
|
||||||
// Begin tx
|
storageResult := new(nodeInfo)
|
||||||
tx, err := r.db.Beginx()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if p := recover(); p != nil {
|
|
||||||
shared.Rollback(tx)
|
|
||||||
panic(p)
|
|
||||||
} else if err != nil {
|
|
||||||
shared.Rollback(tx)
|
|
||||||
} else {
|
|
||||||
err = tx.Commit()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
storageResult := new(storageInfo)
|
|
||||||
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
if err := tx.Get(storageResult, retrieveStorageInfoPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), hash.Hex()); err != nil {
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), hash.Hex()); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
if storageResult.Removed {
|
||||||
deleted := false
|
|
||||||
if err := tx.Get(&deleted, wasNodeDeletedpgStr, storageResult.Path, storageResult.BlockNumber, hash.Hex()); err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
if deleted {
|
|
||||||
return "", []byte{}, nil
|
return "", []byte{}, nil
|
||||||
}
|
}
|
||||||
var i []interface{}
|
var i []interface{}
|
||||||
@ -450,20 +440,22 @@ func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockHash(addr
|
|||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
if len(i) != 2 {
|
if len(i) != 2 {
|
||||||
err = fmt.Errorf("eth IPLDRetriever expected storage leaf node rlp to decode into two elements")
|
return "", nil, fmt.Errorf("eth IPLDRetriever expected storage leaf node rlp to decode into two elements")
|
||||||
return "", nil, err
|
|
||||||
}
|
}
|
||||||
return storageResult.CID, i[1].([]byte), err
|
return storageResult.CID, 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
|
||||||
// This can retrun a non-canonical value
|
// This can retrun a non-canonical value
|
||||||
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber(address common.Address, storageLeafKey common.Hash, number uint64) (string, []byte, error) {
|
func (r *IPLDRetriever) RetrieveStorageAtByAddressAndStorageKeyAndBlockNumber(address common.Address, storageLeafKey common.Hash, number uint64) (string, []byte, error) {
|
||||||
storageResult := new(ipldResult)
|
storageResult := new(nodeInfo)
|
||||||
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), number); err != nil {
|
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockNumberPgStr, stateLeafKey.Hex(), storageLeafKey.Hex(), number); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
if storageResult.Removed {
|
||||||
|
return "", []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 {
|
||||||
return "", nil, fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
|
return "", nil, fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
|
||||||
|
Loading…
Reference in New Issue
Block a user