github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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/intfoundation/intchain/common"
    25  	"github.com/intfoundation/intchain/core/types"
    26  	"github.com/intfoundation/intchain/intdb"
    27  	"github.com/intfoundation/intchain/log"
    28  	"github.com/intfoundation/intchain/rlp"
    29  )
    30  
    31  // ReadCanonicalHash retrieves the hash assigned to a canonical block number.
    32  func ReadCanonicalHash(db intdb.Reader, number uint64) common.Hash {
    33  	data, _ := db.Get(headerHashKey(number))
    34  	if len(data) == 0 {
    35  		return common.Hash{}
    36  	}
    37  	return common.BytesToHash(data)
    38  }
    39  
    40  // WriteCanonicalHash stores the hash assigned to a canonical block number.
    41  func WriteCanonicalHash(db intdb.Writer, hash common.Hash, number uint64) {
    42  	if err := db.Put(headerHashKey(number), 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 intdb.Writer, number uint64) {
    49  	if err := db.Delete(headerHashKey(number)); 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 intdb.Reader, hash common.Hash) *uint64 {
    56  	data, _ := db.Get(headerNumberKey(hash))
    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 intdb.Reader) 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 intdb.Writer, 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 intdb.Reader) 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 intdb.Writer, 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 intdb.Reader) 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 intdb.Writer, 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 intdb.Reader) 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 intdb.Writer, 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 intdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   132  	data, _ := db.Get(headerKey(number, hash))
   133  	return data
   134  }
   135  
   136  // HasHeader verifies the existence of a block header corresponding to the hash.
   137  func HasHeader(db intdb.Reader, hash common.Hash, number uint64) bool {
   138  	if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
   139  		return false
   140  	}
   141  	return true
   142  }
   143  
   144  // ReadHeader retrieves the block header corresponding to the hash.
   145  func ReadHeader(db intdb.Reader, hash common.Hash, number uint64) *types.Header {
   146  	data := ReadHeaderRLP(db, hash, number)
   147  	if len(data) == 0 {
   148  		return nil
   149  	}
   150  	header := new(types.Header)
   151  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   152  		log.Error("Invalid block header RLP", "hash", hash, "err", err)
   153  		return nil
   154  	}
   155  	return header
   156  }
   157  
   158  // WriteHeader stores a block header into the database and also stores the hash-
   159  // to-number mapping.
   160  func WriteHeader(db intdb.Writer, header *types.Header) {
   161  	// Write the hash -> number mapping
   162  	var (
   163  		hash    = header.Hash()
   164  		number  = header.Number.Uint64()
   165  		encoded = encodeBlockNumber(number)
   166  	)
   167  	key := headerNumberKey(hash)
   168  	if err := db.Put(key, encoded); err != nil {
   169  		log.Crit("Failed to store hash to number mapping", "err", err)
   170  	}
   171  	// Write the encoded header
   172  	data, err := rlp.EncodeToBytes(header)
   173  	if err != nil {
   174  		log.Crit("Failed to RLP encode header", "err", err)
   175  	}
   176  	key = headerKey(number, hash)
   177  	if err := db.Put(key, data); err != nil {
   178  		log.Crit("Failed to store header", "err", err)
   179  	}
   180  }
   181  
   182  // DeleteHeader removes all block header data associated with a hash.
   183  func DeleteHeader(db intdb.Writer, hash common.Hash, number uint64) {
   184  	deleteHeaderWithoutNumber(db, hash, number)
   185  	if err := db.Delete(headerNumberKey(hash)); err != nil {
   186  		log.Crit("Failed to delete hash to number mapping", "err", err)
   187  	}
   188  }
   189  
   190  // deleteHeaderWithoutNumber removes only the block header but does not remove
   191  // the hash to number mapping.
   192  func deleteHeaderWithoutNumber(db intdb.Writer, hash common.Hash, number uint64) {
   193  	if err := db.Delete(headerKey(number, hash)); err != nil {
   194  		log.Crit("Failed to delete header", "err", err)
   195  	}
   196  }
   197  
   198  // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   199  func ReadBodyRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   200  	data, _ := db.Get(blockBodyKey(number, hash))
   201  	return data
   202  }
   203  
   204  // WriteBodyRLP stores an RLP encoded block body into the database.
   205  func WriteBodyRLP(db intdb.Writer, hash common.Hash, number uint64, rlp rlp.RawValue) {
   206  	if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
   207  		log.Crit("Failed to store block body", "err", err)
   208  	}
   209  }
   210  
   211  // HasBody verifies the existence of a block body corresponding to the hash.
   212  func HasBody(db intdb.Reader, hash common.Hash, number uint64) bool {
   213  	if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
   214  		return false
   215  	}
   216  	return true
   217  }
   218  
   219  // ReadBody retrieves the block body corresponding to the hash.
   220  func ReadBody(db intdb.Reader, hash common.Hash, number uint64) *types.Body {
   221  	data := ReadBodyRLP(db, hash, number)
   222  	if len(data) == 0 {
   223  		return nil
   224  	}
   225  	body := new(types.Body)
   226  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   227  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   228  		return nil
   229  	}
   230  	return body
   231  }
   232  
   233  // WriteBody storea a block body into the database.
   234  func WriteBody(db intdb.Writer, hash common.Hash, number uint64, body *types.Body) {
   235  	data, err := rlp.EncodeToBytes(body)
   236  	if err != nil {
   237  		log.Crit("Failed to RLP encode body", "err", err)
   238  	}
   239  	WriteBodyRLP(db, hash, number, data)
   240  }
   241  
   242  // DeleteBody removes all block body data associated with a hash.
   243  func DeleteBody(db intdb.Writer, hash common.Hash, number uint64) {
   244  	if err := db.Delete(blockBodyKey(number, hash)); err != nil {
   245  		log.Crit("Failed to delete block body", "err", err)
   246  	}
   247  }
   248  
   249  // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
   250  func ReadTdRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   251  	data, _ := db.Get(headerTDKey(number, hash))
   252  	return data
   253  }
   254  
   255  // ReadTd retrieves a block's total difficulty corresponding to the hash.
   256  func ReadTd(db intdb.Reader, hash common.Hash, number uint64) *big.Int {
   257  	data := ReadTdRLP(db, hash, number)
   258  	if len(data) == 0 {
   259  		return nil
   260  	}
   261  	td := new(big.Int)
   262  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   263  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   264  		return nil
   265  	}
   266  	return td
   267  }
   268  
   269  // WriteTd stores the total difficulty of a block into the database.
   270  func WriteTd(db intdb.Writer, hash common.Hash, number uint64, td *big.Int) {
   271  	data, err := rlp.EncodeToBytes(td)
   272  	if err != nil {
   273  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   274  	}
   275  	if err := db.Put(headerTDKey(number, hash), data); err != nil {
   276  		log.Crit("Failed to store block total difficulty", "err", err)
   277  	}
   278  }
   279  
   280  // DeleteTd removes all block total difficulty data associated with a hash.
   281  func DeleteTd(db intdb.Writer, hash common.Hash, number uint64) {
   282  	if err := db.Delete(headerTDKey(number, hash)); err != nil {
   283  		log.Crit("Failed to delete block total difficulty", "err", err)
   284  	}
   285  }
   286  
   287  // HasReceipts verifies the existence of all the transaction receipts belonging
   288  // to a block.
   289  func HasReceipts(db intdb.Reader, hash common.Hash, number uint64) bool {
   290  	if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
   291  		return false
   292  	}
   293  	return true
   294  }
   295  
   296  // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
   297  func ReadReceiptsRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
   298  	data, _ := db.Get(blockReceiptsKey(number, hash))
   299  	return data
   300  }
   301  
   302  // ReadReceipts retrieves all the transaction receipts belonging to a block.
   303  func ReadReceipts(db intdb.Reader, hash common.Hash, number uint64) types.Receipts {
   304  	// Retrieve the flattened receipt slice
   305  	data := ReadReceiptsRLP(db, hash, number)
   306  	if len(data) == 0 {
   307  		return nil
   308  	}
   309  	// Convert the receipts from their storage form to their internal representation
   310  	storageReceipts := []*types.ReceiptForStorage{}
   311  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   312  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   313  		return nil
   314  	}
   315  	receipts := make(types.Receipts, len(storageReceipts))
   316  	logIndex := uint(0)
   317  	for i, receipt := range storageReceipts {
   318  		// Assemble deriving fields for log.
   319  		for _, log := range receipt.Logs {
   320  			log.TxHash = receipt.TxHash
   321  			log.BlockHash = hash
   322  			log.BlockNumber = number
   323  			log.TxIndex = uint(i)
   324  			log.Index = logIndex
   325  			logIndex += 1
   326  		}
   327  		receipts[i] = (*types.Receipt)(receipt)
   328  		receipts[i].BlockHash = hash
   329  		receipts[i].BlockNumber = big.NewInt(0).SetUint64(number)
   330  		receipts[i].TransactionIndex = uint(i)
   331  	}
   332  	return receipts
   333  }
   334  
   335  // WriteReceipts stores all the transaction receipts belonging to a block.
   336  func WriteReceipts(db intdb.Writer, hash common.Hash, number uint64, receipts types.Receipts) {
   337  	// Convert the receipts into their storage form and serialize them
   338  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   339  	for i, receipt := range receipts {
   340  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   341  	}
   342  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   343  	if err != nil {
   344  		log.Crit("Failed to encode block receipts", "err", err)
   345  	}
   346  	// Store the flattened receipt slice
   347  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   348  		log.Crit("Failed to store block receipts", "err", err)
   349  	}
   350  }
   351  
   352  // DeleteReceipts removes all receipt data associated with a block hash.
   353  func DeleteReceipts(db intdb.Writer, hash common.Hash, number uint64) {
   354  	if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
   355  		log.Crit("Failed to delete block receipts", "err", err)
   356  	}
   357  }
   358  
   359  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   360  // back from the stored header and body. If either the header or body could not
   361  // be retrieved nil is returned.
   362  //
   363  // Note, due to concurrent download of header and block body the header and thus
   364  // canonical hash can be stored in the database but the body data not (yet).
   365  func ReadBlock(db intdb.Reader, hash common.Hash, number uint64) *types.Block {
   366  	header := ReadHeader(db, hash, number)
   367  	if header == nil {
   368  		return nil
   369  	}
   370  	body := ReadBody(db, hash, number)
   371  	if body == nil {
   372  		return nil
   373  	}
   374  	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   375  }
   376  
   377  // WriteBlock serializes a block into the database, header and body separately.
   378  func WriteBlock(db intdb.Writer, block *types.Block) {
   379  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   380  	WriteHeader(db, block.Header())
   381  }
   382  
   383  // DeleteBlock removes all block data associated with a hash.
   384  func DeleteBlock(db intdb.Writer, hash common.Hash, number uint64) {
   385  	DeleteReceipts(db, hash, number)
   386  	DeleteHeader(db, hash, number)
   387  	DeleteBody(db, hash, number)
   388  	DeleteTd(db, hash, number)
   389  }
   390  
   391  // deleteBlockWithoutNumber removes all block data associated with a hash, except
   392  // the hash to number mapping.
   393  func deleteBlockWithoutNumber(db intdb.Writer, hash common.Hash, number uint64) {
   394  	DeleteReceipts(db, hash, number)
   395  	deleteHeaderWithoutNumber(db, hash, number)
   396  	DeleteBody(db, hash, number)
   397  	DeleteTd(db, hash, number)
   398  }
   399  
   400  // FindCommonAncestor returns the last common ancestor of two block headers
   401  func FindCommonAncestor(db intdb.Reader, a, b *types.Header) *types.Header {
   402  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   403  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   404  		if a == nil {
   405  			return nil
   406  		}
   407  	}
   408  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   409  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   410  		if b == nil {
   411  			return nil
   412  		}
   413  	}
   414  	for a.Hash() != b.Hash() {
   415  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   416  		if a == nil {
   417  			return nil
   418  		}
   419  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   420  		if b == nil {
   421  			return nil
   422  		}
   423  	}
   424  	return a
   425  }