github.com/luckypickle/go-ethereum-vet@v1.14.2/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/luckypickle/go-ethereum-vet/common"
    25  	"github.com/luckypickle/go-ethereum-vet/core/types"
    26  	"github.com/luckypickle/go-ethereum-vet/log"
    27  	"github.com/luckypickle/go-ethereum-vet/rlp"
    28  )
    29  
    30  // ReadCanonicalHash retrieves the hash assigned to a canonical block number.
    31  func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash {
    32  	data, _ := db.Get(headerHashKey(number))
    33  	if len(data) == 0 {
    34  		return common.Hash{}
    35  	}
    36  	return common.BytesToHash(data)
    37  }
    38  
    39  // WriteCanonicalHash stores the hash assigned to a canonical block number.
    40  func WriteCanonicalHash(db DatabaseWriter, hash common.Hash, number uint64) {
    41  	if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil {
    42  		log.Crit("Failed to store number to hash mapping", "err", err)
    43  	}
    44  }
    45  
    46  // DeleteCanonicalHash removes the number to hash canonical mapping.
    47  func DeleteCanonicalHash(db DatabaseDeleter, number uint64) {
    48  	if err := db.Delete(headerHashKey(number)); err != nil {
    49  		log.Crit("Failed to delete number to hash mapping", "err", err)
    50  	}
    51  }
    52  
    53  // ReadHeaderNumber returns the header number assigned to a hash.
    54  func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 {
    55  	data, _ := db.Get(headerNumberKey(hash))
    56  	if len(data) != 8 {
    57  		return nil
    58  	}
    59  	number := binary.BigEndian.Uint64(data)
    60  	return &number
    61  }
    62  
    63  // ReadHeadHeaderHash retrieves the hash of the current canonical head header.
    64  func ReadHeadHeaderHash(db DatabaseReader) common.Hash {
    65  	data, _ := db.Get(headHeaderKey)
    66  	if len(data) == 0 {
    67  		return common.Hash{}
    68  	}
    69  	return common.BytesToHash(data)
    70  }
    71  
    72  // WriteHeadHeaderHash stores the hash of the current canonical head header.
    73  func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) {
    74  	if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
    75  		log.Crit("Failed to store last header's hash", "err", err)
    76  	}
    77  }
    78  
    79  // ReadHeadBlockHash retrieves the hash of the current canonical head block.
    80  func ReadHeadBlockHash(db DatabaseReader) common.Hash {
    81  	data, _ := db.Get(headBlockKey)
    82  	if len(data) == 0 {
    83  		return common.Hash{}
    84  	}
    85  	return common.BytesToHash(data)
    86  }
    87  
    88  // WriteHeadBlockHash stores the head block's hash.
    89  func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) {
    90  	if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
    91  		log.Crit("Failed to store last block's hash", "err", err)
    92  	}
    93  }
    94  
    95  // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
    96  func ReadHeadFastBlockHash(db DatabaseReader) common.Hash {
    97  	data, _ := db.Get(headFastBlockKey)
    98  	if len(data) == 0 {
    99  		return common.Hash{}
   100  	}
   101  	return common.BytesToHash(data)
   102  }
   103  
   104  // WriteHeadFastBlockHash stores the hash of the current fast-sync head block.
   105  func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) {
   106  	if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil {
   107  		log.Crit("Failed to store last fast block's hash", "err", err)
   108  	}
   109  }
   110  
   111  // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow
   112  // reporting correct numbers across restarts.
   113  func ReadFastTrieProgress(db DatabaseReader) uint64 {
   114  	data, _ := db.Get(fastTrieProgressKey)
   115  	if len(data) == 0 {
   116  		return 0
   117  	}
   118  	return new(big.Int).SetBytes(data).Uint64()
   119  }
   120  
   121  // WriteFastTrieProgress stores the fast sync trie process counter to support
   122  // retrieving it across restarts.
   123  func WriteFastTrieProgress(db DatabaseWriter, count uint64) {
   124  	if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil {
   125  		log.Crit("Failed to store fast sync trie progress", "err", err)
   126  	}
   127  }
   128  
   129  // ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
   130  func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   131  	data, _ := db.Get(headerKey(number, hash))
   132  	return data
   133  }
   134  
   135  // HasHeader verifies the existence of a block header corresponding to the hash.
   136  func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool {
   137  	if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
   138  		return false
   139  	}
   140  	return true
   141  }
   142  
   143  // ReadHeader retrieves the block header corresponding to the hash.
   144  func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header {
   145  	data := ReadHeaderRLP(db, hash, number)
   146  	if len(data) == 0 {
   147  		return nil
   148  	}
   149  	header := new(types.Header)
   150  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   151  		log.Error("Invalid block header RLP", "hash", hash, "err", err)
   152  		return nil
   153  	}
   154  	return header
   155  }
   156  
   157  // WriteHeader stores a block header into the database and also stores the hash-
   158  // to-number mapping.
   159  func WriteHeader(db DatabaseWriter, header *types.Header) {
   160  	// Write the hash -> number mapping
   161  	var (
   162  		hash    = header.Hash()
   163  		number  = header.Number.Uint64()
   164  		encoded = encodeBlockNumber(number)
   165  	)
   166  	key := headerNumberKey(hash)
   167  	if err := db.Put(key, encoded); err != nil {
   168  		log.Crit("Failed to store hash to number mapping", "err", err)
   169  	}
   170  	// Write the encoded header
   171  	data, err := rlp.EncodeToBytes(header)
   172  	if err != nil {
   173  		log.Crit("Failed to RLP encode header", "err", err)
   174  	}
   175  	key = headerKey(number, hash)
   176  	if err := db.Put(key, data); err != nil {
   177  		log.Crit("Failed to store header", "err", err)
   178  	}
   179  }
   180  
   181  // DeleteHeader removes all block header data associated with a hash.
   182  func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) {
   183  	if err := db.Delete(headerKey(number, hash)); err != nil {
   184  		log.Crit("Failed to delete header", "err", err)
   185  	}
   186  	if err := db.Delete(headerNumberKey(hash)); err != nil {
   187  		log.Crit("Failed to delete hash to number mapping", "err", err)
   188  	}
   189  }
   190  
   191  // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   192  func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   193  	data, _ := db.Get(blockBodyKey(number, hash))
   194  	return data
   195  }
   196  
   197  // WriteBodyRLP stores an RLP encoded block body into the database.
   198  func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
   199  	if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
   200  		log.Crit("Failed to store block body", "err", err)
   201  	}
   202  }
   203  
   204  // HasBody verifies the existence of a block body corresponding to the hash.
   205  func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
   206  	if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
   207  		return false
   208  	}
   209  	return true
   210  }
   211  
   212  // ReadBody retrieves the block body corresponding to the hash.
   213  func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
   214  	data := ReadBodyRLP(db, hash, number)
   215  	if len(data) == 0 {
   216  		return nil
   217  	}
   218  	body := new(types.Body)
   219  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   220  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   221  		return nil
   222  	}
   223  	return body
   224  }
   225  
   226  // WriteBody storea a block body into the database.
   227  func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) {
   228  	data, err := rlp.EncodeToBytes(body)
   229  	if err != nil {
   230  		log.Crit("Failed to RLP encode body", "err", err)
   231  	}
   232  	WriteBodyRLP(db, hash, number, data)
   233  }
   234  
   235  // DeleteBody removes all block body data associated with a hash.
   236  func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) {
   237  	if err := db.Delete(blockBodyKey(number, hash)); err != nil {
   238  		log.Crit("Failed to delete block body", "err", err)
   239  	}
   240  }
   241  
   242  // ReadTd retrieves a block's total difficulty corresponding to the hash.
   243  func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
   244  	data, _ := db.Get(headerTDKey(number, hash))
   245  	if len(data) == 0 {
   246  		return nil
   247  	}
   248  	td := new(big.Int)
   249  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   250  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   251  		return nil
   252  	}
   253  	return td
   254  }
   255  
   256  // WriteTd stores the total difficulty of a block into the database.
   257  func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
   258  	data, err := rlp.EncodeToBytes(td)
   259  	if err != nil {
   260  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   261  	}
   262  	if err := db.Put(headerTDKey(number, hash), data); err != nil {
   263  		log.Crit("Failed to store block total difficulty", "err", err)
   264  	}
   265  }
   266  
   267  // DeleteTd removes all block total difficulty data associated with a hash.
   268  func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
   269  	if err := db.Delete(headerTDKey(number, hash)); err != nil {
   270  		log.Crit("Failed to delete block total difficulty", "err", err)
   271  	}
   272  }
   273  
   274  // ReadReceipts retrieves all the transaction receipts belonging to a block.
   275  func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts {
   276  	// Retrieve the flattened receipt slice
   277  	data, _ := db.Get(blockReceiptsKey(number, hash))
   278  	if len(data) == 0 {
   279  		return nil
   280  	}
   281  	// Convert the revceipts from their storage form to their internal representation
   282  	storageReceipts := []*types.ReceiptForStorage{}
   283  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   284  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   285  		return nil
   286  	}
   287  	receipts := make(types.Receipts, len(storageReceipts))
   288  	for i, receipt := range storageReceipts {
   289  		receipts[i] = (*types.Receipt)(receipt)
   290  	}
   291  	return receipts
   292  }
   293  
   294  // WriteReceipts stores all the transaction receipts belonging to a block.
   295  func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   296  	// Convert the receipts into their storage form and serialize them
   297  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   298  	for i, receipt := range receipts {
   299  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   300  	}
   301  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   302  	if err != nil {
   303  		log.Crit("Failed to encode block receipts", "err", err)
   304  	}
   305  	// Store the flattened receipt slice
   306  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   307  		log.Crit("Failed to store block receipts", "err", err)
   308  	}
   309  }
   310  
   311  // DeleteReceipts removes all receipt data associated with a block hash.
   312  func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
   313  	if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
   314  		log.Crit("Failed to delete block receipts", "err", err)
   315  	}
   316  }
   317  
   318  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   319  // back from the stored header and body. If either the header or body could not
   320  // be retrieved nil is returned.
   321  //
   322  // Note, due to concurrent download of header and block body the header and thus
   323  // canonical hash can be stored in the database but the body data not (yet).
   324  func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block {
   325  	header := ReadHeader(db, hash, number)
   326  	if header == nil {
   327  		return nil
   328  	}
   329  	body := ReadBody(db, hash, number)
   330  	if body == nil {
   331  		return nil
   332  	}
   333  	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   334  }
   335  
   336  // WriteBlock serializes a block into the database, header and body separately.
   337  func WriteBlock(db DatabaseWriter, block *types.Block) {
   338  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   339  	WriteHeader(db, block.Header())
   340  }
   341  
   342  // DeleteBlock removes all block data associated with a hash.
   343  func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) {
   344  	DeleteReceipts(db, hash, number)
   345  	DeleteHeader(db, hash, number)
   346  	DeleteBody(db, hash, number)
   347  	DeleteTd(db, hash, number)
   348  }
   349  
   350  // FindCommonAncestor returns the last common ancestor of two block headers
   351  func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
   352  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   353  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   354  		if a == nil {
   355  			return nil
   356  		}
   357  	}
   358  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   359  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   360  		if b == nil {
   361  			return nil
   362  		}
   363  	}
   364  	for a.Hash() != b.Hash() {
   365  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   366  		if a == nil {
   367  			return nil
   368  		}
   369  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   370  		if b == nil {
   371  			return nil
   372  		}
   373  	}
   374  	return a
   375  }