github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/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  	"github.com/insight-chain/inb-go/common"
    23  	"github.com/insight-chain/inb-go/core/types"
    24  	"github.com/insight-chain/inb-go/ethdb"
    25  	"github.com/insight-chain/inb-go/log"
    26  	"github.com/insight-chain/inb-go/rlp"
    27  	"math/big"
    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  //inb by ssh begin
   192  //type midBody struct {
   193  //	ITransactions []*types.ITransaction
   194  //	Uncles        []*types.Header
   195  //}
   196  
   197  // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   198  func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   199  	data, _ := db.Get(blockBodyKey(number, hash))
   200  	return data
   201  	//data, _ := db.Get(blockBodyKey(number, hash))
   202  	//if len(data) == 0 {
   203  	//	return []byte{}
   204  	//}
   205  	//mid := new(midBody)
   206  	//if err := rlp.Decode(bytes.NewReader(data), mid); err != nil {
   207  	//	log.Error("Invalid block body RLP", "hash", hash, "err", err)
   208  	//	return []byte{}
   209  	//}
   210  	//body := new(types.Body)
   211  	//body.Transactions = types.DecodeTransactionStruct(mid.ITransactions)
   212  	//body.Uncles = mid.Uncles
   213  	//dataOutPut, err := rlp.EncodeToBytes(body)
   214  	//if err != nil {
   215  	//	log.Error("Failed to RLP encode body", "err", err)
   216  	//	return []byte{}
   217  	//}
   218  	//return dataOutPut
   219  }
   220  
   221  // WriteBodyRLP stores an RLP encoded block body into the database.
   222  func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
   223  	if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
   224  		log.Crit("Failed to store block body", "err", err)
   225  	}
   226  }
   227  
   228  // HasBody verifies the existence of a block body corresponding to the hash.
   229  func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
   230  	if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
   231  		return false
   232  	}
   233  	return true
   234  }
   235  
   236  // ReadBody retrieves the block body corresponding to the hash.
   237  func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
   238  	data := ReadBodyRLP(db, hash, number)
   239  	if len(data) == 0 {
   240  		return nil
   241  	}
   242  	body := new(types.Body)
   243  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   244  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   245  		return nil
   246  	}
   247  	return body
   248  }
   249  
   250  // WriteBody storea a block body into the database.
   251  func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) {
   252  	//rlpTxs := types.EncodeTransactionStruct(body.Transactions)
   253  	//mid := &midBody{
   254  	//	ITransactions: rlpTxs,
   255  	//	Uncles:        body.Uncles,
   256  	//}
   257  	//data, err := rlp.EncodeToBytes(mid)
   258  	//if err != nil {
   259  	//	log.Crit("Failed to RLP encode body", "err", err)
   260  	//}
   261  	//WriteBodyRLP(db, hash, number, data)
   262  
   263  	data, err := rlp.EncodeToBytes(body)
   264  	if err != nil {
   265  		log.Crit("Failed to RLP encode body", "err", err)
   266  	}
   267  	WriteBodyRLP(db, hash, number, data)
   268  }
   269  
   270  //inb by ssh end
   271  
   272  // DeleteBody removes all block body data associated with a hash.
   273  func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) {
   274  	if err := db.Delete(blockBodyKey(number, hash)); err != nil {
   275  		log.Crit("Failed to delete block body", "err", err)
   276  	}
   277  }
   278  
   279  // ReadTd retrieves a block's total difficulty corresponding to the hash.
   280  func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
   281  	data, _ := db.Get(headerTDKey(number, hash))
   282  	if len(data) == 0 {
   283  		return nil
   284  	}
   285  	td := new(big.Int)
   286  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   287  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   288  		return nil
   289  	}
   290  	return td
   291  }
   292  
   293  // WriteTd stores the total difficulty of a block into the database.
   294  func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
   295  	data, err := rlp.EncodeToBytes(td)
   296  	if err != nil {
   297  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   298  	}
   299  	if err := db.Put(headerTDKey(number, hash), data); err != nil {
   300  		log.Crit("Failed to store block total difficulty", "err", err)
   301  	}
   302  }
   303  
   304  // DeleteTd removes all block total difficulty data associated with a hash.
   305  func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
   306  	if err := db.Delete(headerTDKey(number, hash)); err != nil {
   307  		log.Crit("Failed to delete block total difficulty", "err", err)
   308  	}
   309  }
   310  
   311  // HasReceipts verifies the existence of all the transaction receipts belonging
   312  // to a block.
   313  func HasReceipts(db DatabaseReader, hash common.Hash, number uint64) bool {
   314  	if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
   315  		return false
   316  	}
   317  	return true
   318  }
   319  
   320  // ReadReceipts retrieves all the transaction receipts belonging to a block.
   321  func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts {
   322  	// Retrieve the flattened receipt slice
   323  	data, _ := db.Get(blockReceiptsKey(number, hash))
   324  	if len(data) == 0 {
   325  		return nil
   326  	}
   327  	// Convert the receipts from their storage form to their internal representation
   328  	storageReceipts := []*types.ReceiptForStorage{}
   329  	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
   330  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   331  		return nil
   332  	}
   333  	receipts := make(types.Receipts, len(storageReceipts))
   334  	for i, receipt := range storageReceipts {
   335  		receipts[i] = (*types.Receipt)(receipt)
   336  	}
   337  	return receipts
   338  }
   339  
   340  // WriteReceipts stores all the transaction receipts belonging to a block.
   341  func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   342  	// Convert the receipts into their storage form and serialize them
   343  	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
   344  	for i, receipt := range receipts {
   345  		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
   346  	}
   347  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   348  	if err != nil {
   349  		log.Crit("Failed to encode block receipts", "err", err)
   350  	}
   351  	// Store the flattened receipt slice
   352  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   353  		log.Crit("Failed to store block receipts", "err", err)
   354  	}
   355  }
   356  
   357  // DeleteReceipts removes all receipt data associated with a block hash.
   358  func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
   359  	if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
   360  		log.Crit("Failed to delete block receipts", "err", err)
   361  	}
   362  }
   363  
   364  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   365  // back from the stored header and body. If either the header or body could not
   366  // be retrieved nil is returned.
   367  //
   368  // Note, due to concurrent download of header and block body the header and thus
   369  // canonical hash can be stored in the database but the body data not (yet).
   370  func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block {
   371  	header := ReadHeader(db, hash, number)
   372  	if header == nil {
   373  		return nil
   374  	}
   375  	body := ReadBody(db, hash, number)
   376  	if body == nil {
   377  		return nil
   378  	}
   379  
   380  	// add by ssh 190815 begin
   381  	//return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   382  	block := types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
   383  	block.VdposContext = getVdposContextTrie(db.(ethdb.Database), header)
   384  	return block
   385  	// add by ssh 190815 end
   386  }
   387  
   388  // add by ssh 190815 begin
   389  func getVdposContextTrie(db ethdb.Database, header *types.Header) *types.VdposContext {
   390  	vdposContestProto := header.VdposContext
   391  	if vdposContestProto != nil {
   392  		vdposContext, err := types.NewVdposContextFromProto(db, vdposContestProto)
   393  		if err != nil {
   394  			return nil
   395  		}
   396  		return vdposContext
   397  	}
   398  	return nil
   399  }
   400  
   401  // add by ssh 190815 end
   402  
   403  // WriteBlock serializes a block into the database, header and body separately.
   404  func WriteBlock(db DatabaseWriter, block *types.Block) {
   405  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   406  	WriteHeader(db, block.Header())
   407  }
   408  
   409  // DeleteBlock removes all block data associated with a hash.
   410  func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) {
   411  	DeleteReceipts(db, hash, number)
   412  	DeleteHeader(db, hash, number)
   413  	DeleteBody(db, hash, number)
   414  	DeleteTd(db, hash, number)
   415  }
   416  
   417  // FindCommonAncestor returns the last common ancestor of two block headers
   418  func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
   419  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   420  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   421  		if a == nil {
   422  			return nil
   423  		}
   424  	}
   425  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   426  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   427  		if b == nil {
   428  			return nil
   429  		}
   430  	}
   431  	for a.Hash() != b.Hash() {
   432  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   433  		if a == nil {
   434  			return nil
   435  		}
   436  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   437  		if b == nil {
   438  			return nil
   439  		}
   440  	}
   441  	return a
   442  }