github.com/ebakus/go-ebakus@v1.0.5-0.20200520105415-dbccef9ec421/core/rawdb/accessors_chain.go (about)

     1  // Copyright 2019 The ebakus/go-ebakus Authors
     2  // This file is part of the ebakus/go-ebakus library.
     3  //
     4  // The ebakus/go-ebakus 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 ebakus/go-ebakus 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 ebakus/go-ebakus library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rawdb
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"math/big"
    23  
    24  	"github.com/ebakus/go-ebakus/common"
    25  	"github.com/ebakus/go-ebakus/core/types"
    26  	"github.com/ebakus/go-ebakus/ethdb"
    27  	"github.com/ebakus/go-ebakus/log"
    28  	"github.com/ebakus/go-ebakus/params"
    29  	"github.com/ebakus/go-ebakus/rlp"
    30  )
    31  
    32  // ReadCanonicalHash retrieves the hash assigned to a canonical block number.
    33  func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
    34  	data, _ := db.Ancient(freezerHashTable, number)
    35  	if len(data) == 0 {
    36  		data, _ = db.Get(headerHashKey(number))
    37  		// In the background freezer is moving data from leveldb to flatten files.
    38  		// So during the first check for ancient db, the data is not yet in there,
    39  		// but when we reach into leveldb, the data was already moved. That would
    40  		// result in a not found error.
    41  		if len(data) == 0 {
    42  			data, _ = db.Ancient(freezerHashTable, number)
    43  		}
    44  	}
    45  	if len(data) == 0 {
    46  		return common.Hash{}
    47  	}
    48  	return common.BytesToHash(data)
    49  }
    50  
    51  // WriteCanonicalHash stores the hash assigned to a canonical block number.
    52  func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
    53  	if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil {
    54  		log.Crit("Failed to store number to hash mapping", "err", err)
    55  	}
    56  }
    57  
    58  // DeleteCanonicalHash removes the number to hash canonical mapping.
    59  func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) {
    60  	if err := db.Delete(headerHashKey(number)); err != nil {
    61  		log.Crit("Failed to delete number to hash mapping", "err", err)
    62  	}
    63  }
    64  
    65  // ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights,
    66  // both canonical and reorged forks included.
    67  func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash {
    68  	prefix := headerKeyPrefix(number)
    69  
    70  	hashes := make([]common.Hash, 0, 1)
    71  	it := db.NewIteratorWithPrefix(prefix)
    72  	defer it.Release()
    73  
    74  	for it.Next() {
    75  		if key := it.Key(); len(key) == len(prefix)+32 {
    76  			hashes = append(hashes, common.BytesToHash(key[len(key)-32:]))
    77  		}
    78  	}
    79  	return hashes
    80  }
    81  
    82  // ReadHeaderNumber returns the header number assigned to a hash.
    83  func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 {
    84  	data, _ := db.Get(headerNumberKey(hash))
    85  	if len(data) != 8 {
    86  		return nil
    87  	}
    88  	number := binary.BigEndian.Uint64(data)
    89  	return &number
    90  }
    91  
    92  // WriteHeaderNumber stores the hash->number mapping.
    93  func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
    94  	key := headerNumberKey(hash)
    95  	enc := encodeBlockNumber(number)
    96  	if err := db.Put(key, enc); err != nil {
    97  		log.Crit("Failed to store hash to number mapping", "err", err)
    98  	}
    99  }
   100  
   101  // DeleteHeaderNumber removes hash->number mapping.
   102  func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) {
   103  	if err := db.Delete(headerNumberKey(hash)); err != nil {
   104  		log.Crit("Failed to delete hash to number mapping", "err", err)
   105  	}
   106  }
   107  
   108  // ReadHeadHeaderHash retrieves the hash of the current canonical head header.
   109  func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash {
   110  	data, _ := db.Get(headHeaderKey)
   111  	if len(data) == 0 {
   112  		return common.Hash{}
   113  	}
   114  	return common.BytesToHash(data)
   115  }
   116  
   117  // WriteHeadHeaderHash stores the hash of the current canonical head header.
   118  func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) {
   119  	if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
   120  		log.Crit("Failed to store last header's hash", "err", err)
   121  	}
   122  }
   123  
   124  // ReadHeadBlockHash retrieves the hash of the current canonical head block.
   125  func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash {
   126  	data, _ := db.Get(headBlockKey)
   127  	if len(data) == 0 {
   128  		return common.Hash{}
   129  	}
   130  	return common.BytesToHash(data)
   131  }
   132  
   133  // WriteHeadBlockHash stores the head block's hash.
   134  func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) {
   135  	if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
   136  		log.Crit("Failed to store last block's hash", "err", err)
   137  	}
   138  }
   139  
   140  // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
   141  func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash {
   142  	data, _ := db.Get(headFastBlockKey)
   143  	if len(data) == 0 {
   144  		return common.Hash{}
   145  	}
   146  	return common.BytesToHash(data)
   147  }
   148  
   149  // WriteHeadFastBlockHash stores the hash of the current fast-sync head block.
   150  func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) {
   151  	if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil {
   152  		log.Crit("Failed to store last fast block's hash", "err", err)
   153  	}
   154  }
   155  
   156  // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow
   157  // reporting correct numbers across restarts.
   158  func ReadFastTrieProgress(db ethdb.KeyValueReader) uint64 {
   159  	data, _ := db.Get(fastTrieProgressKey)
   160  	if len(data) == 0 {
   161  		return 0
   162  	}
   163  	return new(big.Int).SetBytes(data).Uint64()
   164  }
   165  
   166  // WriteFastTrieProgress stores the fast sync trie process counter to support
   167  // retrieving it across restarts.
   168  func WriteFastTrieProgress(db ethdb.KeyValueWriter, count uint64) {
   169  	if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil {
   170  		log.Crit("Failed to store fast sync trie progress", "err", err)
   171  	}
   172  }
   173  
   174  // ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
   175  func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   176  	data, _ := db.Ancient(freezerHeaderTable, number)
   177  	if len(data) == 0 {
   178  		data, _ = db.Get(headerKey(number, hash))
   179  		// In the background freezer is moving data from leveldb to flatten files.
   180  		// So during the first check for ancient db, the data is not yet in there,
   181  		// but when we reach into leveldb, the data was already moved. That would
   182  		// result in a not found error.
   183  		if len(data) == 0 {
   184  			data, _ = db.Ancient(freezerHeaderTable, number)
   185  		}
   186  	}
   187  	return data
   188  }
   189  
   190  // HasHeader verifies the existence of a block header corresponding to the hash.
   191  func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool {
   192  	if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
   193  		return true
   194  	}
   195  	if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
   196  		return false
   197  	}
   198  	return true
   199  }
   200  
   201  // ReadHeader retrieves the block header corresponding to the hash.
   202  func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header {
   203  	data := ReadHeaderRLP(db, hash, number)
   204  	if len(data) == 0 {
   205  		return nil
   206  	}
   207  	header := new(types.Header)
   208  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   209  		log.Error("Invalid block header RLP", "hash", hash, "err", err)
   210  		return nil
   211  	}
   212  	return header
   213  }
   214  
   215  // WriteHeader stores a block header into the database and also stores the hash-
   216  // to-number mapping.
   217  func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) {
   218  	var (
   219  		hash   = header.Hash()
   220  		number = header.Number.Uint64()
   221  	)
   222  	// Write the hash -> number mapping
   223  	WriteHeaderNumber(db, hash, number)
   224  
   225  	// Write the encoded header
   226  	data, err := rlp.EncodeToBytes(header)
   227  	if err != nil {
   228  		log.Crit("Failed to RLP encode header", "err", err)
   229  	}
   230  	key := headerKey(number, hash)
   231  	if err := db.Put(key, data); err != nil {
   232  		log.Crit("Failed to store header", "err", err)
   233  	}
   234  }
   235  
   236  // DeleteHeader removes all block header data associated with a hash.
   237  func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   238  	deleteHeaderWithoutNumber(db, hash, number)
   239  	if err := db.Delete(headerNumberKey(hash)); err != nil {
   240  		log.Crit("Failed to delete hash to number mapping", "err", err)
   241  	}
   242  }
   243  
   244  // deleteHeaderWithoutNumber removes only the block header but does not remove
   245  // the hash to number mapping.
   246  func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   247  	if err := db.Delete(headerKey(number, hash)); err != nil {
   248  		log.Crit("Failed to delete header", "err", err)
   249  	}
   250  }
   251  
   252  // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   253  func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   254  	data, _ := db.Ancient(freezerBodiesTable, number)
   255  	if len(data) == 0 {
   256  		data, _ = db.Get(blockBodyKey(number, hash))
   257  		// In the background freezer is moving data from leveldb to flatten files.
   258  		// So during the first check for ancient db, the data is not yet in there,
   259  		// but when we reach into leveldb, the data was already moved. That would
   260  		// result in a not found error.
   261  		if len(data) == 0 {
   262  			data, _ = db.Ancient(freezerBodiesTable, number)
   263  		}
   264  	}
   265  	return data
   266  }
   267  
   268  // WriteBodyRLP stores an RLP encoded block body into the database.
   269  func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
   270  	if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
   271  		log.Crit("Failed to store block body", "err", err)
   272  	}
   273  }
   274  
   275  // HasBody verifies the existence of a block body corresponding to the hash.
   276  func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
   277  	if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
   278  		return true
   279  	}
   280  	if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
   281  		return false
   282  	}
   283  	return true
   284  }
   285  
   286  // ReadBody retrieves the block body corresponding to the hash.
   287  func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body {
   288  	data := ReadBodyRLP(db, hash, number)
   289  	if len(data) == 0 {
   290  		return nil
   291  	}
   292  	body := new(types.Body)
   293  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   294  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   295  		return nil
   296  	}
   297  	return body
   298  }
   299  
   300  // WriteBody stores a block body into the database.
   301  func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) {
   302  	data, err := rlp.EncodeToBytes(body)
   303  	if err != nil {
   304  		log.Crit("Failed to RLP encode body", "err", err)
   305  	}
   306  	WriteBodyRLP(db, hash, number, data)
   307  }
   308  
   309  // DeleteBody removes all block body data associated with a hash.
   310  func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   311  	if err := db.Delete(blockBodyKey(number, hash)); err != nil {
   312  		log.Crit("Failed to delete block body", "err", err)
   313  	}
   314  }
   315  
   316  // ReadSnapshotRLP retrieves all the transaction snapshot belonging to a block in RLP encoding.
   317  func ReadSnapshotRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   318  	data, _ := db.Ancient(freezerSnapshotTable, number)
   319  	if len(data) == 0 {
   320  		data, _ = db.Get(snapshotKey(hash))
   321  		// In the background freezer is moving data from leveldb to flatten files.
   322  		// So during the first check for ancient db, the data is not yet in there,
   323  		// but when we reach into leveldb, the data was already moved. That would
   324  		// result in a not found error.
   325  		if len(data) == 0 {
   326  			data, _ = db.Ancient(freezerSnapshotTable, number)
   327  		}
   328  	}
   329  	return data
   330  }
   331  
   332  // ReadSnapshot retrieves a block's ebakusdb snapshot corresponding to the hash, nil if none found.
   333  func ReadSnapshot(db ethdb.Reader, hash common.Hash, number uint64) *uint64 {
   334  	data := ReadSnapshotRLP(db, hash, number)
   335  	if len(data) == 0 {
   336  		return nil
   337  	}
   338  	var snapID uint64
   339  	if err := rlp.DecodeBytes(data, &snapID); err != nil {
   340  		log.Error("Invalid block snapshot", "hash", hash, "err", err)
   341  		return nil
   342  	}
   343  	return &snapID
   344  }
   345  
   346  // WriteSnapshot serializes the state snapshot id of a block into the database.
   347  func WriteSnapshot(db ethdb.KeyValueWriter, hash common.Hash, snapshotID uint64) error {
   348  	data, err := rlp.EncodeToBytes(snapshotID)
   349  	if err != nil {
   350  		return err
   351  	}
   352  	key := snapshotKey(hash)
   353  	if err := db.Put(key, data); err != nil {
   354  		log.Crit("Failed to store block ebakus state snapshot", "err", err)
   355  	}
   356  	return nil
   357  }
   358  
   359  // DeleteSnapshot removes the state snapshot associated with a hash.
   360  func DeleteSnapshot(db ethdb.KeyValueWriter, hash common.Hash) {
   361  	key := snapshotKey(hash)
   362  	if err := db.Delete(key); err != nil {
   363  		log.Crit("Failed to delete block ebakus state snapshot", "err", err)
   364  	}
   365  }
   366  
   367  // HasReceipts verifies the existence of all the transaction receipts belonging
   368  // to a block.
   369  func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
   370  	if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
   371  		return true
   372  	}
   373  	if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
   374  		return false
   375  	}
   376  	return true
   377  }
   378  
   379  // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
   380  func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   381  	data, _ := db.Ancient(freezerReceiptTable, number)
   382  	if len(data) == 0 {
   383  		data, _ = db.Get(blockReceiptsKey(number, hash))
   384  		// In the background freezer is moving data from leveldb to flatten files.
   385  		// So during the first check for ancient db, the data is not yet in there,
   386  		// but when we reach into leveldb, the data was already moved. That would
   387  		// result in a not found error.
   388  		if len(data) == 0 {
   389  			data, _ = db.Ancient(freezerReceiptTable, number)
   390  		}
   391  	}
   392  	return data
   393  }
   394  
   395  // ReadRawReceipts retrieves all the transaction receipts belonging to a block.
   396  // The receipt metadata fields are not guaranteed to be populated, so they
   397  // should not be used. Use ReadReceipts instead if the metadata is needed.
   398  func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts {
   399  	// Retrieve the flattened receipt slice
   400  	data := ReadReceiptsRLP(db, hash, number)
   401  	if len(data) == 0 {
   402  		return nil
   403  	}
   404  	// Convert the receipts from their storage form to their internal representation
   405  	storageReceipts := []*types.ReceiptForStorage{}
   406  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   407  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   408  		return nil
   409  	}
   410  	receipts := make(types.Receipts, len(storageReceipts))
   411  	for i, storageReceipt := range storageReceipts {
   412  		receipts[i] = (*types.Receipt)(storageReceipt)
   413  	}
   414  	return receipts
   415  }
   416  
   417  // ReadReceipts retrieves all the transaction receipts belonging to a block, including
   418  // its correspoinding metadata fields. If it is unable to populate these metadata
   419  // fields then nil is returned.
   420  //
   421  // The current implementation populates these metadata fields by reading the receipts'
   422  // corresponding block body, so if the block body is not found it will return nil even
   423  // if the receipt itself is stored.
   424  func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts {
   425  	// We're deriving many fields from the block body, retrieve beside the receipt
   426  	receipts := ReadRawReceipts(db, hash, number)
   427  	if receipts == nil {
   428  		return nil
   429  	}
   430  	body := ReadBody(db, hash, number)
   431  	if body == nil {
   432  		log.Error("Missing body but have receipt", "hash", hash, "number", number)
   433  		return nil
   434  	}
   435  	if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil {
   436  		log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
   437  		return nil
   438  	}
   439  	return receipts
   440  }
   441  
   442  // WriteReceipts stores all the transaction receipts belonging to a block.
   443  func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   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  		log.Crit("Failed to encode block receipts", "err", err)
   452  	}
   453  	// Store the flattened receipt slice
   454  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   455  		log.Crit("Failed to store block receipts", "err", err)
   456  	}
   457  }
   458  
   459  // DeleteReceipts removes all receipt data associated with a block hash.
   460  func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   461  	if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
   462  		log.Crit("Failed to delete block receipts", "err", err)
   463  	}
   464  }
   465  
   466  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   467  // back from the stored header and body. If either the header or body could not
   468  // be retrieved nil is returned.
   469  //
   470  // Note, due to concurrent download of header and block body the header and thus
   471  // canonical hash can be stored in the database but the body data not (yet).
   472  func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
   473  	header := ReadHeader(db, hash, number)
   474  	if header == nil {
   475  		return nil
   476  	}
   477  	body := ReadBody(db, hash, number)
   478  	if body == nil {
   479  		return nil
   480  	}
   481  	return types.NewBlockWithHeader(header).WithBody(body.Transactions)
   482  }
   483  
   484  // WriteBlock serializes a block into the database, header and body separately.
   485  func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
   486  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   487  	WriteHeader(db, block.Header())
   488  }
   489  
   490  // WriteAncientBlock writes entire block data into ancient store and returns the total written size.
   491  func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, ebakusSnapshot *uint64) int {
   492  	// Encode all block components to RLP format.
   493  	headerBlob, err := rlp.EncodeToBytes(block.Header())
   494  	if err != nil {
   495  		log.Crit("Failed to RLP encode block header", "err", err)
   496  	}
   497  	bodyBlob, err := rlp.EncodeToBytes(block.Body())
   498  	if err != nil {
   499  		log.Crit("Failed to RLP encode body", "err", err)
   500  	}
   501  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   502  	for i, receipt := range receipts {
   503  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   504  	}
   505  	receiptBlob, err := rlp.EncodeToBytes(storageReceipts)
   506  	if err != nil {
   507  		log.Crit("Failed to RLP encode block receipts", "err", err)
   508  	}
   509  	ebakusSnapshotBlob, err := rlp.EncodeToBytes(ebakusSnapshot)
   510  	if err != nil {
   511  		log.Crit("Failed to RLP encode block ebakusdb snapshot Id", "err", err)
   512  	}
   513  	// Write all blob to flatten files.
   514  	err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, ebakusSnapshotBlob)
   515  	if err != nil {
   516  		log.Crit("Failed to write block data to ancient store", "err", err)
   517  	}
   518  	return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(ebakusSnapshotBlob) + common.HashLength
   519  }
   520  
   521  // DeleteBlock removes all block data associated with a hash.
   522  func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   523  	DeleteReceipts(db, hash, number)
   524  	DeleteHeader(db, hash, number)
   525  	DeleteBody(db, hash, number)
   526  	DeleteSnapshot(db, hash)
   527  }
   528  
   529  // DeleteBlockWithoutNumber removes all block data associated with a hash, except
   530  // the hash to number mapping.
   531  func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   532  	DeleteReceipts(db, hash, number)
   533  	deleteHeaderWithoutNumber(db, hash, number)
   534  	DeleteBody(db, hash, number)
   535  	DeleteSnapshot(db, hash)
   536  }
   537  
   538  // FindCommonAncestor returns the last common ancestor of two block headers
   539  func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header {
   540  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   541  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   542  		if a == nil {
   543  			return nil
   544  		}
   545  	}
   546  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   547  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   548  		if b == nil {
   549  			return nil
   550  		}
   551  	}
   552  	for a.Hash() != b.Hash() {
   553  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   554  		if a == nil {
   555  			return nil
   556  		}
   557  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   558  		if b == nil {
   559  			return nil
   560  		}
   561  	}
   562  	return a
   563  }