From 49c1f9cfdd4f8788e92a702f0c6a9704d4af61c2 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Wed, 23 Jan 2019 14:46:40 +0800 Subject: [PATCH] core, les: remove unnecessary fields in txlookup --- core/blockchain.go | 1 + core/rawdb/accessors_indexes.go | 57 ++++++++++++++++++---------- core/rawdb/accessors_indexes_test.go | 23 +++++++++++ core/rawdb/schema.go | 12 ++++-- core/types/log.go | 6 +-- core/types/receipt.go | 6 +-- les/handler.go | 4 +- les/handler_test.go | 4 +- les/protocol.go | 2 +- 9 files changed, 82 insertions(+), 33 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index df20998ba4..04fb01c7db 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -70,6 +70,7 @@ const ( // the following incompatible database changes were added. // * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted // * the `Bloom` field of receipt is deleted + // * the `BlockIndex` and `TxIndex` fields of txlookup are deleted BlockChainVersion uint64 = 4 ) diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index 4ff7e5bd35..bd80b4f6aa 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -25,27 +25,30 @@ import ( // ReadTxLookupEntry retrieves the positional metadata associated with a transaction // hash to allow retrieving the transaction or receipt by hash. -func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) { +func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) common.Hash { data, _ := db.Get(txLookupKey(hash)) if len(data) == 0 { - return common.Hash{}, 0, 0 + return common.Hash{} } var entry TxLookupEntry if err := rlp.DecodeBytes(data, &entry); err != nil { - log.Error("Invalid transaction lookup entry RLP", "hash", hash, "err", err) - return common.Hash{}, 0, 0 + var dec LegacyTxLookupEntry + if err = rlp.DecodeBytes(data, &dec); err != nil { + log.Error("Invalid transaction lookup entry RLP", "hash", hash, "err", err) + return common.Hash{} + } + entry.BlockHash = dec.BlockHash + } - return entry.BlockHash, entry.BlockIndex, entry.Index + return entry.BlockHash } // WriteTxLookupEntries stores a positional metadata for every transaction from // a block, enabling hash based transaction and receipt lookups. func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { - for i, tx := range block.Transactions() { + for _, tx := range block.Transactions() { entry := TxLookupEntry{ - BlockHash: block.Hash(), - BlockIndex: block.NumberU64(), - Index: uint64(i), + BlockHash: block.Hash(), } data, err := rlp.EncodeToBytes(entry) if err != nil { @@ -65,31 +68,47 @@ func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { // ReadTransaction retrieves a specific transaction from the database, along with // its added positional metadata. func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { - blockHash, blockNumber, txIndex := ReadTxLookupEntry(db, hash) + blockHash := ReadTxLookupEntry(db, hash) if blockHash == (common.Hash{}) { return nil, common.Hash{}, 0, 0 } - body := ReadBody(db, blockHash, blockNumber) - if body == nil || len(body.Transactions) <= int(txIndex) { - log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex) + blockNumber := ReadHeaderNumber(db, blockHash) + if blockNumber == nil { return nil, common.Hash{}, 0, 0 } - return body.Transactions[txIndex], blockHash, blockNumber, txIndex + body := ReadBody(db, blockHash, *blockNumber) + if body == nil { + log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash) + return nil, common.Hash{}, 0, 0 + } + for txIndex, tx := range body.Transactions { + if tx.Hash() == hash { + return tx, blockHash, *blockNumber, uint64(txIndex) + } + } + log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 } // ReadReceipt retrieves a specific transaction receipt from the database, along with // its added positional metadata. func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { - blockHash, blockNumber, receiptIndex := ReadTxLookupEntry(db, hash) + blockHash := ReadTxLookupEntry(db, hash) if blockHash == (common.Hash{}) { return nil, common.Hash{}, 0, 0 } - receipts := ReadReceipts(db, blockHash, blockNumber) - if len(receipts) <= int(receiptIndex) { - log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex) + blockNumber := ReadHeaderNumber(db, blockHash) + if blockNumber == nil { return nil, common.Hash{}, 0, 0 } - return receipts[receiptIndex], blockHash, blockNumber, receiptIndex + receipts := ReadReceipts(db, blockHash, *blockNumber) + for receiptIndex, receipt := range receipts { + if receipt.TxHash == hash { + return receipt, blockHash, *blockNumber, uint64(receiptIndex) + } + } + log.Error("Receipt not found", "number", blockNumber, "hash", blockHash, "txhash", hash) + return nil, common.Hash{}, 0, 0 } // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index d9c10e1490..bed03a5e6b 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" ) // Tests that positional lookup metadata can be stored and retrieved. @@ -65,4 +66,26 @@ func TestLookupStorage(t *testing.T) { t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) } } + // Insert legacy txlookup and verify the data retrieval + for index, tx := range block.Transactions() { + entry := LegacyTxLookupEntry{ + BlockHash: block.Hash(), + BlockIndex: block.NumberU64(), + Index: uint64(index), + } + data, _ := rlp.EncodeToBytes(entry) + db.Put(txLookupKey(tx.Hash()), data) + } + for i, tx := range txs { + if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { + t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) + } else { + if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { + t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) + } + if tx.Hash() != txn.Hash() { + t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) + } + } + } } diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index 8a9921ef40..b62efdd539 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -63,14 +63,20 @@ var ( preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) ) -// TxLookupEntry is a positional metadata to help looking up the data content of -// a transaction or receipt given only its hash. -type TxLookupEntry struct { +// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary +// fields. +type LegacyTxLookupEntry struct { BlockHash common.Hash BlockIndex uint64 Index uint64 } +// TxLookupEntry is a positional metadata to help looking up the data content of +// a transaction or receipt given only its hash. +type TxLookupEntry struct { + BlockHash common.Hash +} + // encodeBlockNumber encodes a block number as big endian uint64 func encodeBlockNumber(number uint64) []byte { enc := make([]byte, 8) diff --git a/core/types/log.go b/core/types/log.go index 755c11814f..a395d5a67e 100644 --- a/core/types/log.go +++ b/core/types/log.go @@ -71,8 +71,8 @@ type rlpLog struct { // rlpStorageLog is the storage encoding of a log. type rlpStorageLog rlpLog -// rlpSwollenStorageLog is the previous storage encoding of a log including some redundant fields. -type rlpSwollenStorageLog struct { +// LegacyRlpStorageLog is the previous storage encoding of a log including some redundant fields. +type LegacyRlpStorageLog struct { Address common.Address Topics []common.Hash Data []byte @@ -125,7 +125,7 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error { } } else { // Try to decode log with previous definition. - var dec rlpSwollenStorageLog + var dec LegacyRlpStorageLog err = s.Decode(&dec) if err == nil { *l = LogForStorage{ diff --git a/core/types/receipt.go b/core/types/receipt.go index 298a928697..0dfe35e0d8 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -82,8 +82,8 @@ type receiptStorageRLP struct { GasUsed uint64 } -// receiptSwollenStorageRLP is the previous storage encoding of a receipt including some unnecessary fields. -type receiptSwollenStorageRLP struct { +// LegacyReceiptStorageRLP is the previous storage encoding of a receipt including some unnecessary fields. +type LegacyReceiptStorageRLP struct { PostStateOrStatus []byte CumulativeGasUsed uint64 Bloom Bloom @@ -186,7 +186,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { var dec receiptStorageRLP if err := s.Decode(&dec); err != nil { - var sdec receiptSwollenStorageRLP + var sdec LegacyReceiptStorageRLP if err := s.Decode(&sdec); err != nil { return err } diff --git a/les/handler.go b/les/handler.go index 19ccbcd2b6..1564b55205 100644 --- a/les/handler.go +++ b/les/handler.go @@ -1166,9 +1166,9 @@ func (pm *ProtocolManager) txStatus(hashes []common.Hash) []txStatus { // If the transaction is unknown to the pool, try looking it up locally if stat == core.TxStatusUnknown { - if block, number, index := rawdb.ReadTxLookupEntry(pm.chainDb, hashes[i]); block != (common.Hash{}) { + if tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(pm.chainDb, hashes[i]); tx != nil { stats[i].Status = core.TxStatusIncluded - stats[i].Lookup = &rawdb.TxLookupEntry{BlockHash: block, BlockIndex: number, Index: index} + stats[i].Lookup = &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex} } } } diff --git a/les/handler_test.go b/les/handler_test.go index 43be7f41b1..c7c90dbab7 100644 --- a/les/handler_test.go +++ b/les/handler_test.go @@ -559,8 +559,8 @@ func TestTransactionStatusLes2(t *testing.T) { // check if their status is included now block1hash := rawdb.ReadCanonicalHash(db, 1) - test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) - test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) + test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) + test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) // create a reorg that rolls them back gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {}) diff --git a/les/protocol.go b/les/protocol.go index 0b24f5aedb..b75f92bf74 100644 --- a/les/protocol.go +++ b/les/protocol.go @@ -221,6 +221,6 @@ type proofsData [][]rlp.RawValue type txStatus struct { Status core.TxStatus - Lookup *rawdb.TxLookupEntry `rlp:"nil"` + Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"` Error string }