From 6c77d63dc252998bffcec39fe9437d7239879183 Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Wed, 26 Jun 2024 08:52:59 +0800 Subject: [PATCH] core/types: replace core.SetReceiptsData with receipts.DeriveFields --- core/blockchain.go | 56 ++++++-------------------------------------- light/odr_util.go | 19 +++++++++++++-- light/postprocess.go | 2 +- 3 files changed, 25 insertions(+), 52 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 48a7e69b5e..247319a91e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1029,49 +1029,6 @@ func (bc *BlockChain) Rollback(chain []common.Hash) { } } -// SetReceiptsData computes all the non-consensus fields of the receipts -func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts types.Receipts) error { - signer := types.MakeSigner(config, block.Number()) - - transactions, logIndex := block.Transactions(), uint(0) - if len(transactions) != len(receipts) { - return errors.New("transaction and receipt count mismatch") - } - - for j := 0; j < len(receipts); j++ { - // The transaction hash can be retrieved from the transaction itself - receipts[j].TxHash = transactions[j].Hash() - - // block location fields - receipts[j].BlockHash = block.Hash() - receipts[j].BlockNumber = block.Number() - receipts[j].TransactionIndex = uint(j) - - // The contract address can be derived from the transaction itself - if transactions[j].To() == nil { - // Deriving the signer is expensive, only do if it's actually needed - from, _ := types.Sender(signer, transactions[j]) - receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce()) - } - // The used gas can be calculated based on previous receipts - if j == 0 { - receipts[j].GasUsed = receipts[j].CumulativeGasUsed - } else { - receipts[j].GasUsed = receipts[j].CumulativeGasUsed - receipts[j-1].CumulativeGasUsed - } - // The derived log fields can simply be set from the block and transaction - for k := 0; k < len(receipts[j].Logs); k++ { - receipts[j].Logs[k].BlockNumber = block.NumberU64() - receipts[j].Logs[k].BlockHash = block.Hash() - receipts[j].Logs[k].TxHash = receipts[j].TxHash - receipts[j].Logs[k].TxIndex = uint(j) - receipts[j].Logs[k].Index = logIndex - logIndex++ - } - } - return nil -} - // InsertReceiptChain attempts to complete an already existing header chain with // transaction and receipt data. func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { @@ -1100,22 +1057,23 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if atomic.LoadInt32(&bc.procInterrupt) == 1 { return 0, nil } + blockHash, blockNumber := block.Hash(), block.NumberU64() // Short circuit if the owner header is unknown - if !bc.HasHeader(block.Hash(), block.NumberU64()) { - return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) + if !bc.HasHeader(blockHash, blockNumber) { + return i, fmt.Errorf("containing header #%d [%x…] unknown", blockNumber, blockHash.Bytes()[:4]) } // Skip if the entire data is already known - if bc.HasBlock(block.Hash(), block.NumberU64()) { + if bc.HasBlock(blockHash, blockNumber) { stats.ignored++ continue } // Compute all the non-consensus fields of the receipts - if err := SetReceiptsData(bc.chainConfig, block, receipts); err != nil { + if err := receipts.DeriveFields(bc.chainConfig, blockHash, blockNumber, block.Transactions()); err != nil { return i, fmt.Errorf("failed to set receipts data: %v", err) } // Write all the data out into the database - rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()) - if err := WriteBlockReceipts(batch, block.Hash(), block.NumberU64(), receipts); err != nil { + rawdb.WriteBody(batch, blockHash, blockNumber, block.Body()) + if err := WriteBlockReceipts(batch, blockHash, blockNumber, receipts); err != nil { return i, fmt.Errorf("failed to write block receipts: %v", err) } if err := WriteTxLookupEntries(batch, block); err != nil { diff --git a/light/odr_util.go b/light/odr_util.go index d7ebd6739f..11ddda877a 100644 --- a/light/odr_util.go +++ b/light/odr_util.go @@ -19,6 +19,7 @@ package light import ( "bytes" "context" + "errors" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core" @@ -29,6 +30,13 @@ import ( var sha3_nil = crypto.Keccak256Hash(nil) +// errNonCanonicalHash is returned if the requested chain data doesn't belong +// to the canonical chain. ODR can only retrieve the canonical chain data covered +// by the CHT or Bloom trie for verification. +var errNonCanonicalHash = errors.New("hash is not currently canonical") + +// GetHeaderByNumber retrieves the canonical block header corresponding to the +// given number. The returned header is proven by local CHT. func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { db := odr.Database() hash := core.GetCanonicalHash(db, number) @@ -113,7 +121,7 @@ func GetBlock(ctx context.Context, odr OdrBackend, hash common.Hash, number uint // Retrieve the block header and body contents header := core.GetHeader(odr.Database(), hash, number) if header == nil { - return nil, ErrNoHeader + return nil, errNoHeader } body, err := GetBody(ctx, odr, hash, number) if err != nil { @@ -129,6 +137,13 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num // Retrieve the potentially incomplete receipts from disk or network receipts := core.GetBlockReceipts(odr.Database(), hash, number) if receipts == nil { + header, err := GetHeaderByNumber(ctx, odr, number) + if err != nil { + return nil, errNoHeader + } + if header.Hash() != hash { + return nil, errNonCanonicalHash + } r := &ReceiptsRequest{Hash: hash, Number: number} if err := odr.Retrieve(ctx, r); err != nil { return nil, err @@ -144,7 +159,7 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num genesis := core.GetCanonicalHash(odr.Database(), 0) config, _ := core.GetChainConfig(odr.Database(), genesis) - if err := core.SetReceiptsData(config, block, receipts); err != nil { + if err := receipts.DeriveFields(config, hash, number, block.Transactions()); err != nil { return nil, err } core.WriteBlockReceipts(odr.Database(), hash, number, receipts) diff --git a/light/postprocess.go b/light/postprocess.go index f407c85d14..5f6799cf7a 100644 --- a/light/postprocess.go +++ b/light/postprocess.go @@ -83,7 +83,7 @@ var trustedCheckpoints = map[common.Hash]trustedCheckpoint{ var ( ErrNoTrustedCht = errors.New("no trusted canonical hash trie") ErrNoTrustedBloomTrie = errors.New("no trusted bloom trie") - ErrNoHeader = errors.New("header not found") + errNoHeader = errors.New("header not found") chtPrefix = []byte("chtRoot-") // chtPrefix + chtNum (uint64 big endian) -> trie root hash ChtTablePrefix = "cht-" )