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