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