github.com/bcskill/bcschain/v3@v3.4.9-beta2/core/rawdb/accessors_indexes.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rawdb 18 19 import ( 20 "encoding/binary" 21 "github.com/bcskill/bcschain/v3/params" 22 "math/big" 23 24 "github.com/bcskill/bcschain/v3/common" 25 "github.com/bcskill/bcschain/v3/core/types" 26 "github.com/bcskill/bcschain/v3/log" 27 "github.com/bcskill/bcschain/v3/rlp" 28 ) 29 30 // ReadTxLookupEntry retrieves the positional metadata associated with a transaction 31 // hash to allow retrieving the transaction or receipt by hash. 32 func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) *uint64 { 33 var data []byte 34 Must("get tx lookup entry", func() (err error) { 35 data, err = db.Get(hashKey(lookupPrefix, hash)) 36 if err == common.ErrNotFound { 37 err = nil 38 } 39 return 40 }) 41 if len(data) == 0 { 42 return nil 43 } 44 // Database v6 lookup just stores the block number 45 if len(data) < common.HashLength { 46 number := new(big.Int).SetBytes(data).Uint64() 47 return &number 48 } 49 // Database v4-v5 tx lookup format just stores the hash 50 if len(data) == common.HashLength { 51 return ReadHeaderNumber(db, common.BytesToHash(data)) 52 } 53 // Finally try database v3 tx lookup format 54 var entry LegacyTxLookupEntry 55 if err := rlp.DecodeBytes(data, &entry); err != nil { 56 log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) 57 return nil 58 } 59 return &entry.BlockIndex 60 } 61 62 // WriteTxLookupEntries stores a positional metadata for every transaction from 63 // a block, enabling hash based transaction and receipt lookups. 64 func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { 65 for _, tx := range block.Transactions() { 66 data := block.Number().Bytes() 67 Must("put tx lookup entry", func() (err error) { 68 return db.Put(hashKey(lookupPrefix, tx.Hash()), data) 69 }) 70 } 71 } 72 73 // DeleteTxLookupEntry removes all transaction data associated with a hash. 74 func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { 75 Must("delete tx lookup entry", func() error { 76 return db.Delete(hashKey(lookupPrefix, hash)) 77 }) 78 } 79 80 // ReadTransaction retrieves a specific transaction from the database, along with 81 // its added positional metadata. 82 func ReadTransaction(db common.Database, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { 83 blockNumber := ReadTxLookupEntry(db.GlobalTable(), hash) 84 if blockNumber == nil { 85 return nil, common.Hash{}, 0, 0 86 } 87 blockHash := ReadCanonicalHash(db, *blockNumber) 88 if blockHash == (common.Hash{}) { 89 return nil, common.Hash{}, 0, 0 90 } 91 body := ReadBody(db.BodyTable(), blockHash, *blockNumber) 92 if body == nil { 93 log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash) 94 return nil, common.Hash{}, 0, 0 95 } 96 for txIndex, tx := range body.Transactions { 97 if tx.Hash() == hash { 98 return tx, blockHash, *blockNumber, uint64(txIndex) 99 } 100 } 101 log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash) 102 return nil, common.Hash{}, 0, 0 103 } 104 105 // ReadReceipt retrieves a specific transaction receipt from the database, along with 106 // its added positional metadata. 107 func ReadReceipt(db common.Database, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { 108 blockNumber := ReadTxLookupEntry(db.GlobalTable(), hash) 109 if blockNumber == nil { 110 return nil, common.Hash{}, 0, 0 111 } 112 blockHash := ReadCanonicalHash(db, *blockNumber) 113 if blockHash == (common.Hash{}) { 114 return nil, common.Hash{}, 0, 0 115 } 116 receipts := ReadReceipts(db, blockHash, *blockNumber, config) 117 for receiptIndex, receipt := range receipts { 118 if receipt.TxHash == hash { 119 return receipt, blockHash, *blockNumber, uint64(receiptIndex) 120 } 121 } 122 log.Error("Receipt not found", "number", blockNumber, "hash", blockHash, "txhash", hash) 123 return nil, common.Hash{}, 0, 0 124 } 125 126 // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given 127 // section and bit index from the. 128 func ReadBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) []byte { 129 var key [43]byte 130 key[0] = bloomBitsPrefix 131 binary.BigEndian.PutUint16(key[1:], uint16(bit)) 132 binary.BigEndian.PutUint64(key[3:], section) 133 copy(key[11:], head[:]) 134 var data []byte 135 Must("get bloom bits", func() (err error) { 136 data, err = db.Get(key[:]) 137 if err == common.ErrNotFound { 138 err = nil 139 } 140 return 141 }) 142 return data 143 } 144 145 // WriteBloomBits stores the compressed bloom bits vector belonging to the given 146 // section and bit index. 147 func WriteBloomBits(db DatabaseWriter, bit uint, section uint64, head common.Hash, bits []byte) { 148 var key [43]byte 149 key[0] = bloomBitsPrefix 150 binary.BigEndian.PutUint16(key[1:], uint16(bit)) 151 binary.BigEndian.PutUint64(key[3:], section) 152 copy(key[11:], head[:]) 153 154 Must("put bloom bits", func() error { 155 return db.Put(key[:], bits) 156 }) 157 }