github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/core/database_util.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  	"math/big"
    26  	"github.com/SmartMeshFoundation/Spectrum/common"
    27  	"github.com/SmartMeshFoundation/Spectrum/core/types"
    28  	"github.com/SmartMeshFoundation/Spectrum/ethdb"
    29  	"github.com/SmartMeshFoundation/Spectrum/log"
    30  	"github.com/SmartMeshFoundation/Spectrum/metrics"
    31  	"github.com/SmartMeshFoundation/Spectrum/params"
    32  	"github.com/SmartMeshFoundation/Spectrum/rlp"
    33  )
    34  
    35  // DatabaseReader wraps the Get method of a backing data store.
    36  type DatabaseReader interface {
    37  	Get(key []byte) (value []byte, err error)
    38  }
    39  
    40  // DatabaseDeleter wraps the Delete method of a backing data store.
    41  type DatabaseDeleter interface {
    42  	Delete(key []byte) error
    43  }
    44  
    45  var (
    46  	headHeaderKey = []byte("LastHeader")
    47  	headBlockKey  = []byte("LastBlock")
    48  	headFastKey   = []byte("LastFast")
    49  
    50  	// Data item prefixes (use single byte to avoid mixing data types, avoid `i`).
    51  	headerPrefix        = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
    52  	tdSuffix            = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td
    53  	numSuffix           = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash
    54  	blockHashPrefix     = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian)
    55  	bodyPrefix          = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body
    56  	blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
    57  	lookupPrefix        = []byte("l") // lookupPrefix + hash -> transaction/receipt lookup metadata
    58  	bloomBitsPrefix     = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
    59  
    60  	preimagePrefix = "secure-key-"              // preimagePrefix + hash -> preimage
    61  	configPrefix   = []byte("ethereum-config-") // config prefix for the db
    62  
    63  	// Chain index prefixes (use `i` + single byte to avoid mixing data types).
    64  	BloomBitsIndexPrefix = []byte("iB") // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress
    65  
    66  	// used by old db, now only used for conversion
    67  	oldReceiptsPrefix = []byte("receipts-")
    68  	oldTxMetaSuffix   = []byte{0x01}
    69  
    70  	ErrChainConfigNotFound = errors.New("ChainConfig not found") // general config not found error
    71  
    72  	preimageCounter    = metrics.NewCounter("db/preimage/total")
    73  	preimageHitCounter = metrics.NewCounter("db/preimage/hits")
    74  )
    75  
    76  // TxLookupEntry is a positional metadata to help looking up the data content of
    77  // a transaction or receipt given only its hash.
    78  type TxLookupEntry struct {
    79  	BlockHash  common.Hash
    80  	BlockIndex uint64
    81  	Index      uint64
    82  }
    83  
    84  // encodeBlockNumber encodes a block number as big endian uint64
    85  func encodeBlockNumber(number uint64) []byte {
    86  	enc := make([]byte, 8)
    87  	binary.BigEndian.PutUint64(enc, number)
    88  	return enc
    89  }
    90  
    91  // GetCanonicalHash retrieves a hash assigned to a canonical block number.
    92  func GetCanonicalHash(db DatabaseReader, number uint64) common.Hash {
    93  	data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...))
    94  	if len(data) == 0 {
    95  		return common.Hash{}
    96  	}
    97  	return common.BytesToHash(data)
    98  }
    99  
   100  // missingNumber is returned by GetBlockNumber if no header with the
   101  // given block hash has been stored in the database
   102  const missingNumber = uint64(0xffffffffffffffff)
   103  
   104  // GetBlockNumber returns the block number assigned to a block hash
   105  // if the corresponding header is present in the database
   106  func GetBlockNumber(db DatabaseReader, hash common.Hash) uint64 {
   107  	data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...))
   108  	if len(data) != 8 {
   109  		return missingNumber
   110  	}
   111  	return binary.BigEndian.Uint64(data)
   112  }
   113  
   114  // GetHeadHeaderHash retrieves the hash of the current canonical head block's
   115  // header. The difference between this and GetHeadBlockHash is that whereas the
   116  // last block hash is only updated upon a full block import, the last header
   117  // hash is updated already at header import, allowing head tracking for the
   118  // light synchronization mechanism.
   119  func GetHeadHeaderHash(db DatabaseReader) common.Hash {
   120  	data, _ := db.Get(headHeaderKey)
   121  	if len(data) == 0 {
   122  		return common.Hash{}
   123  	}
   124  	return common.BytesToHash(data)
   125  }
   126  
   127  // GetHeadBlockHash retrieves the hash of the current canonical head block.
   128  func GetHeadBlockHash(db DatabaseReader) common.Hash {
   129  	data, _ := db.Get(headBlockKey)
   130  	if len(data) == 0 {
   131  		return common.Hash{}
   132  	}
   133  	return common.BytesToHash(data)
   134  }
   135  
   136  // GetHeadFastBlockHash retrieves the hash of the current canonical head block during
   137  // fast synchronization. The difference between this and GetHeadBlockHash is that
   138  // whereas the last block hash is only updated upon a full block import, the last
   139  // fast hash is updated when importing pre-processed blocks.
   140  func GetHeadFastBlockHash(db DatabaseReader) common.Hash {
   141  	data, _ := db.Get(headFastKey)
   142  	if len(data) == 0 {
   143  		return common.Hash{}
   144  	}
   145  	return common.BytesToHash(data)
   146  }
   147  
   148  // GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil
   149  // if the header's not found.
   150  func GetHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   151  	data, _ := db.Get(headerKey(hash, number))
   152  	return data
   153  }
   154  
   155  // GetHeader retrieves the block header corresponding to the hash, nil if none
   156  // found.
   157  func GetHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header {
   158  	data := GetHeaderRLP(db, hash, number)
   159  	if len(data) == 0 {
   160  		return nil
   161  	}
   162  	header := new(types.Header)
   163  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   164  		log.Error("Invalid block header RLP", "hash", hash, "err", err)
   165  		return nil
   166  	}
   167  	return header
   168  }
   169  
   170  // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   171  func GetBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   172  	data, _ := db.Get(blockBodyKey(hash, number))
   173  	return data
   174  }
   175  
   176  func headerKey(hash common.Hash, number uint64) []byte {
   177  	return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   178  }
   179  
   180  func blockBodyKey(hash common.Hash, number uint64) []byte {
   181  	return append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   182  }
   183  
   184  // GetBody retrieves the block body (transactons, uncles) corresponding to the
   185  // hash, nil if none found.
   186  func GetBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
   187  	data := GetBodyRLP(db, hash, number)
   188  	if len(data) == 0 {
   189  		return nil
   190  	}
   191  	body := new(types.Body)
   192  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   193  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   194  		return nil
   195  	}
   196  	return body
   197  }
   198  
   199  // GetTd retrieves a block's total difficulty corresponding to the hash, nil if
   200  // none found.
   201  func GetTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
   202  	data, _ := db.Get(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash[:]...), tdSuffix...))
   203  	if len(data) == 0 {
   204  		return nil
   205  	}
   206  	td := new(big.Int)
   207  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   208  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   209  		return nil
   210  	}
   211  	return td
   212  }
   213  
   214  // GetBlock retrieves an entire block corresponding to the hash, assembling it
   215  // back from the stored header and body. If either the header or body could not
   216  // be retrieved nil is returned.
   217  //
   218  // Note, due to concurrent download of header and block body the header and thus
   219  // canonical hash can be stored in the database but the body data not (yet).
   220  func GetBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block {
   221  	// Retrieve the block header and body contents
   222  	header := GetHeader(db, hash, number)
   223  	if header == nil {
   224  		return nil
   225  	}
   226  	body := GetBody(db, hash, number)
   227  	if body == nil {
   228  		return nil
   229  	}
   230  	// Reassemble the block and return
   231  	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   232  }
   233  
   234  // GetBlockReceipts retrieves the receipts generated by the transactions included
   235  // in a block given by its hash.
   236  func GetBlockReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts {
   237  	data, _ := db.Get(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash[:]...))
   238  	if len(data) == 0 {
   239  		return nil
   240  	}
   241  	storageReceipts := []*types.ReceiptForStorage{}
   242  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   243  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   244  		return nil
   245  	}
   246  	receipts := make(types.Receipts, len(storageReceipts))
   247  	for i, receipt := range storageReceipts {
   248  		receipts[i] = (*types.Receipt)(receipt)
   249  	}
   250  	return receipts
   251  }
   252  
   253  // GetTxLookupEntry retrieves the positional metadata associated with a transaction
   254  // hash to allow retrieving the transaction or receipt by hash.
   255  func GetTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) {
   256  	// Load the positional metadata from disk and bail if it fails
   257  	data, _ := db.Get(append(lookupPrefix, hash.Bytes()...))
   258  	if len(data) == 0 {
   259  		return common.Hash{}, 0, 0
   260  	}
   261  	// Parse and return the contents of the lookup entry
   262  	var entry TxLookupEntry
   263  	if err := rlp.DecodeBytes(data, &entry); err != nil {
   264  		log.Error("Invalid lookup entry RLP", "hash", hash, "err", err)
   265  		return common.Hash{}, 0, 0
   266  	}
   267  	return entry.BlockHash, entry.BlockIndex, entry.Index
   268  }
   269  
   270  // GetTransaction retrieves a specific transaction from the database, along with
   271  // its added positional metadata.
   272  func GetTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
   273  	// Retrieve the lookup metadata and resolve the transaction from the body
   274  	blockHash, blockNumber, txIndex := GetTxLookupEntry(db, hash)
   275  
   276  	if blockHash != (common.Hash{}) {
   277  		body := GetBody(db, blockHash, blockNumber)
   278  		if body == nil || len(body.Transactions) <= int(txIndex) {
   279  			log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex)
   280  			return nil, common.Hash{}, 0, 0
   281  		}
   282  		return body.Transactions[txIndex], blockHash, blockNumber, txIndex
   283  	}
   284  	// Old transaction representation, load the transaction and it's metadata separately
   285  	data, _ := db.Get(hash.Bytes())
   286  	if len(data) == 0 {
   287  		return nil, common.Hash{}, 0, 0
   288  	}
   289  	var tx types.Transaction
   290  	if err := rlp.DecodeBytes(data, &tx); err != nil {
   291  		return nil, common.Hash{}, 0, 0
   292  	}
   293  	// Retrieve the blockchain positional metadata
   294  	data, _ = db.Get(append(hash.Bytes(), oldTxMetaSuffix...))
   295  	if len(data) == 0 {
   296  		return nil, common.Hash{}, 0, 0
   297  	}
   298  	var entry TxLookupEntry
   299  	if err := rlp.DecodeBytes(data, &entry); err != nil {
   300  		return nil, common.Hash{}, 0, 0
   301  	}
   302  	return &tx, entry.BlockHash, entry.BlockIndex, entry.Index
   303  }
   304  
   305  // GetReceipt retrieves a specific transaction receipt from the database, along with
   306  // its added positional metadata.
   307  func GetReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) {
   308  	// Retrieve the lookup metadata and resolve the receipt from the receipts
   309  	blockHash, blockNumber, receiptIndex := GetTxLookupEntry(db, hash)
   310  
   311  	if blockHash != (common.Hash{}) {
   312  		receipts := GetBlockReceipts(db, blockHash, blockNumber)
   313  		if len(receipts) <= int(receiptIndex) {
   314  			log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex)
   315  			return nil, common.Hash{}, 0, 0
   316  		}
   317  		return receipts[receiptIndex], blockHash, blockNumber, receiptIndex
   318  	}
   319  	// Old receipt representation, load the receipt and set an unknown metadata
   320  	data, _ := db.Get(append(oldReceiptsPrefix, hash[:]...))
   321  	if len(data) == 0 {
   322  		return nil, common.Hash{}, 0, 0
   323  	}
   324  	var receipt types.ReceiptForStorage
   325  	err := rlp.DecodeBytes(data, &receipt)
   326  	if err != nil {
   327  		log.Error("Invalid receipt RLP", "hash", hash, "err", err)
   328  	}
   329  	return (*types.Receipt)(&receipt), common.Hash{}, 0, 0
   330  }
   331  
   332  // GetBloomBits retrieves the compressed bloom bit vector belonging to the given
   333  // section and bit index from the.
   334  func GetBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) ([]byte, error) {
   335  	key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...)
   336  
   337  	binary.BigEndian.PutUint16(key[1:], uint16(bit))
   338  	binary.BigEndian.PutUint64(key[3:], section)
   339  
   340  	return db.Get(key)
   341  }
   342  
   343  // WriteCanonicalHash stores the canonical hash for the given block number.
   344  func WriteCanonicalHash(db ethdb.Putter, hash common.Hash, number uint64) error {
   345  	key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)
   346  	if err := db.Put(key, hash.Bytes()); err != nil {
   347  		log.Crit("Failed to store number to hash mapping", "err", err)
   348  	}
   349  	return nil
   350  }
   351  
   352  // WriteHeadHeaderHash stores the head header's hash.
   353  func WriteHeadHeaderHash(db ethdb.Putter, hash common.Hash) error {
   354  	if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
   355  		log.Crit("Failed to store last header's hash", "err", err)
   356  	}
   357  	return nil
   358  }
   359  
   360  // WriteHeadBlockHash stores the head block's hash.
   361  func WriteHeadBlockHash(db ethdb.Putter, hash common.Hash) error {
   362  	if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
   363  		log.Crit("Failed to store last block's hash", "err", err)
   364  	}
   365  	return nil
   366  }
   367  
   368  // WriteHeadFastBlockHash stores the fast head block's hash.
   369  func WriteHeadFastBlockHash(db ethdb.Putter, hash common.Hash) error {
   370  	if err := db.Put(headFastKey, hash.Bytes()); err != nil {
   371  		log.Crit("Failed to store last fast block's hash", "err", err)
   372  	}
   373  	return nil
   374  }
   375  
   376  // WriteHeader serializes a block header into the database.
   377  func WriteHeader(db ethdb.Putter, header *types.Header) error {
   378  	data, err := rlp.EncodeToBytes(header)
   379  	if err != nil {
   380  		return err
   381  	}
   382  	hash := header.Hash().Bytes()
   383  	num := header.Number.Uint64()
   384  	encNum := encodeBlockNumber(num)
   385  	key := append(blockHashPrefix, hash...)
   386  	if err := db.Put(key, encNum); err != nil {
   387  		log.Crit("Failed to store hash to number mapping", "err", err)
   388  	}
   389  	key = append(append(headerPrefix, encNum...), hash...)
   390  	if err := db.Put(key, data); err != nil {
   391  		log.Crit("Failed to store header", "err", err)
   392  	}
   393  	return nil
   394  }
   395  
   396  // WriteBody serializes the body of a block into the database.
   397  func WriteBody(db ethdb.Putter, hash common.Hash, number uint64, body *types.Body) error {
   398  	data, err := rlp.EncodeToBytes(body)
   399  	if err != nil {
   400  		return err
   401  	}
   402  	return WriteBodyRLP(db, hash, number, data)
   403  }
   404  
   405  // WriteBodyRLP writes a serialized body of a block into the database.
   406  func WriteBodyRLP(db ethdb.Putter, hash common.Hash, number uint64, rlp rlp.RawValue) error {
   407  	key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   408  	if err := db.Put(key, rlp); err != nil {
   409  		log.Crit("Failed to store block body", "err", err)
   410  	}
   411  	return nil
   412  }
   413  
   414  // WriteTd serializes the total difficulty of a block into the database.
   415  func WriteTd(db ethdb.Putter, hash common.Hash, number uint64, td *big.Int) error {
   416  	data, err := rlp.EncodeToBytes(td)
   417  	if err != nil {
   418  		return err
   419  	}
   420  	key := append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...)
   421  	if err := db.Put(key, data); err != nil {
   422  		log.Crit("Failed to store block total difficulty", "err", err)
   423  	}
   424  	return nil
   425  }
   426  
   427  // WriteBlock serializes a block into the database, header and body separately.
   428  func WriteBlock(db ethdb.Putter, block *types.Block) error {
   429  	// Store the body first to retain database consistency
   430  	if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil {
   431  		return err
   432  	}
   433  	// Store the header too, signaling full block ownership
   434  	if err := WriteHeader(db, block.Header()); err != nil {
   435  		return err
   436  	}
   437  	return nil
   438  }
   439  
   440  // WriteBlockReceipts stores all the transaction receipts belonging to a block
   441  // as a single receipt slice. This is used during chain reorganisations for
   442  // rescheduling dropped transactions.
   443  func WriteBlockReceipts(db ethdb.Putter, hash common.Hash, number uint64, receipts types.Receipts) error {
   444  	// Convert the receipts into their storage form and serialize them
   445  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   446  	for i, receipt := range receipts {
   447  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   448  	}
   449  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   450  	if err != nil {
   451  		return err
   452  	}
   453  	// Store the flattened receipt slice
   454  	key := append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   455  	if err := db.Put(key, bytes); err != nil {
   456  		log.Crit("Failed to store block receipts", "err", err)
   457  	}
   458  	return nil
   459  }
   460  
   461  // WriteTxLookupEntries stores a positional metadata for every transaction from
   462  // a block, enabling hash based transaction and receipt lookups.
   463  func WriteTxLookupEntries(db ethdb.Putter, block *types.Block) error {
   464  	// Iterate over each transaction and encode its metadata
   465  	for i, tx := range block.Transactions() {
   466  		entry := TxLookupEntry{
   467  			BlockHash:  block.Hash(),
   468  			BlockIndex: block.NumberU64(),
   469  			Index:      uint64(i),
   470  		}
   471  		data, err := rlp.EncodeToBytes(entry)
   472  		if err != nil {
   473  			return err
   474  		}
   475  		if err := db.Put(append(lookupPrefix, tx.Hash().Bytes()...), data); err != nil {
   476  			return err
   477  		}
   478  	}
   479  	return nil
   480  }
   481  
   482  // WriteBloomBits writes the compressed bloom bits vector belonging to the given
   483  // section and bit index.
   484  func WriteBloomBits(db ethdb.Putter, bit uint, section uint64, head common.Hash, bits []byte) {
   485  	key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...)
   486  
   487  	binary.BigEndian.PutUint16(key[1:], uint16(bit))
   488  	binary.BigEndian.PutUint64(key[3:], section)
   489  
   490  	if err := db.Put(key, bits); err != nil {
   491  		log.Crit("Failed to store bloom bits", "err", err)
   492  	}
   493  }
   494  
   495  // DeleteCanonicalHash removes the number to hash canonical mapping.
   496  func DeleteCanonicalHash(db DatabaseDeleter, number uint64) {
   497  	db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...))
   498  }
   499  
   500  // DeleteHeader removes all block header data associated with a hash.
   501  func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) {
   502  	db.Delete(append(blockHashPrefix, hash.Bytes()...))
   503  	db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   504  }
   505  
   506  // DeleteBody removes all block body data associated with a hash.
   507  func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) {
   508  	db.Delete(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   509  	//TODO add by liangc : 在这里插入一个块到本地,那么需要执行一次 chief 合约的 get 方法,来刷新签名列表
   510  }
   511  
   512  // DeleteTd removes all block total difficulty data associated with a hash.
   513  func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
   514  	db.Delete(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...))
   515  }
   516  
   517  // DeleteBlock removes all block data associated with a hash.
   518  func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) {
   519  	DeleteBlockReceipts(db, hash, number)
   520  	DeleteHeader(db, hash, number)
   521  	DeleteBody(db, hash, number)
   522  	DeleteTd(db, hash, number)
   523  }
   524  
   525  // DeleteBlockReceipts removes all receipt data associated with a block hash.
   526  func DeleteBlockReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
   527  	db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   528  }
   529  
   530  // DeleteTxLookupEntry removes all transaction data associated with a hash.
   531  func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) {
   532  	db.Delete(append(lookupPrefix, hash.Bytes()...))
   533  }
   534  
   535  // PreimageTable returns a Database instance with the key prefix for preimage entries.
   536  func PreimageTable(db ethdb.Database) ethdb.Database {
   537  	return ethdb.NewTable(db, preimagePrefix)
   538  }
   539  
   540  // WritePreimages writes the provided set of preimages to the database. `number` is the
   541  // current block number, and is used for debug messages only.
   542  func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error {
   543  	table := PreimageTable(db)
   544  	batch := table.NewBatch()
   545  	hitCount := 0
   546  	for hash, preimage := range preimages {
   547  		if _, err := table.Get(hash.Bytes()); err != nil {
   548  			batch.Put(hash.Bytes(), preimage)
   549  			hitCount++
   550  		}
   551  	}
   552  	preimageCounter.Inc(int64(len(preimages)))
   553  	preimageHitCounter.Inc(int64(hitCount))
   554  	if hitCount > 0 {
   555  		if err := batch.Write(); err != nil {
   556  			return fmt.Errorf("preimage write fail for block %d: %v", number, err)
   557  		}
   558  	}
   559  	return nil
   560  }
   561  
   562  // GetBlockChainVersion reads the version number from db.
   563  func GetBlockChainVersion(db DatabaseReader) int {
   564  	var vsn uint
   565  	enc, _ := db.Get([]byte("BlockchainVersion"))
   566  	rlp.DecodeBytes(enc, &vsn)
   567  	return int(vsn)
   568  }
   569  
   570  // WriteBlockChainVersion writes vsn as the version number to db.
   571  func WriteBlockChainVersion(db ethdb.Putter, vsn int) {
   572  	enc, _ := rlp.EncodeToBytes(uint(vsn))
   573  	db.Put([]byte("BlockchainVersion"), enc)
   574  }
   575  
   576  // WriteChainConfig writes the chain config settings to the database.
   577  func WriteChainConfig(db ethdb.Putter, hash common.Hash, cfg *params.ChainConfig) error {
   578  	// short circuit and ignore if nil config. GetChainConfig
   579  	// will return a default.
   580  	if cfg == nil {
   581  		return nil
   582  	}
   583  
   584  	jsonChainConfig, err := json.Marshal(cfg)
   585  	if err != nil {
   586  		return err
   587  	}
   588  
   589  	return db.Put(append(configPrefix, hash[:]...), jsonChainConfig)
   590  }
   591  
   592  // GetChainConfig will fetch the network settings based on the given hash.
   593  func GetChainConfig(db DatabaseReader, hash common.Hash) (*params.ChainConfig, error) {
   594  	jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...))
   595  	if len(jsonChainConfig) == 0 {
   596  		return nil, ErrChainConfigNotFound
   597  	}
   598  
   599  	var config params.ChainConfig
   600  	if err := json.Unmarshal(jsonChainConfig, &config); err != nil {
   601  		return nil, err
   602  	}
   603  
   604  	return &config, nil
   605  }
   606  
   607  // FindCommonAncestor returns the last common ancestor of two block headers
   608  func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
   609  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   610  		a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
   611  		if a == nil {
   612  			return nil
   613  		}
   614  	}
   615  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   616  		b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
   617  		if b == nil {
   618  			return nil
   619  		}
   620  	}
   621  	for a.Hash() != b.Hash() {
   622  		a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
   623  		if a == nil {
   624  			return nil
   625  		}
   626  		b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
   627  		if b == nil {
   628  			return nil
   629  		}
   630  	}
   631  	return a
   632  }