| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | // Copyright 2018 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package rawdb | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-07-13 17:02:54 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							| 
									
										
										
										
											2019-04-15 12:36:27 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadTxLookupEntry retrieves the positional metadata associated with a transaction | 
					
						
							|  |  |  | // hash to allow retrieving the transaction or receipt by hash. | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 { | 
					
						
							| 
									
										
										
										
											2018-06-11 21:06:26 +08:00
										 |  |  | 	data, _ := db.Get(txLookupKey(hash)) | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	if len(data) == 0 { | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 		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 | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	// Database v4-v5 tx lookup format just stores the hash | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	if len(data) == common.HashLength { | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 		return ReadHeaderNumber(db, common.BytesToHash(data)) | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	// Finally try database v3 tx lookup format | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	var entry LegacyTxLookupEntry | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	if err := rlp.DecodeBytes(data, &entry); err != nil { | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 		log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	return &entry.BlockIndex | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 10:37:01 +02:00
										 |  |  | // writeTxLookupEntry stores a positional metadata for a transaction, | 
					
						
							|  |  |  | // enabling hash based transaction and receipt lookups. | 
					
						
							|  |  |  | func writeTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash, numberBytes []byte) { | 
					
						
							|  |  |  | 	if err := db.Put(txLookupKey(hash), numberBytes); err != nil { | 
					
						
							|  |  |  | 		log.Crit("Failed to store transaction lookup entry", "err", err) | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 10:37:01 +02:00
										 |  |  | // WriteTxLookupEntries is identical to WriteTxLookupEntry, but it works on | 
					
						
							|  |  |  | // a list of hashes | 
					
						
							|  |  |  | func WriteTxLookupEntries(db ethdb.KeyValueWriter, number uint64, hashes []common.Hash) { | 
					
						
							| 
									
										
										
										
											2020-05-11 17:58:43 +02:00
										 |  |  | 	numberBytes := new(big.Int).SetUint64(number).Bytes() | 
					
						
							|  |  |  | 	for _, hash := range hashes { | 
					
						
							| 
									
										
										
										
											2020-09-15 10:37:01 +02:00
										 |  |  | 		writeTxLookupEntry(db, hash, numberBytes) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // WriteTxLookupEntriesByBlock stores a positional metadata for every transaction from | 
					
						
							|  |  |  | // a block, enabling hash based transaction and receipt lookups. | 
					
						
							|  |  |  | func WriteTxLookupEntriesByBlock(db ethdb.KeyValueWriter, block *types.Block) { | 
					
						
							|  |  |  | 	numberBytes := block.Number().Bytes() | 
					
						
							|  |  |  | 	for _, tx := range block.Transactions() { | 
					
						
							|  |  |  | 		writeTxLookupEntry(db, tx.Hash(), numberBytes) | 
					
						
							| 
									
										
										
										
											2020-05-11 17:58:43 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | // DeleteTxLookupEntry removes all transaction data associated with a hash. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | func DeleteTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash) { | 
					
						
							| 
									
										
										
										
											2020-05-11 17:58:43 +02:00
										 |  |  | 	if err := db.Delete(txLookupKey(hash)); err != nil { | 
					
						
							|  |  |  | 		log.Crit("Failed to delete transaction lookup entry", "err", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DeleteTxLookupEntries removes all transaction lookups for a given block. | 
					
						
							| 
									
										
										
										
											2020-09-15 10:37:01 +02:00
										 |  |  | func DeleteTxLookupEntries(db ethdb.KeyValueWriter, hashes []common.Hash) { | 
					
						
							| 
									
										
										
										
											2020-05-11 17:58:43 +02:00
										 |  |  | 	for _, hash := range hashes { | 
					
						
							| 
									
										
										
										
											2020-09-15 10:37:01 +02:00
										 |  |  | 		DeleteTxLookupEntry(db, hash) | 
					
						
							| 
									
										
										
										
											2020-05-11 17:58:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadTransaction retrieves a specific transaction from the database, along with | 
					
						
							|  |  |  | // its added positional metadata. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	blockNumber := ReadTxLookupEntry(db, hash) | 
					
						
							|  |  |  | 	if blockNumber == nil { | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		return nil, common.Hash{}, 0, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	blockHash := ReadCanonicalHash(db, *blockNumber) | 
					
						
							|  |  |  | 	if blockHash == (common.Hash{}) { | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 		return nil, common.Hash{}, 0, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	body := ReadBody(db, blockHash, *blockNumber) | 
					
						
							|  |  |  | 	if body == nil { | 
					
						
							| 
									
										
										
										
											2021-08-04 01:10:37 -07:00
										 |  |  | 		log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash) | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		return nil, common.Hash{}, 0, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	for txIndex, tx := range body.Transactions { | 
					
						
							|  |  |  | 		if tx.Hash() == hash { | 
					
						
							|  |  |  | 			return tx, blockHash, *blockNumber, uint64(txIndex) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-04 01:10:37 -07:00
										 |  |  | 	log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	return nil, common.Hash{}, 0, 0 | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadReceipt retrieves a specific transaction receipt from the database, along with | 
					
						
							|  |  |  | // its added positional metadata. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { | 
					
						
							| 
									
										
										
										
											2019-04-15 12:36:27 +03:00
										 |  |  | 	// Retrieve the context of the receipt based on the transaction hash | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	blockNumber := ReadTxLookupEntry(db, hash) | 
					
						
							|  |  |  | 	if blockNumber == nil { | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		return nil, common.Hash{}, 0, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:24:56 -07:00
										 |  |  | 	blockHash := ReadCanonicalHash(db, *blockNumber) | 
					
						
							|  |  |  | 	if blockHash == (common.Hash{}) { | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		return nil, common.Hash{}, 0, 0 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-15 12:36:27 +03:00
										 |  |  | 	// Read all the receipts from the block and return the one with the matching hash | 
					
						
							|  |  |  | 	receipts := ReadReceipts(db, blockHash, *blockNumber, config) | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	for receiptIndex, receipt := range receipts { | 
					
						
							|  |  |  | 		if receipt.TxHash == hash { | 
					
						
							|  |  |  | 			return receipt, blockHash, *blockNumber, uint64(receiptIndex) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-04 01:10:37 -07:00
										 |  |  | 	log.Error("Receipt not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) | 
					
						
							| 
									
										
										
										
											2019-02-21 21:14:35 +08:00
										 |  |  | 	return nil, common.Hash{}, 0, 0 | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given | 
					
						
							|  |  |  | // section and bit index from the. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | func ReadBloomBits(db ethdb.KeyValueReader, bit uint, section uint64, head common.Hash) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2018-06-11 21:06:26 +08:00
										 |  |  | 	return db.Get(bloomBitsKey(bit, section, head)) | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // WriteBloomBits stores the compressed bloom bits vector belonging to the given | 
					
						
							|  |  |  | // section and bit index. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | func WriteBloomBits(db ethdb.KeyValueWriter, bit uint, section uint64, head common.Hash, bits []byte) { | 
					
						
							| 
									
										
										
										
											2018-06-11 21:06:26 +08:00
										 |  |  | 	if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		log.Crit("Failed to store bloom bits", "err", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-07-13 17:02:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // DeleteBloombits removes all compressed bloom bits vector belonging to the | 
					
						
							|  |  |  | // given section range and bit index. | 
					
						
							|  |  |  | func DeleteBloombits(db ethdb.Database, bit uint, from uint64, to uint64) { | 
					
						
							|  |  |  | 	start, end := bloomBitsKey(bit, from, common.Hash{}), bloomBitsKey(bit, to, common.Hash{}) | 
					
						
							|  |  |  | 	it := db.NewIterator(nil, start) | 
					
						
							|  |  |  | 	defer it.Release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for it.Next() { | 
					
						
							|  |  |  | 		if bytes.Compare(it.Key(), end) >= 0 { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(it.Key()) != len(bloomBitsPrefix)+2+8+32 { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		db.Delete(it.Key()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if it.Error() != nil { | 
					
						
							|  |  |  | 		log.Crit("Failed to delete bloom bits", "err", it.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |