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