core, les: remove unnecessary fields in txlookup

This commit is contained in:
rjl493456442 2019-01-23 14:46:40 +08:00
parent b41c584ab4
commit 49c1f9cfdd
9 changed files with 82 additions and 33 deletions

View file

@ -70,6 +70,7 @@ const (
// the following incompatible database changes were added. // the following incompatible database changes were added.
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted // * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
// * the `Bloom` field of receipt is deleted // * the `Bloom` field of receipt is deleted
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
BlockChainVersion uint64 = 4 BlockChainVersion uint64 = 4
) )

View file

@ -25,27 +25,30 @@ import (
// ReadTxLookupEntry retrieves the positional metadata associated with a transaction // ReadTxLookupEntry retrieves the positional metadata associated with a transaction
// hash to allow retrieving the transaction or receipt by hash. // 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)) data, _ := db.Get(txLookupKey(hash))
if len(data) == 0 { if len(data) == 0 {
return common.Hash{}, 0, 0 return common.Hash{}
} }
var entry TxLookupEntry var entry TxLookupEntry
if err := rlp.DecodeBytes(data, &entry); err != nil { if err := rlp.DecodeBytes(data, &entry); err != nil {
var dec LegacyTxLookupEntry
if err = rlp.DecodeBytes(data, &dec); err != nil {
log.Error("Invalid transaction lookup entry RLP", "hash", hash, "err", err) log.Error("Invalid transaction lookup entry RLP", "hash", hash, "err", err)
return common.Hash{}, 0, 0 return common.Hash{}
} }
return entry.BlockHash, entry.BlockIndex, entry.Index entry.BlockHash = dec.BlockHash
}
return entry.BlockHash
} }
// WriteTxLookupEntries stores a positional metadata for every transaction from // WriteTxLookupEntries stores a positional metadata for every transaction from
// a block, enabling hash based transaction and receipt lookups. // a block, enabling hash based transaction and receipt lookups.
func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) {
for i, tx := range block.Transactions() { for _, tx := range block.Transactions() {
entry := TxLookupEntry{ entry := TxLookupEntry{
BlockHash: block.Hash(), BlockHash: block.Hash(),
BlockIndex: block.NumberU64(),
Index: uint64(i),
} }
data, err := rlp.EncodeToBytes(entry) data, err := rlp.EncodeToBytes(entry)
if err != nil { if err != nil {
@ -65,31 +68,47 @@ func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) {
// ReadTransaction retrieves a specific transaction from the database, along with // ReadTransaction retrieves a specific transaction from the database, along with
// its added positional metadata. // its added positional metadata.
func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { 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{}) { if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0 return nil, common.Hash{}, 0, 0
} }
body := ReadBody(db, blockHash, blockNumber) blockNumber := ReadHeaderNumber(db, blockHash)
if body == nil || len(body.Transactions) <= int(txIndex) { if blockNumber == nil {
log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex)
return nil, common.Hash{}, 0, 0 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 // ReadReceipt retrieves a specific transaction receipt from the database, along with
// its added positional metadata. // its added positional metadata.
func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { 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{}) { if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0 return nil, common.Hash{}, 0, 0
} }
receipts := ReadReceipts(db, blockHash, blockNumber) blockNumber := ReadHeaderNumber(db, blockHash)
if len(receipts) <= int(receiptIndex) { if blockNumber == nil {
log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex)
return nil, common.Hash{}, 0, 0 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 // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given

View file

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
) )
// Tests that positional lookup metadata can be stored and retrieved. // 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) 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)
}
}
}
} }

View file

@ -63,12 +63,18 @@ var (
preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil)
) )
// 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 // TxLookupEntry is a positional metadata to help looking up the data content of
// a transaction or receipt given only its hash. // a transaction or receipt given only its hash.
type TxLookupEntry struct { type TxLookupEntry struct {
BlockHash common.Hash BlockHash common.Hash
BlockIndex uint64
Index uint64
} }
// encodeBlockNumber encodes a block number as big endian uint64 // encodeBlockNumber encodes a block number as big endian uint64

View file

@ -71,8 +71,8 @@ type rlpLog struct {
// rlpStorageLog is the storage encoding of a log. // rlpStorageLog is the storage encoding of a log.
type rlpStorageLog rlpLog type rlpStorageLog rlpLog
// rlpSwollenStorageLog is the previous storage encoding of a log including some redundant fields. // LegacyRlpStorageLog is the previous storage encoding of a log including some redundant fields.
type rlpSwollenStorageLog struct { type LegacyRlpStorageLog struct {
Address common.Address Address common.Address
Topics []common.Hash Topics []common.Hash
Data []byte Data []byte
@ -125,7 +125,7 @@ func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
} }
} else { } else {
// Try to decode log with previous definition. // Try to decode log with previous definition.
var dec rlpSwollenStorageLog var dec LegacyRlpStorageLog
err = s.Decode(&dec) err = s.Decode(&dec)
if err == nil { if err == nil {
*l = LogForStorage{ *l = LogForStorage{

View file

@ -82,8 +82,8 @@ type receiptStorageRLP struct {
GasUsed uint64 GasUsed uint64
} }
// receiptSwollenStorageRLP is the previous storage encoding of a receipt including some unnecessary fields. // LegacyReceiptStorageRLP is the previous storage encoding of a receipt including some unnecessary fields.
type receiptSwollenStorageRLP struct { type LegacyReceiptStorageRLP struct {
PostStateOrStatus []byte PostStateOrStatus []byte
CumulativeGasUsed uint64 CumulativeGasUsed uint64
Bloom Bloom Bloom Bloom
@ -186,7 +186,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
var dec receiptStorageRLP var dec receiptStorageRLP
if err := s.Decode(&dec); err != nil { if err := s.Decode(&dec); err != nil {
var sdec receiptSwollenStorageRLP var sdec LegacyReceiptStorageRLP
if err := s.Decode(&sdec); err != nil { if err := s.Decode(&sdec); err != nil {
return err return err
} }

View file

@ -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 the transaction is unknown to the pool, try looking it up locally
if stat == core.TxStatusUnknown { 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].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}
} }
} }
} }

View file

@ -559,8 +559,8 @@ func TestTransactionStatusLes2(t *testing.T) {
// check if their status is included now // check if their status is included now
block1hash := rawdb.ReadCanonicalHash(db, 1) block1hash := rawdb.ReadCanonicalHash(db, 1)
test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) 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.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}})
// create a reorg that rolls them back // 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) {}) gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {})

View file

@ -221,6 +221,6 @@ type proofsData [][]rlp.RawValue
type txStatus struct { type txStatus struct {
Status core.TxStatus Status core.TxStatus
Lookup *rawdb.TxLookupEntry `rlp:"nil"` Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"`
Error string Error string
} }