@ -17,6 +17,8 @@
package rawdb
package rawdb
import (
import (
"math/big"
"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"
@ -27,28 +29,34 @@ 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 ethdb . Reader , hash common . Hash ) common . Hash {
func ReadTxLookupEntry ( db ethdb . Reader , hash common . Hash ) * uint64 {
data , _ := db . Get ( txLookupKey ( hash ) )
data , _ := db . Get ( txLookupKey ( hash ) )
if len ( data ) == 0 {
if len ( data ) == 0 {
return common . Hash { }
return nil
}
// Database v6 tx lookup just stores the block number
if len ( data ) < common . HashLength {
number := new ( big . Int ) . SetBytes ( data ) . Uint64 ( )
return & number
}
}
// Database v4-v5 tx lookup format just stores the hash
if len ( data ) == common . HashLength {
if len ( data ) == common . HashLength {
return common . BytesToHash ( data )
return ReadHeaderNumber ( db , common . BytesToHash ( data ) )
}
}
// Probably it's legacy txlookup entry data, try to decode it.
// Finally try database v3 tx lookup format
var entry LegacyTxLookupEntry
var entry LegacyTxLookupEntry
if err := rlp . DecodeBytes ( data , & entry ) ; err != nil {
if err := rlp . DecodeBytes ( data , & entry ) ; err != nil {
log . Error ( "Invalid transaction lookup entry RLP" , "hash" , hash , "blob" , data , "err" , err )
log . Error ( "Invalid transaction lookup entry RLP" , "hash" , hash , "blob" , data , "err" , err )
return common . Hash { }
return nil
}
}
return entry . BlockHash
return & entry . BlockIndex
}
}
// 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 ethdb . Writer , block * types . Block ) {
func WriteTxLookupEntries ( db ethdb . Writer , block * types . Block ) {
for _ , tx := range block . Transactions ( ) {
for _ , tx := range block . Transactions ( ) {
if err := db . Put ( txLookupKey ( tx . Hash ( ) ) , block . Hash ( ) . Bytes ( ) ) ; err != nil {
if err := db . Put ( txLookupKey ( tx . Hash ( ) ) , block . Number ( ) . Bytes ( ) ) ; err != nil {
log . Crit ( "Failed to store transaction lookup entry" , "err" , err )
log . Crit ( "Failed to store transaction lookup entry" , "err" , err )
}
}
}
}
@ -62,12 +70,12 @@ func DeleteTxLookupEntry(db ethdb.Writer, 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 ethdb . Reader , hash common . Hash ) ( * types . Transaction , common . Hash , uint64 , uint64 ) {
func ReadTransaction ( db ethdb . Reader , hash common . Hash ) ( * types . Transaction , common . Hash , uint64 , uint64 ) {
blockHash := ReadTxLookupEntry ( db , hash )
blockNumber := ReadTxLookupEntry ( db , hash )
if blockHash == ( common . Hash { } ) {
if blockNumber == nil {
return nil , common . Hash { } , 0 , 0
return nil , common . Hash { } , 0 , 0
}
}
blockNumber := ReadHeaderNumber ( db , blockHash )
blockHash := ReadCanonicalHash ( db , * blockNumber )
if blockNumber == nil {
if blockHash == ( common . Hash { } ) {
return nil , common . Hash { } , 0 , 0
return nil , common . Hash { } , 0 , 0
}
}
body := ReadBody ( db , blockHash , * blockNumber )
body := ReadBody ( db , blockHash , * blockNumber )
@ -88,12 +96,12 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
// its added positional metadata.
// its added positional metadata.
func ReadReceipt ( db ethdb . Reader , hash common . Hash , config * params . ChainConfig ) ( * types . Receipt , common . Hash , uint64 , uint64 ) {
func ReadReceipt ( db ethdb . Reader , hash common . Hash , config * params . ChainConfig ) ( * types . Receipt , common . Hash , uint64 , uint64 ) {
// Retrieve the context of the receipt based on the transaction hash
// Retrieve the context of the receipt based on the transaction hash
blockHash := ReadTxLookupEntry ( db , hash )
blockNumber := ReadTxLookupEntry ( db , hash )
if blockHash == ( common . Hash { } ) {
if blockNumber == nil {
return nil , common . Hash { } , 0 , 0
return nil , common . Hash { } , 0 , 0
}
}
blockNumber := ReadHeaderNumber ( db , blockHash )
blockHash := ReadCanonicalHash ( db , * blockNumber )
if blockNumber == nil {
if blockHash == ( common . Hash { } ) {
return nil , common . Hash { } , 0 , 0
return nil , common . Hash { } , 0 , 0
}
}
// Read all the receipts from the block and return the one with the matching hash
// Read all the receipts from the block and return the one with the matching hash