github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/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  	"sync"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/ethdb"
    31  	"github.com/ethereum/go-ethereum/logger"
    32  	"github.com/ethereum/go-ethereum/logger/glog"
    33  	"github.com/ethereum/go-ethereum/metrics"
    34  	"github.com/ethereum/go-ethereum/params"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  )
    37  
    38  var (
    39  	headHeaderKey = []byte("LastHeader")
    40  	headBlockKey  = []byte("LastBlock")
    41  	headFastKey   = []byte("LastFast")
    42  
    43  	headerPrefix        = []byte("h")   // headerPrefix + num (uint64 big endian) + hash -> header
    44  	tdSuffix            = []byte("t")   // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td
    45  	numSuffix           = []byte("n")   // headerPrefix + num (uint64 big endian) + numSuffix -> hash
    46  	blockHashPrefix     = []byte("H")   // blockHashPrefix + hash -> num (uint64 big endian)
    47  	bodyPrefix          = []byte("b")   // bodyPrefix + num (uint64 big endian) + hash -> block body
    48  	blockReceiptsPrefix = []byte("r")   // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
    49  	preimagePrefix      = "secure-key-" // preimagePrefix + hash -> preimage
    50  
    51  	txMetaSuffix   = []byte{0x01}
    52  	receiptsPrefix = []byte("receipts-")
    53  
    54  	mipmapPre    = []byte("mipmap-log-bloom-")
    55  	MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
    56  
    57  	configPrefix = []byte("ethereum-config-") // config prefix for the db
    58  
    59  	// used by old (non-sequential keys) db, now only used for conversion
    60  	oldBlockPrefix         = []byte("block-")
    61  	oldHeaderSuffix        = []byte("-header")
    62  	oldTdSuffix            = []byte("-td") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td
    63  	oldBodySuffix          = []byte("-body")
    64  	oldBlockNumPrefix      = []byte("block-num-")
    65  	oldBlockReceiptsPrefix = []byte("receipts-block-")
    66  	oldBlockHashPrefix     = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
    67  
    68  	ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
    69  
    70  	mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
    71  
    72  	preimageCounter    = metrics.NewCounter("db/preimage/total")
    73  	preimageHitCounter = metrics.NewCounter("db/preimage/hits")
    74  )
    75  
    76  // encodeBlockNumber encodes a block number as big endian uint64
    77  func encodeBlockNumber(number uint64) []byte {
    78  	enc := make([]byte, 8)
    79  	binary.BigEndian.PutUint64(enc, number)
    80  	return enc
    81  }
    82  
    83  // GetCanonicalHash retrieves a hash assigned to a canonical block number.
    84  func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
    85  	data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...))
    86  	if len(data) == 0 {
    87  		data, _ = db.Get(append(oldBlockNumPrefix, big.NewInt(int64(number)).Bytes()...))
    88  		if len(data) == 0 {
    89  			return common.Hash{}
    90  		}
    91  	}
    92  	return common.BytesToHash(data)
    93  }
    94  
    95  // missingNumber is returned by GetBlockNumber if no header with the
    96  // given block hash has been stored in the database
    97  const missingNumber = uint64(0xffffffffffffffff)
    98  
    99  // GetBlockNumber returns the block number assigned to a block hash
   100  // if the corresponding header is present in the database
   101  func GetBlockNumber(db ethdb.Database, hash common.Hash) uint64 {
   102  	data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...))
   103  	if len(data) != 8 {
   104  		data, _ := db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldHeaderSuffix...))
   105  		if len(data) == 0 {
   106  			return missingNumber
   107  		}
   108  		header := new(types.Header)
   109  		if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   110  			glog.Fatalf("failed to decode block header: %v", err)
   111  		}
   112  		return header.Number.Uint64()
   113  	}
   114  	return binary.BigEndian.Uint64(data)
   115  }
   116  
   117  // GetHeadHeaderHash retrieves the hash of the current canonical head block's
   118  // header. The difference between this and GetHeadBlockHash is that whereas the
   119  // last block hash is only updated upon a full block import, the last header
   120  // hash is updated already at header import, allowing head tracking for the
   121  // light synchronization mechanism.
   122  func GetHeadHeaderHash(db ethdb.Database) common.Hash {
   123  	data, _ := db.Get(headHeaderKey)
   124  	if len(data) == 0 {
   125  		return common.Hash{}
   126  	}
   127  	return common.BytesToHash(data)
   128  }
   129  
   130  // GetHeadBlockHash retrieves the hash of the current canonical head block.
   131  func GetHeadBlockHash(db ethdb.Database) common.Hash {
   132  	data, _ := db.Get(headBlockKey)
   133  	if len(data) == 0 {
   134  		return common.Hash{}
   135  	}
   136  	return common.BytesToHash(data)
   137  }
   138  
   139  // GetHeadFastBlockHash retrieves the hash of the current canonical head block during
   140  // fast synchronization. The difference between this and GetHeadBlockHash is that
   141  // whereas the last block hash is only updated upon a full block import, the last
   142  // fast hash is updated when importing pre-processed blocks.
   143  func GetHeadFastBlockHash(db ethdb.Database) common.Hash {
   144  	data, _ := db.Get(headFastKey)
   145  	if len(data) == 0 {
   146  		return common.Hash{}
   147  	}
   148  	return common.BytesToHash(data)
   149  }
   150  
   151  // GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil
   152  // if the header's not found.
   153  func GetHeaderRLP(db ethdb.Database, hash common.Hash, number uint64) rlp.RawValue {
   154  	data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   155  	if len(data) == 0 {
   156  		data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldHeaderSuffix...))
   157  	}
   158  	return data
   159  }
   160  
   161  // GetHeader retrieves the block header corresponding to the hash, nil if none
   162  // found.
   163  func GetHeader(db ethdb.Database, hash common.Hash, number uint64) *types.Header {
   164  	data := GetHeaderRLP(db, hash, number)
   165  	if len(data) == 0 {
   166  		return nil
   167  	}
   168  	header := new(types.Header)
   169  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   170  		glog.V(logger.Error).Infof("invalid block header RLP for hash %x: %v", hash, err)
   171  		return nil
   172  	}
   173  	return header
   174  }
   175  
   176  // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   177  func GetBodyRLP(db ethdb.Database, hash common.Hash, number uint64) rlp.RawValue {
   178  	data, _ := db.Get(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   179  	if len(data) == 0 {
   180  		data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldBodySuffix...))
   181  	}
   182  	return data
   183  }
   184  
   185  // GetBody retrieves the block body (transactons, uncles) corresponding to the
   186  // hash, nil if none found.
   187  func GetBody(db ethdb.Database, hash common.Hash, number uint64) *types.Body {
   188  	data := GetBodyRLP(db, hash, number)
   189  	if len(data) == 0 {
   190  		return nil
   191  	}
   192  	body := new(types.Body)
   193  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   194  		glog.V(logger.Error).Infof("invalid block body RLP for hash %x: %v", hash, err)
   195  		return nil
   196  	}
   197  	return body
   198  }
   199  
   200  // GetTd retrieves a block's total difficulty corresponding to the hash, nil if
   201  // none found.
   202  func GetTd(db ethdb.Database, hash common.Hash, number uint64) *big.Int {
   203  	data, _ := db.Get(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash[:]...), tdSuffix...))
   204  	if len(data) == 0 {
   205  		data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldTdSuffix...))
   206  		if len(data) == 0 {
   207  			return nil
   208  		}
   209  	}
   210  	td := new(big.Int)
   211  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   212  		glog.V(logger.Error).Infof("invalid block total difficulty RLP for hash %x: %v", hash, err)
   213  		return nil
   214  	}
   215  	return td
   216  }
   217  
   218  // GetBlock retrieves an entire block corresponding to the hash, assembling it
   219  // back from the stored header and body. If either the header or body could not
   220  // be retrieved nil is returned.
   221  //
   222  // Note, due to concurrent download of header and block body the header and thus
   223  // canonical hash can be stored in the database but the body data not (yet).
   224  func GetBlock(db ethdb.Database, hash common.Hash, number uint64) *types.Block {
   225  	// Retrieve the block header and body contents
   226  	header := GetHeader(db, hash, number)
   227  	if header == nil {
   228  		return nil
   229  	}
   230  	body := GetBody(db, hash, number)
   231  	if body == nil {
   232  		return nil
   233  	}
   234  	// Reassemble the block and return
   235  	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   236  }
   237  
   238  // GetBlockReceipts retrieves the receipts generated by the transactions included
   239  // in a block given by its hash.
   240  func GetBlockReceipts(db ethdb.Database, hash common.Hash, number uint64) types.Receipts {
   241  	data, _ := db.Get(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash[:]...))
   242  	if len(data) == 0 {
   243  		data, _ = db.Get(append(oldBlockReceiptsPrefix, hash.Bytes()...))
   244  		if len(data) == 0 {
   245  			return nil
   246  		}
   247  	}
   248  	storageReceipts := []*types.ReceiptForStorage{}
   249  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   250  		glog.V(logger.Error).Infof("invalid receipt array RLP for hash %x: %v", hash, err)
   251  		return nil
   252  	}
   253  	receipts := make(types.Receipts, len(storageReceipts))
   254  	for i, receipt := range storageReceipts {
   255  		receipts[i] = (*types.Receipt)(receipt)
   256  	}
   257  	return receipts
   258  }
   259  
   260  // GetTransaction retrieves a specific transaction from the database, along with
   261  // its added positional metadata.
   262  func GetTransaction(db ethdb.Database, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
   263  	// Retrieve the transaction itself from the database
   264  	data, _ := db.Get(hash.Bytes())
   265  	if len(data) == 0 {
   266  		return nil, common.Hash{}, 0, 0
   267  	}
   268  	var tx types.Transaction
   269  	if err := rlp.DecodeBytes(data, &tx); err != nil {
   270  		return nil, common.Hash{}, 0, 0
   271  	}
   272  	// Retrieve the blockchain positional metadata
   273  	data, _ = db.Get(append(hash.Bytes(), txMetaSuffix...))
   274  	if len(data) == 0 {
   275  		return nil, common.Hash{}, 0, 0
   276  	}
   277  	var meta struct {
   278  		BlockHash  common.Hash
   279  		BlockIndex uint64
   280  		Index      uint64
   281  	}
   282  	if err := rlp.DecodeBytes(data, &meta); err != nil {
   283  		return nil, common.Hash{}, 0, 0
   284  	}
   285  	return &tx, meta.BlockHash, meta.BlockIndex, meta.Index
   286  }
   287  
   288  // GetReceipt returns a receipt by hash
   289  func GetReceipt(db ethdb.Database, txHash common.Hash) *types.Receipt {
   290  	data, _ := db.Get(append(receiptsPrefix, txHash[:]...))
   291  	if len(data) == 0 {
   292  		return nil
   293  	}
   294  	var receipt types.ReceiptForStorage
   295  	err := rlp.DecodeBytes(data, &receipt)
   296  	if err != nil {
   297  		glog.V(logger.Core).Infoln("GetReceipt err:", err)
   298  	}
   299  	return (*types.Receipt)(&receipt)
   300  }
   301  
   302  // WriteCanonicalHash stores the canonical hash for the given block number.
   303  func WriteCanonicalHash(db ethdb.Database, hash common.Hash, number uint64) error {
   304  	key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)
   305  	if err := db.Put(key, hash.Bytes()); err != nil {
   306  		glog.Fatalf("failed to store number to hash mapping into database: %v", err)
   307  	}
   308  	return nil
   309  }
   310  
   311  // WriteHeadHeaderHash stores the head header's hash.
   312  func WriteHeadHeaderHash(db ethdb.Database, hash common.Hash) error {
   313  	if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
   314  		glog.Fatalf("failed to store last header's hash into database: %v", err)
   315  	}
   316  	return nil
   317  }
   318  
   319  // WriteHeadBlockHash stores the head block's hash.
   320  func WriteHeadBlockHash(db ethdb.Database, hash common.Hash) error {
   321  	if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
   322  		glog.Fatalf("failed to store last block's hash into database: %v", err)
   323  	}
   324  	return nil
   325  }
   326  
   327  // WriteHeadFastBlockHash stores the fast head block's hash.
   328  func WriteHeadFastBlockHash(db ethdb.Database, hash common.Hash) error {
   329  	if err := db.Put(headFastKey, hash.Bytes()); err != nil {
   330  		glog.Fatalf("failed to store last fast block's hash into database: %v", err)
   331  	}
   332  	return nil
   333  }
   334  
   335  // WriteHeader serializes a block header into the database.
   336  func WriteHeader(db ethdb.Database, header *types.Header) error {
   337  	data, err := rlp.EncodeToBytes(header)
   338  	if err != nil {
   339  		return err
   340  	}
   341  	hash := header.Hash().Bytes()
   342  	num := header.Number.Uint64()
   343  	encNum := encodeBlockNumber(num)
   344  	key := append(blockHashPrefix, hash...)
   345  	if err := db.Put(key, encNum); err != nil {
   346  		glog.Fatalf("failed to store hash to number mapping into database: %v", err)
   347  	}
   348  	key = append(append(headerPrefix, encNum...), hash...)
   349  	if err := db.Put(key, data); err != nil {
   350  		glog.Fatalf("failed to store header into database: %v", err)
   351  	}
   352  	glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, hash[:4])
   353  	return nil
   354  }
   355  
   356  // WriteBody serializes the body of a block into the database.
   357  func WriteBody(db ethdb.Database, hash common.Hash, number uint64, body *types.Body) error {
   358  	data, err := rlp.EncodeToBytes(body)
   359  	if err != nil {
   360  		return err
   361  	}
   362  	return WriteBodyRLP(db, hash, number, data)
   363  }
   364  
   365  // WriteBodyRLP writes a serialized body of a block into the database.
   366  func WriteBodyRLP(db ethdb.Database, hash common.Hash, number uint64, rlp rlp.RawValue) error {
   367  	key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   368  	if err := db.Put(key, rlp); err != nil {
   369  		glog.Fatalf("failed to store block body into database: %v", err)
   370  	}
   371  	glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4])
   372  	return nil
   373  }
   374  
   375  // WriteTd serializes the total difficulty of a block into the database.
   376  func WriteTd(db ethdb.Database, hash common.Hash, number uint64, td *big.Int) error {
   377  	data, err := rlp.EncodeToBytes(td)
   378  	if err != nil {
   379  		return err
   380  	}
   381  	key := append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...)
   382  	if err := db.Put(key, data); err != nil {
   383  		glog.Fatalf("failed to store block total difficulty into database: %v", err)
   384  	}
   385  	glog.V(logger.Debug).Infof("stored block total difficulty [%x…]: %v", hash.Bytes()[:4], td)
   386  	return nil
   387  }
   388  
   389  // WriteBlock serializes a block into the database, header and body separately.
   390  func WriteBlock(db ethdb.Database, block *types.Block) error {
   391  	// Store the body first to retain database consistency
   392  	if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil {
   393  		return err
   394  	}
   395  	// Store the header too, signaling full block ownership
   396  	if err := WriteHeader(db, block.Header()); err != nil {
   397  		return err
   398  	}
   399  	return nil
   400  }
   401  
   402  // WriteBlockReceipts stores all the transaction receipts belonging to a block
   403  // as a single receipt slice. This is used during chain reorganisations for
   404  // rescheduling dropped transactions.
   405  func WriteBlockReceipts(db ethdb.Database, hash common.Hash, number uint64, receipts types.Receipts) error {
   406  	// Convert the receipts into their storage form and serialize them
   407  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   408  	for i, receipt := range receipts {
   409  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   410  	}
   411  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   412  	if err != nil {
   413  		return err
   414  	}
   415  	// Store the flattened receipt slice
   416  	key := append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
   417  	if err := db.Put(key, bytes); err != nil {
   418  		glog.Fatalf("failed to store block receipts into database: %v", err)
   419  	}
   420  	glog.V(logger.Debug).Infof("stored block receipts [%x…]", hash.Bytes()[:4])
   421  	return nil
   422  }
   423  
   424  // WriteTransactions stores the transactions associated with a specific block
   425  // into the given database. Beside writing the transaction, the function also
   426  // stores a metadata entry along with the transaction, detailing the position
   427  // of this within the blockchain.
   428  func WriteTransactions(db ethdb.Database, block *types.Block) error {
   429  	batch := db.NewBatch()
   430  
   431  	// Iterate over each transaction and encode it with its metadata
   432  	for i, tx := range block.Transactions() {
   433  		// Encode and queue up the transaction for storage
   434  		data, err := rlp.EncodeToBytes(tx)
   435  		if err != nil {
   436  			return err
   437  		}
   438  		if err := batch.Put(tx.Hash().Bytes(), data); err != nil {
   439  			return err
   440  		}
   441  		// Encode and queue up the transaction metadata for storage
   442  		meta := struct {
   443  			BlockHash  common.Hash
   444  			BlockIndex uint64
   445  			Index      uint64
   446  		}{
   447  			BlockHash:  block.Hash(),
   448  			BlockIndex: block.NumberU64(),
   449  			Index:      uint64(i),
   450  		}
   451  		data, err = rlp.EncodeToBytes(meta)
   452  		if err != nil {
   453  			return err
   454  		}
   455  		if err := batch.Put(append(tx.Hash().Bytes(), txMetaSuffix...), data); err != nil {
   456  			return err
   457  		}
   458  	}
   459  	// Write the scheduled data into the database
   460  	if err := batch.Write(); err != nil {
   461  		glog.Fatalf("failed to store transactions into database: %v", err)
   462  	}
   463  	return nil
   464  }
   465  
   466  // WriteReceipt stores a single transaction receipt into the database.
   467  func WriteReceipt(db ethdb.Database, receipt *types.Receipt) error {
   468  	storageReceipt := (*types.ReceiptForStorage)(receipt)
   469  	data, err := rlp.EncodeToBytes(storageReceipt)
   470  	if err != nil {
   471  		return err
   472  	}
   473  	return db.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data)
   474  }
   475  
   476  // WriteReceipts stores a batch of transaction receipts into the database.
   477  func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
   478  	batch := db.NewBatch()
   479  
   480  	// Iterate over all the receipts and queue them for database injection
   481  	for _, receipt := range receipts {
   482  		storageReceipt := (*types.ReceiptForStorage)(receipt)
   483  		data, err := rlp.EncodeToBytes(storageReceipt)
   484  		if err != nil {
   485  			return err
   486  		}
   487  		if err := batch.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data); err != nil {
   488  			return err
   489  		}
   490  	}
   491  	// Write the scheduled data into the database
   492  	if err := batch.Write(); err != nil {
   493  		glog.Fatalf("failed to store receipts into database: %v", err)
   494  	}
   495  	return nil
   496  }
   497  
   498  // DeleteCanonicalHash removes the number to hash canonical mapping.
   499  func DeleteCanonicalHash(db ethdb.Database, number uint64) {
   500  	db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...))
   501  }
   502  
   503  // DeleteHeader removes all block header data associated with a hash.
   504  func DeleteHeader(db ethdb.Database, hash common.Hash, number uint64) {
   505  	db.Delete(append(blockHashPrefix, hash.Bytes()...))
   506  	db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   507  }
   508  
   509  // DeleteBody removes all block body data associated with a hash.
   510  func DeleteBody(db ethdb.Database, hash common.Hash, number uint64) {
   511  	db.Delete(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   512  }
   513  
   514  // DeleteTd removes all block total difficulty data associated with a hash.
   515  func DeleteTd(db ethdb.Database, hash common.Hash, number uint64) {
   516  	db.Delete(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...))
   517  }
   518  
   519  // DeleteBlock removes all block data associated with a hash.
   520  func DeleteBlock(db ethdb.Database, hash common.Hash, number uint64) {
   521  	DeleteBlockReceipts(db, hash, number)
   522  	DeleteHeader(db, hash, number)
   523  	DeleteBody(db, hash, number)
   524  	DeleteTd(db, hash, number)
   525  }
   526  
   527  // DeleteBlockReceipts removes all receipt data associated with a block hash.
   528  func DeleteBlockReceipts(db ethdb.Database, hash common.Hash, number uint64) {
   529  	db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...))
   530  }
   531  
   532  // DeleteTransaction removes all transaction data associated with a hash.
   533  func DeleteTransaction(db ethdb.Database, hash common.Hash) {
   534  	db.Delete(hash.Bytes())
   535  	db.Delete(append(hash.Bytes(), txMetaSuffix...))
   536  }
   537  
   538  // DeleteReceipt removes all receipt data associated with a transaction hash.
   539  func DeleteReceipt(db ethdb.Database, hash common.Hash) {
   540  	db.Delete(append(receiptsPrefix, hash.Bytes()...))
   541  }
   542  
   543  // [deprecated by the header/block split, remove eventually]
   544  // GetBlockByHashOld returns the old combined block corresponding to the hash
   545  // or nil if not found. This method is only used by the upgrade mechanism to
   546  // access the old combined block representation. It will be dropped after the
   547  // network transitions to eth/63.
   548  func GetBlockByHashOld(db ethdb.Database, hash common.Hash) *types.Block {
   549  	data, _ := db.Get(append(oldBlockHashPrefix, hash[:]...))
   550  	if len(data) == 0 {
   551  		return nil
   552  	}
   553  	var block types.StorageBlock
   554  	if err := rlp.Decode(bytes.NewReader(data), &block); err != nil {
   555  		glog.V(logger.Error).Infof("invalid block RLP for hash %x: %v", hash, err)
   556  		return nil
   557  	}
   558  	return (*types.Block)(&block)
   559  }
   560  
   561  // returns a formatted MIP mapped key by adding prefix, canonical number and level
   562  //
   563  // ex. fn(98, 1000) = (prefix || 1000 || 0)
   564  func mipmapKey(num, level uint64) []byte {
   565  	lkey := make([]byte, 8)
   566  	binary.BigEndian.PutUint64(lkey, level)
   567  	key := new(big.Int).SetUint64(num / level * level)
   568  
   569  	return append(mipmapPre, append(lkey, key.Bytes()...)...)
   570  }
   571  
   572  // WriteMapmapBloom writes each address included in the receipts' logs to the
   573  // MIP bloom bin.
   574  func WriteMipmapBloom(db ethdb.Database, number uint64, receipts types.Receipts) error {
   575  	mipmapBloomMu.Lock()
   576  	defer mipmapBloomMu.Unlock()
   577  
   578  	batch := db.NewBatch()
   579  	for _, level := range MIPMapLevels {
   580  		key := mipmapKey(number, level)
   581  		bloomDat, _ := db.Get(key)
   582  		bloom := types.BytesToBloom(bloomDat)
   583  		for _, receipt := range receipts {
   584  			for _, log := range receipt.Logs {
   585  				bloom.Add(log.Address.Big())
   586  			}
   587  		}
   588  		batch.Put(key, bloom.Bytes())
   589  	}
   590  	if err := batch.Write(); err != nil {
   591  		return fmt.Errorf("mipmap write fail for: %d: %v", number, err)
   592  	}
   593  	return nil
   594  }
   595  
   596  // GetMipmapBloom returns a bloom filter using the number and level as input
   597  // parameters. For available levels see MIPMapLevels.
   598  func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
   599  	bloomDat, _ := db.Get(mipmapKey(number, level))
   600  	return types.BytesToBloom(bloomDat)
   601  }
   602  
   603  // PreimageTable returns a Database instance with the key prefix for preimage entries.
   604  func PreimageTable(db ethdb.Database) ethdb.Database {
   605  	return ethdb.NewTable(db, preimagePrefix)
   606  }
   607  
   608  // WritePreimages writes the provided set of preimages to the database. `number` is the
   609  // current block number, and is used for debug messages only.
   610  func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error {
   611  	table := PreimageTable(db)
   612  	batch := table.NewBatch()
   613  	hitCount := 0
   614  	for hash, preimage := range preimages {
   615  		if _, err := table.Get(hash.Bytes()); err != nil {
   616  			batch.Put(hash.Bytes(), preimage)
   617  			hitCount += 1
   618  		}
   619  	}
   620  	preimageCounter.Inc(int64(len(preimages)))
   621  	preimageHitCounter.Inc(int64(hitCount))
   622  	if hitCount > 0 {
   623  		if err := batch.Write(); err != nil {
   624  			return fmt.Errorf("preimage write fail for block %d: %v", number, err)
   625  		}
   626  		glog.V(logger.Debug).Infof("%d preimages in block %d, including %d new", len(preimages), number, hitCount)
   627  	}
   628  	return nil
   629  }
   630  
   631  // GetBlockChainVersion reads the version number from db.
   632  func GetBlockChainVersion(db ethdb.Database) int {
   633  	var vsn uint
   634  	enc, _ := db.Get([]byte("BlockchainVersion"))
   635  	rlp.DecodeBytes(enc, &vsn)
   636  	return int(vsn)
   637  }
   638  
   639  // WriteBlockChainVersion writes vsn as the version number to db.
   640  func WriteBlockChainVersion(db ethdb.Database, vsn int) {
   641  	enc, _ := rlp.EncodeToBytes(uint(vsn))
   642  	db.Put([]byte("BlockchainVersion"), enc)
   643  }
   644  
   645  // WriteChainConfig writes the chain config settings to the database.
   646  func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *params.ChainConfig) error {
   647  	// short circuit and ignore if nil config. GetChainConfig
   648  	// will return a default.
   649  	if cfg == nil {
   650  		return nil
   651  	}
   652  
   653  	jsonChainConfig, err := json.Marshal(cfg)
   654  	if err != nil {
   655  		return err
   656  	}
   657  
   658  	return db.Put(append(configPrefix, hash[:]...), jsonChainConfig)
   659  }
   660  
   661  // GetChainConfig will fetch the network settings based on the given hash.
   662  func GetChainConfig(db ethdb.Database, hash common.Hash) (*params.ChainConfig, error) {
   663  	jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...))
   664  	if len(jsonChainConfig) == 0 {
   665  		return nil, ChainConfigNotFoundErr
   666  	}
   667  
   668  	var config params.ChainConfig
   669  	if err := json.Unmarshal(jsonChainConfig, &config); err != nil {
   670  		return nil, err
   671  	}
   672  
   673  	return &config, nil
   674  }
   675  
   676  // FindCommonAncestor returns the last common ancestor of two block headers
   677  func FindCommonAncestor(db ethdb.Database, a, b *types.Header) *types.Header {
   678  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   679  		a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
   680  		if a == nil {
   681  			return nil
   682  		}
   683  	}
   684  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   685  		b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
   686  		if b == nil {
   687  			return nil
   688  		}
   689  	}
   690  	for a.Hash() != b.Hash() {
   691  		a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
   692  		if a == nil {
   693  			return nil
   694  		}
   695  		b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
   696  		if b == nil {
   697  			return nil
   698  		}
   699  	}
   700  	return a
   701  }