forked from cerc-io/ipld-eth-server
move all sql statements into own file
This commit is contained in:
parent
907f15f640
commit
5bd9783aed
@ -1,47 +0,0 @@
|
|||||||
// VulcanizeDB
|
|
||||||
// Copyright © 2019 Vulcanize
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package eth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/bloombits"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FilterBackend is the geth interface we need to satisfy to use their filters
|
|
||||||
type FilterBackend interface {
|
|
||||||
ChainDb() ethdb.Database
|
|
||||||
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
|
|
||||||
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
|
|
||||||
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
|
||||||
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
|
||||||
|
|
||||||
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
|
||||||
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
|
||||||
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
|
|
||||||
SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription
|
|
||||||
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
|
|
||||||
|
|
||||||
BloomStatus() (uint64, uint64)
|
|
||||||
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
|
|
||||||
}
|
|
@ -1,367 +0,0 @@
|
|||||||
// VulcanizeDB
|
|
||||||
// Copyright © 2019 Vulcanize
|
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package eth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/cerc-io/ipld-eth-server/v4/pkg/shared"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/trie_helpers"
|
|
||||||
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
|
||||||
FROM eth.header_cids
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
header_cids.cid = blocks.key
|
|
||||||
AND header_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE block_hash = $1`
|
|
||||||
RetrieveUnclesPgStr = `SELECT uncle_cids.cid, data
|
|
||||||
FROM eth.uncle_cids
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
uncle_cids.header_id = header_cids.block_hash
|
|
||||||
AND uncle_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
uncle_cids.cid = blocks.key
|
|
||||||
AND uncle_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE header_cids.block_hash = $1
|
|
||||||
AND header_cids.block_number = $2
|
|
||||||
ORDER BY uncle_cids.parent_hash`
|
|
||||||
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data
|
|
||||||
FROM eth.uncle_cids
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
uncle_cids.header_id = header_cids.block_hash
|
|
||||||
AND uncle_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
uncle_cids.cid = blocks.key
|
|
||||||
AND uncle_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE header_cids.block_hash = $1
|
|
||||||
ORDER BY uncle_cids.parent_hash`
|
|
||||||
RetrieveTransactionsPgStr = `SELECT transaction_cids.cid, data
|
|
||||||
FROM eth.transaction_cids
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
transaction_cids.header_id = header_cids.block_hash
|
|
||||||
AND transaction_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
transaction_cids.cid = blocks.key
|
|
||||||
AND transaction_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE block_hash = $1
|
|
||||||
AND header_cids.block_number = $2
|
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
|
||||||
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
|
||||||
FROM eth.transaction_cids
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
transaction_cids.header_id = header_cids.block_hash
|
|
||||||
AND transaction_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
transaction_cids.cid = blocks.key
|
|
||||||
AND transaction_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE block_hash = $1
|
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
|
||||||
RetrieveReceiptsPgStr = `SELECT receipt_cids.cid, data, eth.transaction_cids.tx_hash
|
|
||||||
FROM eth.receipt_cids
|
|
||||||
INNER JOIN eth.transaction_cids ON (
|
|
||||||
receipt_cids.tx_id = transaction_cids.tx_hash
|
|
||||||
AND receipt_cids.header_id = transaction_cids.header_id
|
|
||||||
AND receipt_cids.block_number = transaction_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
transaction_cids.header_id = header_cids.block_hash
|
|
||||||
AND transaction_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
receipt_cids.cid = blocks.key
|
|
||||||
AND receipt_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE block_hash = $1
|
|
||||||
AND header_cids.block_number = $2
|
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
|
||||||
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data, eth.transaction_cids.tx_hash
|
|
||||||
FROM eth.receipt_cids
|
|
||||||
INNER JOIN eth.transaction_cids ON (
|
|
||||||
receipt_cids.tx_id = transaction_cids.tx_hash
|
|
||||||
AND receipt_cids.header_id = transaction_cids.header_id
|
|
||||||
AND receipt_cids.block_number = transaction_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
transaction_cids.header_id = header_cids.block_hash
|
|
||||||
AND transaction_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
INNER JOIN ipld.blocks ON (
|
|
||||||
receipt_cids.cid = blocks.key
|
|
||||||
AND receipt_cids.block_number = blocks.block_number
|
|
||||||
)
|
|
||||||
WHERE block_hash = $1
|
|
||||||
ORDER BY eth.transaction_cids.index ASC`
|
|
||||||
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, state_cids.block_number, state_cids.node_type
|
|
||||||
FROM eth.state_cids
|
|
||||||
INNER JOIN eth.header_cids ON (
|
|
||||||
state_cids.header_id = header_cids.block_hash
|
|
||||||
AND state_cids.block_number = header_cids.block_number
|
|
||||||
)
|
|
||||||
WHERE state_leaf_key = $1
|
|
||||||
AND header_cids.block_number <= (SELECT block_number
|
|
||||||
FROM eth.header_cids
|
|
||||||
WHERE block_hash = $2)
|
|
||||||
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
|
||||||
ORDER BY header_cids.block_number DESC
|
|
||||||
LIMIT 1`
|
|
||||||
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, block_number, node_type, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
|
|
||||||
)
|
|
||||||
|
|
||||||
var EmptyNodeValue = make([]byte, common.HashLength)
|
|
||||||
|
|
||||||
type rctIpldResult struct {
|
|
||||||
LeafCID string `db:"cid"`
|
|
||||||
Data []byte `db:"data"`
|
|
||||||
TxHash string `db:"tx_hash"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ipldResult struct {
|
|
||||||
CID string `db:"cid"`
|
|
||||||
Data []byte `db:"data"`
|
|
||||||
TxHash string `db:"tx_hash"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type IPLDRetriever struct {
|
|
||||||
db *sqlx.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIPLDRetriever(db *sqlx.DB) *IPLDRetriever {
|
|
||||||
return &IPLDRetriever{
|
|
||||||
db: db,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveHeaderByHash returns the cid and rlp bytes for the header corresponding to the provided block hash
|
|
||||||
func (r *IPLDRetriever) RetrieveHeaderByHash(tx *sqlx.Tx, hash common.Hash) (string, []byte, error) {
|
|
||||||
headerResult := new(ipldResult)
|
|
||||||
return headerResult.CID, headerResult.Data, tx.Get(headerResult, RetrieveHeaderByHashPgStr, hash.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveUncles returns the cids and rlp bytes for the uncles corresponding to the provided block hash, number (of non-omner root block)
|
|
||||||
func (r *IPLDRetriever) RetrieveUncles(tx *sqlx.Tx, hash common.Hash, number uint64) ([]string, [][]byte, error) {
|
|
||||||
uncleResults := make([]ipldResult, 0)
|
|
||||||
if err := tx.Select(&uncleResults, RetrieveUnclesPgStr, hash.Hex(), number); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(uncleResults))
|
|
||||||
uncles := make([][]byte, len(uncleResults))
|
|
||||||
for i, res := range uncleResults {
|
|
||||||
cids[i] = res.CID
|
|
||||||
uncles[i] = res.Data
|
|
||||||
}
|
|
||||||
return cids, uncles, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveUnclesByBlockHash returns the cids and rlp bytes for the uncles corresponding to the provided block hash (of non-omner root block)
|
|
||||||
func (r *IPLDRetriever) RetrieveUnclesByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, error) {
|
|
||||||
uncleResults := make([]ipldResult, 0)
|
|
||||||
if err := tx.Select(&uncleResults, RetrieveUnclesByBlockHashPgStr, hash.Hex()); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(uncleResults))
|
|
||||||
uncles := make([][]byte, len(uncleResults))
|
|
||||||
for i, res := range uncleResults {
|
|
||||||
cids[i] = res.CID
|
|
||||||
uncles[i] = res.Data
|
|
||||||
}
|
|
||||||
return cids, uncles, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveTransactions returns the cids and rlp bytes for the transactions corresponding to the provided block hash, number
|
|
||||||
func (r *IPLDRetriever) RetrieveTransactions(tx *sqlx.Tx, hash common.Hash, number uint64) ([]string, [][]byte, error) {
|
|
||||||
txResults := make([]ipldResult, 0)
|
|
||||||
if err := tx.Select(&txResults, RetrieveTransactionsPgStr, hash.Hex(), number); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(txResults))
|
|
||||||
txs := make([][]byte, len(txResults))
|
|
||||||
for i, res := range txResults {
|
|
||||||
cids[i] = res.CID
|
|
||||||
txs[i] = res.Data
|
|
||||||
}
|
|
||||||
return cids, txs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveTransactionsByBlockHash returns the cids and rlp bytes for the transactions corresponding to the provided block hash
|
|
||||||
func (r *IPLDRetriever) RetrieveTransactionsByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, error) {
|
|
||||||
txResults := make([]ipldResult, 0)
|
|
||||||
if err := tx.Select(&txResults, RetrieveTransactionsByBlockHashPgStr, hash.Hex()); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(txResults))
|
|
||||||
txs := make([][]byte, len(txResults))
|
|
||||||
for i, res := range txResults {
|
|
||||||
cids[i] = res.CID
|
|
||||||
txs[i] = res.Data
|
|
||||||
}
|
|
||||||
return cids, txs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeLeafNode decodes the leaf node data
|
|
||||||
func DecodeLeafNode(node []byte) ([]byte, error) {
|
|
||||||
var nodeElements []interface{}
|
|
||||||
if err := rlp.DecodeBytes(node, &nodeElements); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ty, err := trie_helpers.CheckKeyType(nodeElements)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ty != sdtypes.Leaf {
|
|
||||||
return nil, fmt.Errorf("expected leaf node but found %s", ty)
|
|
||||||
}
|
|
||||||
return nodeElements[1].([]byte), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveReceipts returns the cids and rlp bytes for the receipts corresponding to the provided block hash, number.
|
|
||||||
// cid returned corresponds to the leaf node data which contains the receipt.
|
|
||||||
func (r *IPLDRetriever) RetrieveReceipts(tx *sqlx.Tx, hash common.Hash, number uint64) ([]string, [][]byte, []common.Hash, error) {
|
|
||||||
rctResults := make([]rctIpldResult, 0)
|
|
||||||
if err := tx.Select(&rctResults, RetrieveReceiptsPgStr, hash.Hex(), number); err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(rctResults))
|
|
||||||
rcts := make([][]byte, len(rctResults))
|
|
||||||
txs := make([]common.Hash, len(rctResults))
|
|
||||||
|
|
||||||
for i, res := range rctResults {
|
|
||||||
cids[i] = res.LeafCID
|
|
||||||
nodeVal, err := DecodeLeafNode(res.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
rcts[i] = nodeVal
|
|
||||||
txs[i] = common.HexToHash(res.TxHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cids, rcts, txs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveReceiptsByBlockHash returns the cids and rlp bytes for the receipts corresponding to the provided block hash.
|
|
||||||
// cid returned corresponds to the leaf node data which contains the receipt.
|
|
||||||
func (r *IPLDRetriever) RetrieveReceiptsByBlockHash(tx *sqlx.Tx, hash common.Hash) ([]string, [][]byte, []common.Hash, error) {
|
|
||||||
rctResults := make([]rctIpldResult, 0)
|
|
||||||
if err := tx.Select(&rctResults, RetrieveReceiptsByBlockHashPgStr, hash.Hex()); err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
cids := make([]string, len(rctResults))
|
|
||||||
rcts := make([][]byte, len(rctResults))
|
|
||||||
txs := make([]common.Hash, len(rctResults))
|
|
||||||
|
|
||||||
for i, res := range rctResults {
|
|
||||||
cids[i] = res.LeafCID
|
|
||||||
nodeVal, err := DecodeLeafNode(res.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
rcts[i] = nodeVal
|
|
||||||
txs[i] = common.HexToHash(res.TxHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cids, rcts, txs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type nodeInfo struct {
|
|
||||||
CID string `db:"cid"`
|
|
||||||
BlockNumber string `db:"block_number"`
|
|
||||||
Data []byte `db:"data"`
|
|
||||||
NodeType int `db:"node_type"`
|
|
||||||
StateLeafRemoved bool `db:"state_leaf_removed"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
func (r *IPLDRetriever) RetrieveAccountByAddressAndBlockHash(address common.Address, hash common.Hash) (string, []byte, error) {
|
|
||||||
accountResult := new(nodeInfo)
|
|
||||||
leafKey := crypto.Keccak256Hash(address.Bytes())
|
|
||||||
if err := r.db.Get(accountResult, RetrieveAccountByLeafKeyAndBlockHashPgStr, leafKey.Hex(), hash.Hex()); err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if accountResult.NodeType == sdtypes.Removed.Int() {
|
|
||||||
return "", EmptyNodeValue, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNumber, err := strconv.ParseUint(accountResult.BlockNumber, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
accountResult.Data, err = shared.FetchIPLD(r.db, accountResult.CID, blockNumber)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var i []interface{}
|
|
||||||
if err := rlp.DecodeBytes(accountResult.Data, &i); err != nil {
|
|
||||||
return "", nil, fmt.Errorf("error decoding state leaf node rlp: %s", err.Error())
|
|
||||||
}
|
|
||||||
if len(i) != 2 {
|
|
||||||
return "", nil, fmt.Errorf("eth IPLDRetriever expected state leaf node rlp to decode into two elements")
|
|
||||||
}
|
|
||||||
return accountResult.CID, i[1].([]byte), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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, []byte, error) {
|
|
||||||
storageResult := new(nodeInfo)
|
|
||||||
stateLeafKey := crypto.Keccak256Hash(address.Bytes())
|
|
||||||
storageHash := crypto.Keccak256Hash(key.Bytes())
|
|
||||||
if err := r.db.Get(storageResult, RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr, stateLeafKey.Hex(), storageHash.Hex(), hash.Hex()); err != nil {
|
|
||||||
return "", nil, nil, err
|
|
||||||
}
|
|
||||||
if storageResult.StateLeafRemoved || storageResult.NodeType == sdtypes.Removed.Int() {
|
|
||||||
return "", EmptyNodeValue, EmptyNodeValue, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNumber, err := strconv.ParseUint(storageResult.BlockNumber, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, nil, err
|
|
||||||
}
|
|
||||||
storageResult.Data, err = shared.FetchIPLD(r.db, storageResult.CID, blockNumber)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var i []interface{}
|
|
||||||
if err := rlp.DecodeBytes(storageResult.Data, &i); err != nil {
|
|
||||||
err = fmt.Errorf("error decoding storage leaf node rlp: %s", err.Error())
|
|
||||||
return "", nil, nil, err
|
|
||||||
}
|
|
||||||
if len(i) != 2 {
|
|
||||||
return "", nil, nil, fmt.Errorf("eth IPLDRetriever expected storage leaf node rlp to decode into two elements")
|
|
||||||
}
|
|
||||||
return storageResult.CID, storageResult.Data, i[1].([]byte), nil
|
|
||||||
}
|
|
154
pkg/eth/sql.go
Normal file
154
pkg/eth/sql.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package eth
|
||||||
|
|
||||||
|
const (
|
||||||
|
RetrieveHeaderByHashPgStr = `SELECT cid, data
|
||||||
|
FROM eth.header_cids
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
header_cids.cid = blocks.key
|
||||||
|
AND header_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE block_hash = $1`
|
||||||
|
RetrieveUnclesPgStr = `SELECT uncle_cids.cid, data
|
||||||
|
FROM eth.uncle_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
uncle_cids.header_id = header_cids.block_hash
|
||||||
|
AND uncle_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
uncle_cids.cid = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE header_cids.block_hash = $1
|
||||||
|
AND header_cids.block_number = $2
|
||||||
|
ORDER BY uncle_cids.parent_hash`
|
||||||
|
RetrieveUnclesByBlockHashPgStr = `SELECT uncle_cids.cid, data
|
||||||
|
FROM eth.uncle_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
uncle_cids.header_id = header_cids.block_hash
|
||||||
|
AND uncle_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
uncle_cids.cid = blocks.key
|
||||||
|
AND uncle_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE header_cids.block_hash = $1
|
||||||
|
ORDER BY uncle_cids.parent_hash`
|
||||||
|
RetrieveTransactionsPgStr = `SELECT transaction_cids.cid, data
|
||||||
|
FROM eth.transaction_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
transaction_cids.cid = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE block_hash = $1
|
||||||
|
AND header_cids.block_number = $2
|
||||||
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
|
RetrieveTransactionsByBlockHashPgStr = `SELECT transaction_cids.cid, data
|
||||||
|
FROM eth.transaction_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
transaction_cids.cid = blocks.key
|
||||||
|
AND transaction_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE block_hash = $1
|
||||||
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
|
RetrieveReceiptsPgStr = `SELECT receipt_cids.cid, data, eth.transaction_cids.tx_hash
|
||||||
|
FROM eth.receipt_cids
|
||||||
|
INNER JOIN eth.transaction_cids ON (
|
||||||
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.header_id = transaction_cids.header_id
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
receipt_cids.cid = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE block_hash = $1
|
||||||
|
AND header_cids.block_number = $2
|
||||||
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
|
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data, eth.transaction_cids.tx_hash
|
||||||
|
FROM eth.receipt_cids
|
||||||
|
INNER JOIN eth.transaction_cids ON (
|
||||||
|
receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.header_id = transaction_cids.header_id
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
INNER JOIN ipld.blocks ON (
|
||||||
|
receipt_cids.cid = blocks.key
|
||||||
|
AND receipt_cids.block_number = blocks.block_number
|
||||||
|
)
|
||||||
|
WHERE block_hash = $1
|
||||||
|
ORDER BY eth.transaction_cids.index ASC`
|
||||||
|
RetrieveAccountByLeafKeyAndBlockHashPgStr = `SELECT state_cids.cid, state_cids.block_number, state_cids.node_type
|
||||||
|
FROM eth.state_cids
|
||||||
|
INNER JOIN eth.header_cids ON (
|
||||||
|
state_cids.header_id = header_cids.block_hash
|
||||||
|
AND state_cids.block_number = header_cids.block_number
|
||||||
|
)
|
||||||
|
WHERE state_leaf_key = $1
|
||||||
|
AND header_cids.block_number <= (SELECT block_number
|
||||||
|
FROM eth.header_cids
|
||||||
|
WHERE block_hash = $2)
|
||||||
|
AND header_cids.block_hash = (SELECT canonical_header_hash(header_cids.block_number))
|
||||||
|
ORDER BY header_cids.block_number DESC
|
||||||
|
LIMIT 1`
|
||||||
|
RetrieveFilteredGQLLogs = `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.header_id as block_hash,
|
||||||
|
eth.log_cids.cid, eth.log_cids.index, eth.log_cids.rct_id, eth.log_cids.address,
|
||||||
|
eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3, eth.log_cids.log_data,
|
||||||
|
data, eth.receipt_cids.cid, eth.receipt_cids.post_status, eth.receipt_cids.tx_id AS tx_hash
|
||||||
|
FROM eth.log_cids, eth.receipt_cids, ipld.blocks
|
||||||
|
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
||||||
|
AND eth.log_cids.header_id = receipt_cids.header_id
|
||||||
|
AND eth.log_cids.block_number = receipt_cids.block_number
|
||||||
|
AND log_cids.cid = blocks.key
|
||||||
|
AND log_cids.block_number = blocks.block_number
|
||||||
|
AND receipt_cids.header_id = $1`
|
||||||
|
RetrieveFilteredLogs = `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.cid, eth.log_cids.index, eth.log_cids.rct_id,
|
||||||
|
eth.log_cids.address, eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3,
|
||||||
|
eth.log_cids.log_data, eth.transaction_cids.tx_hash, eth.transaction_cids.index as txn_index,
|
||||||
|
eth.receipt_cids.cid as cid, eth.receipt_cids.post_status, header_cids.block_hash
|
||||||
|
FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids
|
||||||
|
WHERE eth.log_cids.rct_id = receipt_cids.tx_id
|
||||||
|
AND eth.log_cids.header_id = eth.receipt_cids.header_id
|
||||||
|
AND eth.log_cids.block_number = eth.receipt_cids.block_number
|
||||||
|
AND receipt_cids.tx_id = transaction_cids.tx_hash
|
||||||
|
AND receipt_cids.header_id = transaction_cids.header_id
|
||||||
|
AND receipt_cids.block_number = transaction_cids.block_number
|
||||||
|
AND transaction_cids.header_id = header_cids.block_hash
|
||||||
|
AND transaction_cids.block_number = header_cids.block_number`
|
||||||
|
RetrieveStorageLeafByAddressHashAndLeafKeyAndBlockHashPgStr = `SELECT cid, block_number, node_type, state_leaf_removed FROM get_storage_at_by_hash($1, $2, $3)`
|
||||||
|
)
|
||||||
|
|
||||||
|
type rctIpldResult struct {
|
||||||
|
LeafCID string `db:"cid"`
|
||||||
|
Data []byte `db:"data"`
|
||||||
|
TxHash string `db:"tx_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ipldResult struct {
|
||||||
|
CID string `db:"cid"`
|
||||||
|
Data []byte `db:"data"`
|
||||||
|
TxHash string `db:"tx_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeInfo struct {
|
||||||
|
CID string `db:"cid"`
|
||||||
|
BlockNumber string `db:"block_number"`
|
||||||
|
Data []byte `db:"data"`
|
||||||
|
NodeType int `db:"node_type"`
|
||||||
|
StateLeafRemoved bool `db:"state_leaf_removed"`
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user