Avoid two step queries for creating a block object
This commit is contained in:
parent
ddc7485c08
commit
86ef0b25d8
@ -39,7 +39,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/models"
|
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -281,7 +280,7 @@ func (b *Backend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.Blo
|
|||||||
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByNumber returns the requested canonical block.
|
// BlockByNumber returns the requested canonical block
|
||||||
func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) {
|
func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber) (*types.Block, error) {
|
||||||
var err error
|
var err error
|
||||||
number := blockNumber.Int64()
|
number := blockNumber.Int64()
|
||||||
@ -311,213 +310,118 @@ func (b *Backend) BlockByNumber(ctx context.Context, blockNumber rpc.BlockNumber
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Retrieve all the CIDs for the block
|
|
||||||
// TODO: optimize this by retrieving iplds directly rather than the cids first (this is remanent from when we fetched iplds through ipfs blockservice interface)
|
// Fetch header
|
||||||
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(canonicalHash)
|
header, err := b.HeaderByHash(ctx, canonicalHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("error fetching header", err)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin tx
|
// Fetch uncles
|
||||||
tx, err := b.DB.Beginx()
|
uncles, err := b.GetUnclesByBlockHash(ctx, canonicalHash)
|
||||||
if err != nil {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return nil, err
|
log.Error("error fetching uncles", err)
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if p := recover(); p != nil {
|
|
||||||
shared.Rollback(tx)
|
|
||||||
panic(p)
|
|
||||||
} else if err != nil {
|
|
||||||
shared.Rollback(tx)
|
|
||||||
} else {
|
|
||||||
err = tx.Commit()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Fetch and decode the header IPLD
|
|
||||||
var headerIPLD models.IPLDModel
|
|
||||||
headerIPLD, err = b.Fetcher.FetchHeader(tx, headerCID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error fetching header ipld", err)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var header types.Header
|
|
||||||
err = rlp.DecodeBytes(headerIPLD.Data, &header)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch and decode the uncle IPLDs
|
// Fetch transactions
|
||||||
var uncleIPLDs []models.IPLDModel
|
transactions, err := b.GetTransactionsByBlockHash(ctx, canonicalHash)
|
||||||
uncleIPLDs, err = b.Fetcher.FetchUncles(tx, uncleCIDs)
|
if err != nil && err != sql.ErrNoRows {
|
||||||
if err != nil {
|
log.Error("error fetching transactions", err)
|
||||||
log.Error("error fetching uncle iplds", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var uncles []*types.Header
|
|
||||||
for _, uncleIPLD := range uncleIPLDs {
|
|
||||||
var uncle types.Header
|
|
||||||
err = rlp.DecodeBytes(uncleIPLD.Data, &uncle)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
uncles = append(uncles, &uncle)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch and decode the transaction IPLDs
|
// Fetch receipts
|
||||||
var txIPLDs []models.IPLDModel
|
receipts, err := b.GetReceipts(ctx, canonicalHash)
|
||||||
txIPLDs, err = b.Fetcher.FetchTrxs(tx, txCIDs)
|
if err != nil && err != sql.ErrNoRows {
|
||||||
if err != nil {
|
log.Error("error fetching receipts", err)
|
||||||
log.Error("error fetching tx iplds", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var transactions []*types.Transaction
|
|
||||||
for _, txIPLD := range txIPLDs {
|
|
||||||
var transaction types.Transaction
|
|
||||||
err = transaction.UnmarshalBinary(txIPLD.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
transactions = append(transactions, &transaction)
|
|
||||||
}
|
|
||||||
// Fetch and decode the receipt IPLDs
|
|
||||||
var rctIPLDs []models.IPLDModel
|
|
||||||
rctIPLDs, err = b.Fetcher.FetchRcts(tx, rctCIDs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error fetching rct iplds", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var receipts []*types.Receipt
|
|
||||||
for _, rctIPLD := range rctIPLDs {
|
|
||||||
var receipt types.Receipt
|
|
||||||
nodeVal, err := DecodeLeafNode(rctIPLD.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = receipt.UnmarshalBinary(nodeVal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
receipts = append(receipts, &receipt)
|
|
||||||
}
|
|
||||||
// Compose everything together into a complete block
|
// Compose everything together into a complete block
|
||||||
return types.NewBlock(&header, transactions, uncles, receipts, new(trie.Trie)), err
|
return types.NewBlock(header, transactions, uncles, receipts, new(trie.Trie)), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
|
// BlockByHash returns the requested block
|
||||||
// detail, otherwise only the transaction hash is returned.
|
|
||||||
func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
|
func (b *Backend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
|
||||||
// Retrieve all the CIDs for the block
|
// Fetch header
|
||||||
headerCID, uncleCIDs, txCIDs, rctCIDs, err := b.Retriever.RetrieveBlockByHash(hash)
|
header, err := b.HeaderByHash(ctx, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error("error fetching header", err)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin tx
|
// Fetch uncles
|
||||||
tx, err := b.DB.Beginx()
|
uncles, err := b.GetUnclesByBlockHash(ctx, hash)
|
||||||
if err != nil {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
log.Error("error fetching uncles", err)
|
||||||
return nil, err
|
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()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Fetch and decode the header IPLD
|
// Fetch transactions
|
||||||
var headerIPLD models.IPLDModel
|
transactions, err := b.GetTransactionsByBlockHash(ctx, hash)
|
||||||
headerIPLD, err = b.Fetcher.FetchHeader(tx, headerCID)
|
if err != nil && err != sql.ErrNoRows {
|
||||||
if err != nil {
|
log.Error("error fetching transactions", err)
|
||||||
log.Error("error fetching header ipld", err)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var header types.Header
|
|
||||||
err = rlp.DecodeBytes(headerIPLD.Data, &header)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Fetch and decode the uncle IPLDs
|
|
||||||
var uncleIPLDs []models.IPLDModel
|
|
||||||
uncleIPLDs, err = b.Fetcher.FetchUncles(tx, uncleCIDs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error fetching uncle iplds", err)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var uncles []*types.Header
|
|
||||||
for _, uncleIPLD := range uncleIPLDs {
|
|
||||||
var uncle types.Header
|
|
||||||
err = rlp.DecodeBytes(uncleIPLD.Data, &uncle)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
uncles = append(uncles, &uncle)
|
|
||||||
}
|
|
||||||
// Fetch and decode the transaction IPLDs
|
|
||||||
var txIPLDs []models.IPLDModel
|
|
||||||
txIPLDs, err = b.Fetcher.FetchTrxs(tx, txCIDs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error fetching tx iplds", err)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var transactions []*types.Transaction
|
|
||||||
for _, txIPLD := range txIPLDs {
|
|
||||||
var transaction types.Transaction
|
|
||||||
err = transaction.UnmarshalBinary(txIPLD.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
transactions = append(transactions, &transaction)
|
|
||||||
}
|
|
||||||
// Fetch and decode the receipt IPLDs
|
|
||||||
var rctIPLDs []models.IPLDModel
|
|
||||||
rctIPLDs, err = b.Fetcher.FetchRcts(tx, rctCIDs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("error fetching rct iplds", err)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var receipts []*types.Receipt
|
|
||||||
for _, rctIPLD := range rctIPLDs {
|
|
||||||
var receipt types.Receipt
|
|
||||||
nodeVal, err := DecodeLeafNode(rctIPLD.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = receipt.UnmarshalBinary(nodeVal)
|
// Fetch receipts
|
||||||
if err != nil {
|
receipts, err := b.GetReceipts(ctx, hash)
|
||||||
return nil, err
|
if err != nil && err != sql.ErrNoRows {
|
||||||
}
|
log.Error("error fetching receipts", err)
|
||||||
receipts = append(receipts, &receipt)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compose everything together into a complete block
|
// Compose everything together into a complete block
|
||||||
return types.NewBlock(&header, transactions, uncles, receipts, new(trie.Trie)), err
|
return types.NewBlock(header, transactions, uncles, receipts, new(trie.Trie)), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnclesByBlockHash retrieves uncles for a provided block hash
|
||||||
|
func (b *Backend) GetUnclesByBlockHash(ctx context.Context, hash common.Hash) ([]*types.Header, error) {
|
||||||
|
_, uncleBytes, err := b.IPLDRetriever.RetrieveUnclesByBlockHash(hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uncles := make([]*types.Header, len(uncleBytes))
|
||||||
|
for i, bytes := range uncleBytes {
|
||||||
|
var uncle types.Header
|
||||||
|
err = rlp.DecodeBytes(bytes, &uncle)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uncles[i] = &uncle
|
||||||
|
}
|
||||||
|
|
||||||
|
return uncles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTransactionsByBlockHash retrieves transactions for a provided block hash
|
||||||
|
func (b *Backend) GetTransactionsByBlockHash(ctx context.Context, hash common.Hash) (types.Transactions, error) {
|
||||||
|
_, transactionBytes, err := b.IPLDRetriever.RetrieveTransactionsByBlockHash(hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txs := make(types.Transactions, len(transactionBytes))
|
||||||
|
for i, txBytes := range transactionBytes {
|
||||||
|
var tx types.Transaction
|
||||||
|
if err := tx.UnmarshalBinary(txBytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txs[i] = &tx
|
||||||
|
}
|
||||||
|
|
||||||
|
return txs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransaction retrieves a tx by hash
|
// GetTransaction retrieves a tx by hash
|
||||||
|
Loading…
Reference in New Issue
Block a user