mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/database_util: refactor for txLookups
This commit is contained in:
parent
03cd248c7b
commit
251bcba7c9
3 changed files with 33 additions and 72 deletions
|
|
@ -1182,8 +1182,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
|
||||||
// When transactions get deleted from the database that means the
|
// When transactions get deleted from the database that means the
|
||||||
// receipts that were created in the fork must also be deleted
|
// receipts that were created in the fork must also be deleted
|
||||||
for _, tx := range diff {
|
for _, tx := range diff {
|
||||||
DeleteReceipt(bc.chainDb, tx.Hash())
|
DeleteTxLookupEntry(bc.chainDb, tx.Hash())
|
||||||
DeleteTransaction(bc.chainDb, tx.Hash())
|
|
||||||
}
|
}
|
||||||
// Must be posted in a goroutine because of the transaction pool trying
|
// Must be posted in a goroutine because of the transaction pool trying
|
||||||
// to acquire the chain manager lock
|
// to acquire the chain manager lock
|
||||||
|
|
@ -1402,3 +1401,10 @@ func (bc *BlockChain) Config() *params.ChainConfig { return bc.config }
|
||||||
|
|
||||||
// Engine retrieves the blockchain's consensus engine.
|
// Engine retrieves the blockchain's consensus engine.
|
||||||
func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
|
func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
|
||||||
|
|
||||||
|
// BigIntSlice attaches the methods of sort.Interface to []*big.Int, sorting in increasing order.
|
||||||
|
type BigIntSlice []*big.Int
|
||||||
|
|
||||||
|
func (s BigIntSlice) Len() int { return len(s) }
|
||||||
|
func (s BigIntSlice) Less(i, j int) bool { return s[i].Cmp(s[j]) < 0 }
|
||||||
|
func (s BigIntSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
|
||||||
|
|
@ -98,16 +98,8 @@ const missingNumber = uint64(0xffffffffffffffff)
|
||||||
func GetBlockNumber(db ethdb.Database, hash common.Hash) uint64 {
|
func GetBlockNumber(db ethdb.Database, hash common.Hash) uint64 {
|
||||||
data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...))
|
data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...))
|
||||||
if len(data) != 8 {
|
if len(data) != 8 {
|
||||||
data, _ := db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldHeaderSuffix...))
|
|
||||||
if len(data) == 0 {
|
|
||||||
return missingNumber
|
return missingNumber
|
||||||
}
|
}
|
||||||
header := new(types.Header)
|
|
||||||
if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
|
|
||||||
log.Crit("Failed to decode block header", "err", err)
|
|
||||||
}
|
|
||||||
return header.Number.Uint64()
|
|
||||||
}
|
|
||||||
return binary.BigEndian.Uint64(data)
|
return binary.BigEndian.Uint64(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,7 +245,7 @@ func GetTxLookupEntry(db ethdb.Database, hash common.Hash) (common.Hash, uint64,
|
||||||
// Parse and return the contents of the lookup entry
|
// Parse and return the contents of the lookup entry
|
||||||
var entry txLookupEntry
|
var entry txLookupEntry
|
||||||
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
if err := rlp.DecodeBytes(data, &entry); err != nil {
|
||||||
glog.V(logger.Error).Infof("Invalid lookup entry RLP", "hash", hash, "err", err)
|
log.Error("Invalid lookup entry RLP", "hash", hash, "err", err)
|
||||||
return common.Hash{}, 0, 0
|
return common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
return entry.BlockHash, entry.BlockIndex, entry.Index
|
return entry.BlockHash, entry.BlockIndex, entry.Index
|
||||||
|
|
@ -268,7 +260,7 @@ func GetTransaction(db ethdb.Database, hash common.Hash) (*types.Transaction, co
|
||||||
if blockHash != (common.Hash{}) {
|
if blockHash != (common.Hash{}) {
|
||||||
body := GetBody(db, blockHash, blockNumber)
|
body := GetBody(db, blockHash, blockNumber)
|
||||||
if body == nil || len(body.Transactions) <= int(txIndex) {
|
if body == nil || len(body.Transactions) <= int(txIndex) {
|
||||||
glog.V(logger.Error).Infof("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex)
|
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
|
return body.Transactions[txIndex], blockHash, blockNumber, txIndex
|
||||||
|
|
@ -295,9 +287,22 @@ func GetTransaction(db ethdb.Database, hash common.Hash) (*types.Transaction, co
|
||||||
return &tx, entry.BlockHash, entry.BlockIndex, entry.Index
|
return &tx, entry.BlockHash, entry.BlockIndex, entry.Index
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReceipt returns a receipt by hash
|
// GetReceipt retrieves a specific transaction receipt from the database, along with
|
||||||
func GetReceipt(db ethdb.Database, hash common.Hash) *types.Receipt {
|
// its added positional metadata.
|
||||||
data, _ := db.Get(append(receiptsPrefix, hash[:]...))
|
func GetReceipt(db ethdb.Database, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) {
|
||||||
|
// Retrieve the lookup metadata and resolve the receipt from the receipts
|
||||||
|
blockHash, blockNumber, receiptIndex := GetTxLookupEntry(db, hash)
|
||||||
|
|
||||||
|
if blockHash != (common.Hash{}) {
|
||||||
|
receipts := GetBlockReceipts(db, blockHash, blockNumber)
|
||||||
|
if len(receipts) <= int(receiptIndex) {
|
||||||
|
log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex)
|
||||||
|
return nil, common.Hash{}, 0, 0
|
||||||
|
}
|
||||||
|
return receipts[receiptIndex], blockHash, blockNumber, receiptIndex
|
||||||
|
}
|
||||||
|
// Old receipt representation, load the receipt and set an unknown metadata
|
||||||
|
data, _ := db.Get(append(oldReceiptsPrefix, hash[:]...))
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
|
|
@ -434,20 +439,7 @@ func WriteTxLookupEntries(db ethdb.Database, block *types.Block) error {
|
||||||
|
|
||||||
// Iterate over each transaction and encode its metadata
|
// Iterate over each transaction and encode its metadata
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// Encode and queue up the transaction for storage
|
entry := txLookupEntry{
|
||||||
data, err := rlp.EncodeToBytes(tx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = batch.Put(tx.Hash().Bytes(), data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Encode and queue up the transaction metadata for storage
|
|
||||||
meta := struct {
|
|
||||||
BlockHash common.Hash
|
|
||||||
BlockIndex uint64
|
|
||||||
Index uint64
|
|
||||||
}{
|
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
BlockIndex: block.NumberU64(),
|
BlockIndex: block.NumberU64(),
|
||||||
Index: uint64(i),
|
Index: uint64(i),
|
||||||
|
|
@ -462,39 +454,7 @@ func WriteTxLookupEntries(db ethdb.Database, block *types.Block) error {
|
||||||
}
|
}
|
||||||
// Write the scheduled data into the database
|
// Write the scheduled data into the database
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
log.Crit("Failed to store transactions", "err", err)
|
log.Crit("Failed to store lookup entries:", err)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteReceipt stores a single transaction receipt into the database.
|
|
||||||
func WriteReceipt(db ethdb.Database, receipt *types.Receipt) error {
|
|
||||||
storageReceipt := (*types.ReceiptForStorage)(receipt)
|
|
||||||
data, err := rlp.EncodeToBytes(storageReceipt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return db.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteReceipts stores a batch of transaction receipts into the database.
|
|
||||||
func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
|
|
||||||
batch := db.NewBatch()
|
|
||||||
|
|
||||||
// Iterate over all the receipts and queue them for database injection
|
|
||||||
for _, receipt := range receipts {
|
|
||||||
storageReceipt := (*types.ReceiptForStorage)(receipt)
|
|
||||||
data, err := rlp.EncodeToBytes(storageReceipt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := batch.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Write the scheduled data into the database
|
|
||||||
if err := batch.Write(); err != nil {
|
|
||||||
log.Crit("Failed to store receipts", "err", err)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -533,15 +493,9 @@ func DeleteBlockReceipts(db ethdb.Database, hash common.Hash, number uint64) {
|
||||||
db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
|
db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTransaction removes all transaction data associated with a hash.
|
// DeleteTxLookupEntry removes all transaction data associated with a hash.
|
||||||
func DeleteTransaction(db ethdb.Database, hash common.Hash) {
|
func DeleteTxLookupEntry(db ethdb.Database, hash common.Hash) {
|
||||||
db.Delete(hash.Bytes())
|
db.Delete(append(lookupPrefix, hash.Bytes()...))
|
||||||
db.Delete(append(hash.Bytes(), txMetaSuffix...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteReceipt removes all receipt data associated with a transaction hash.
|
|
||||||
func DeleteReceipt(db ethdb.Database, hash common.Hash) {
|
|
||||||
db.Delete(append(receiptsPrefix, hash.Bytes()...))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a formatted MIP mapped key by adding prefix, canonical number and level
|
// returns a formatted MIP mapped key by adding prefix, canonical number and level
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ubiq/go-ubiq/common"
|
"github.com/ubiq/go-ubiq/common"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue