github.com/bhs-gq/quorum-hotstuff@v21.1.0+incompatible/core/rawdb/accessors_chain.go (about)

     1  // Copyright 2018 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 rawdb
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/ethdb"
    27  	"github.com/ethereum/go-ethereum/log"
    28  	"github.com/ethereum/go-ethereum/params"
    29  	"github.com/ethereum/go-ethereum/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  // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
   317  func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   318  	data, _ := db.Ancient(freezerDifficultyTable, number)
   319  	if len(data) == 0 {
   320  		data, _ = db.Get(headerTDKey(number, 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(freezerDifficultyTable, number)
   327  		}
   328  	}
   329  	return data
   330  }
   331  
   332  // ReadTd retrieves a block's total difficulty corresponding to the hash.
   333  func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int {
   334  	data := ReadTdRLP(db, hash, number)
   335  	if len(data) == 0 {
   336  		return nil
   337  	}
   338  	td := new(big.Int)
   339  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   340  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   341  		return nil
   342  	}
   343  	return td
   344  }
   345  
   346  // WriteTd stores the total difficulty of a block into the database.
   347  func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) {
   348  	data, err := rlp.EncodeToBytes(td)
   349  	if err != nil {
   350  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   351  	}
   352  	if err := db.Put(headerTDKey(number, hash), data); err != nil {
   353  		log.Crit("Failed to store block total difficulty", "err", err)
   354  	}
   355  }
   356  
   357  // DeleteTd removes all block total difficulty data associated with a hash.
   358  func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   359  	if err := db.Delete(headerTDKey(number, hash)); err != nil {
   360  		log.Crit("Failed to delete block total difficulty", "err", err)
   361  	}
   362  }
   363  
   364  // HasReceipts verifies the existence of all the transaction receipts belonging
   365  // to a block.
   366  func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
   367  	if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash {
   368  		return true
   369  	}
   370  	if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
   371  		return false
   372  	}
   373  	return true
   374  }
   375  
   376  // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
   377  func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   378  	data, _ := db.Ancient(freezerReceiptTable, number)
   379  	if len(data) == 0 {
   380  		data, _ = db.Get(blockReceiptsKey(number, hash))
   381  		// In the background freezer is moving data from leveldb to flatten files.
   382  		// So during the first check for ancient db, the data is not yet in there,
   383  		// but when we reach into leveldb, the data was already moved. That would
   384  		// result in a not found error.
   385  		if len(data) == 0 {
   386  			data, _ = db.Ancient(freezerReceiptTable, number)
   387  		}
   388  	}
   389  	return data
   390  }
   391  
   392  // ReadRawReceipts retrieves all the transaction receipts belonging to a block.
   393  // The receipt metadata fields are not guaranteed to be populated, so they
   394  // should not be used. Use ReadReceipts instead if the metadata is needed.
   395  func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts {
   396  	// Retrieve the flattened receipt slice
   397  	data := ReadReceiptsRLP(db, hash, number)
   398  	if len(data) == 0 {
   399  		return nil
   400  	}
   401  	// Convert the receipts from their storage form to their internal representation
   402  	storageReceipts := []*types.ReceiptForStorage{}
   403  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   404  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   405  		return nil
   406  	}
   407  	receipts := make(types.Receipts, len(storageReceipts))
   408  	for i, storageReceipt := range storageReceipts {
   409  		receipts[i] = (*types.Receipt)(storageReceipt)
   410  	}
   411  	return receipts
   412  }
   413  
   414  // ReadReceipts retrieves all the transaction receipts belonging to a block, including
   415  // its correspoinding metadata fields. If it is unable to populate these metadata
   416  // fields then nil is returned.
   417  //
   418  // The current implementation populates these metadata fields by reading the receipts'
   419  // corresponding block body, so if the block body is not found it will return nil even
   420  // if the receipt itself is stored.
   421  func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts {
   422  	// We're deriving many fields from the block body, retrieve beside the receipt
   423  	receipts := ReadRawReceipts(db, hash, number)
   424  	if receipts == nil {
   425  		return nil
   426  	}
   427  	body := ReadBody(db, hash, number)
   428  	if body == nil {
   429  		log.Error("Missing body but have receipt", "hash", hash, "number", number)
   430  		return nil
   431  	}
   432  	if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil {
   433  		log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
   434  		return nil
   435  	}
   436  	return receipts
   437  }
   438  
   439  // WriteReceipts stores all the transaction receipts belonging to a block.
   440  func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   441  	// Convert the receipts into their storage form and serialize them
   442  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   443  	for i, receipt := range receipts {
   444  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   445  	}
   446  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   447  	if err != nil {
   448  		log.Crit("Failed to encode block receipts", "err", err)
   449  	}
   450  	// Store the flattened receipt slice
   451  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   452  		log.Crit("Failed to store block receipts", "err", err)
   453  	}
   454  }
   455  
   456  // DeleteReceipts removes all receipt data associated with a block hash.
   457  func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   458  	if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
   459  		log.Crit("Failed to delete block receipts", "err", err)
   460  	}
   461  }
   462  
   463  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   464  // back from the stored header and body. If either the header or body could not
   465  // be retrieved nil is returned.
   466  //
   467  // Note, due to concurrent download of header and block body the header and thus
   468  // canonical hash can be stored in the database but the body data not (yet).
   469  func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
   470  	header := ReadHeader(db, hash, number)
   471  	if header == nil {
   472  		return nil
   473  	}
   474  	body := ReadBody(db, hash, number)
   475  	if body == nil {
   476  		return nil
   477  	}
   478  	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   479  }
   480  
   481  // WriteBlock serializes a block into the database, header and body separately.
   482  func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
   483  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   484  	WriteHeader(db, block.Header())
   485  }
   486  
   487  // WriteAncientBlock writes entire block data into ancient store and returns the total written size.
   488  func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int {
   489  	// Encode all block components to RLP format.
   490  	headerBlob, err := rlp.EncodeToBytes(block.Header())
   491  	if err != nil {
   492  		log.Crit("Failed to RLP encode block header", "err", err)
   493  	}
   494  	bodyBlob, err := rlp.EncodeToBytes(block.Body())
   495  	if err != nil {
   496  		log.Crit("Failed to RLP encode body", "err", err)
   497  	}
   498  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   499  	for i, receipt := range receipts {
   500  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   501  	}
   502  	receiptBlob, err := rlp.EncodeToBytes(storageReceipts)
   503  	if err != nil {
   504  		log.Crit("Failed to RLP encode block receipts", "err", err)
   505  	}
   506  	tdBlob, err := rlp.EncodeToBytes(td)
   507  	if err != nil {
   508  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   509  	}
   510  	// Write all blob to flatten files.
   511  	err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob)
   512  	if err != nil {
   513  		log.Crit("Failed to write block data to ancient store", "err", err)
   514  	}
   515  	return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(tdBlob) + common.HashLength
   516  }
   517  
   518  // DeleteBlock removes all block data associated with a hash.
   519  func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   520  	DeleteReceipts(db, hash, number)
   521  	DeleteHeader(db, hash, number)
   522  	DeleteBody(db, hash, number)
   523  	DeleteTd(db, hash, number)
   524  }
   525  
   526  // DeleteBlockWithoutNumber removes all block data associated with a hash, except
   527  // the hash to number mapping.
   528  func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
   529  	DeleteReceipts(db, hash, number)
   530  	deleteHeaderWithoutNumber(db, hash, number)
   531  	DeleteBody(db, hash, number)
   532  	DeleteTd(db, hash, number)
   533  }
   534  
   535  // FindCommonAncestor returns the last common ancestor of two block headers
   536  func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header {
   537  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   538  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   539  		if a == nil {
   540  			return nil
   541  		}
   542  	}
   543  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   544  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   545  		if b == nil {
   546  			return nil
   547  		}
   548  	}
   549  	for a.Hash() != b.Hash() {
   550  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   551  		if a == nil {
   552  			return nil
   553  		}
   554  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   555  		if b == nil {
   556  			return nil
   557  		}
   558  	}
   559  	return a
   560  }