github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/database_util.go (about)

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