github.com/bcskill/bcschain/v3@v3.4.9-beta2/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/bcskill/bcschain/v3/common"
    25  	"github.com/bcskill/bcschain/v3/core/types"
    26  	"github.com/bcskill/bcschain/v3/ethdb"
    27  	"github.com/bcskill/bcschain/v3/log"
    28  	"github.com/bcskill/bcschain/v3/params"
    29  	"github.com/bcskill/bcschain/v3/rlp"
    30  )
    31  
    32  // ReadCanonicalHash retrieves the hash assigned to a canonical block number.
    33  func ReadCanonicalHash(db common.Database, number uint64) common.Hash {
    34  	k := numKey(number)
    35  	var data []byte
    36  	Must("get canonical hash", func() (err error) {
    37  		data, err = db.GlobalTable().Get(k)
    38  		if err == common.ErrNotFound {
    39  			data, err = db.HeaderTable().Get(k)
    40  			if err == common.ErrNotFound {
    41  				err = nil
    42  			}
    43  			if err != nil {
    44  				// Move to global for faster future lookup.
    45  				perr := db.GlobalTable().Put(k, data)
    46  				if perr != nil {
    47  					log.Warn("Failed to put canonical hash to global table", "number", number, "err", perr)
    48  				} else {
    49  					// Can ignore ErrImmutableSegment errors here.
    50  					if derr := db.HeaderTable().Delete(k); err != nil && err != ethdb.ErrImmutableSegment {
    51  						log.Warn("Failed to delete canonical hash from header table", "number", number, "err", derr)
    52  					}
    53  				}
    54  			}
    55  		}
    56  		return
    57  	})
    58  	if len(data) == 0 {
    59  		return common.Hash{}
    60  	}
    61  	return common.BytesToHash(data)
    62  }
    63  
    64  // WriteCanonicalHash stores the hash assigned to a canonical block number.
    65  func WriteCanonicalHash(db common.Database, hash common.Hash, number uint64) {
    66  	Must("put canonical hash", func() error {
    67  		return db.GlobalTable().Put(numKey(number), hash.Bytes())
    68  	})
    69  }
    70  
    71  // DeleteCanonicalHash removes the number to hash canonical mapping.
    72  func DeleteCanonicalHash(db common.Database, number uint64) {
    73  	k := numKey(number)
    74  	Must("delete canonical hash", func() error {
    75  		if err := db.HeaderTable().Delete(k); err != nil && err != ethdb.ErrImmutableSegment {
    76  			log.Warn("Failed to delete canonical hash from header table", "number", number, "err", err)
    77  			return err
    78  		} else if err == ethdb.ErrImmutableSegment {
    79  			// Cannot tolerate ErrImmutableSegment errors here, but this shouldn't happen in practice.
    80  			log.Crit("Unable to delete canonical hash from immutable segment. Database may not be recoverable.", "number", number, "err", err)
    81  		}
    82  		return db.GlobalTable().Delete(k)
    83  	})
    84  }
    85  
    86  // ReadHeaderNumber returns the header number assigned to a hash.
    87  func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 {
    88  	var data []byte
    89  	Must("get header number", func() (err error) {
    90  		data, err = db.Get(hashKey(blockHashPrefix, hash))
    91  		if err == common.ErrNotFound {
    92  			err = nil
    93  		}
    94  		return
    95  	})
    96  	if len(data) != 8 {
    97  		return nil
    98  	}
    99  	number := binary.BigEndian.Uint64(data)
   100  	return &number
   101  }
   102  
   103  // ReadHeadHeaderHash retrieves the hash of the current canonical head header.
   104  func ReadHeadHeaderHash(db DatabaseReader) common.Hash {
   105  	var data []byte
   106  	Must("get head header hash", func() (err error) {
   107  		data, err = db.Get(headHeaderKey)
   108  		if err == common.ErrNotFound {
   109  			err = nil
   110  		}
   111  		return
   112  	})
   113  	if len(data) == 0 {
   114  		return common.Hash{}
   115  	}
   116  	return common.BytesToHash(data)
   117  }
   118  
   119  // WriteHeadHeaderHash stores the hash of the current canonical head header.
   120  func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) {
   121  	Must("put head header hash", func() error {
   122  		return db.Put(headHeaderKey, hash.Bytes())
   123  	})
   124  }
   125  
   126  // ReadHeadBlockHash retrieves the hash of the current canonical head block.
   127  func ReadHeadBlockHash(db DatabaseReader) common.Hash {
   128  	var data []byte
   129  	Must("get head block hash", func() (err error) {
   130  		data, err = db.Get(headBlockKey)
   131  		if err == common.ErrNotFound {
   132  			err = nil
   133  		}
   134  		return
   135  	})
   136  	if len(data) == 0 {
   137  		return common.Hash{}
   138  	}
   139  	return common.BytesToHash(data)
   140  }
   141  
   142  // WriteHeadBlockHash stores the head block's hash.
   143  func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) {
   144  	Must("put head block hash", func() error {
   145  		return db.Put(headBlockKey, hash.Bytes())
   146  	})
   147  }
   148  
   149  // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
   150  func ReadHeadFastBlockHash(db DatabaseReader) common.Hash {
   151  	var data []byte
   152  	Must("get fast head block hash", func() (err error) {
   153  		data, err = db.Get(headFastBlockKey)
   154  		if err == common.ErrNotFound {
   155  			err = nil
   156  		}
   157  		return
   158  	})
   159  	if len(data) == 0 {
   160  		return common.Hash{}
   161  	}
   162  	return common.BytesToHash(data)
   163  }
   164  
   165  // WriteHeadFastBlockHash stores the hash of the current fast-sync head block.
   166  func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) {
   167  	Must("put fast head block hash", func() error {
   168  		return db.Put(headFastBlockKey, hash.Bytes())
   169  	})
   170  }
   171  
   172  // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow
   173  // reporting correct numbers across restarts.
   174  func ReadFastTrieProgress(db DatabaseReader) uint64 {
   175  	var data []byte
   176  	Must("get fast trie progress", func() (err error) {
   177  		data, err = db.Get(fastTrieProgressKey)
   178  		if err == common.ErrNotFound {
   179  			err = nil
   180  		}
   181  		return
   182  	})
   183  	if len(data) == 0 {
   184  		return 0
   185  	}
   186  	return new(big.Int).SetBytes(data).Uint64()
   187  }
   188  
   189  // WriteFastTrieProgress stores the fast sync trie process counter to support
   190  // retrieving it across restarts.
   191  func WriteFastTrieProgress(db DatabaseWriter, count uint64) {
   192  	Must("put fast trie progress", func() error {
   193  		return db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes())
   194  	})
   195  }
   196  
   197  // ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
   198  func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   199  	var data []byte
   200  	Must("get header", func() (err error) {
   201  		data, err = db.Get(numHashKey(headerPrefix, number, hash))
   202  		if err == common.ErrNotFound {
   203  			err = nil
   204  		}
   205  		return
   206  	})
   207  	return data
   208  }
   209  
   210  // HasHeader verifies the existence of a block header corresponding to the hash.
   211  func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool {
   212  	var has bool
   213  	Must("has header", func() (err error) {
   214  		has, err = db.Has(numHashKey(headerPrefix, number, hash))
   215  		if err == common.ErrNotFound {
   216  			err = nil
   217  		}
   218  		return
   219  	})
   220  	return has
   221  }
   222  
   223  // ReadHeader retrieves the block header corresponding to the hash.
   224  func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header {
   225  	data := ReadHeaderRLP(db, hash, number)
   226  	if len(data) == 0 {
   227  		return nil
   228  	}
   229  	header := new(types.Header)
   230  	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
   231  		log.Error("Invalid block header RLP", "hash", hash, "err", err)
   232  		return nil
   233  	}
   234  	return header
   235  }
   236  
   237  // WriteHeader stores a block header into the database and also stores the hash-
   238  // to-number mapping.
   239  func WriteHeader(global, headerTable common.Putter, header *types.Header) {
   240  	data, err := rlp.EncodeToBytes(header)
   241  	if err != nil {
   242  		log.Crit("Failed to encode header", "err", err)
   243  		return
   244  	}
   245  	hash := header.Hash()
   246  	num := header.Number.Uint64()
   247  	encNum := encodeBlockNumber(num)
   248  	Must("put hash to number mapping", func() error {
   249  		return global.Put(hashKey(blockHashPrefix, hash), encNum)
   250  	})
   251  	Must("put header", func() error {
   252  		return headerTable.Put(numHashKey(headerPrefix, num, hash), data)
   253  	})
   254  }
   255  
   256  // DeleteHeader removes all block header data associated with a hash.
   257  func DeleteHeader(global, headerTable common.Deleter, hash common.Hash, number uint64) {
   258  	Must("delete header", func() error {
   259  		return global.Delete(hashKey(blockHashPrefix, hash))
   260  	})
   261  	Must("delete header hash to number mapping", func() error {
   262  		return headerTable.Delete(numHashKey(headerPrefix, number, hash))
   263  	})
   264  }
   265  
   266  // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
   267  func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue {
   268  	var data []byte
   269  	Must("read body", func() (err error) {
   270  		data, err = db.Get(numHashKey(bodyPrefix, number, hash))
   271  		if err == common.ErrNotFound {
   272  			err = nil
   273  		}
   274  		return
   275  	})
   276  	return data
   277  }
   278  
   279  // WriteBodyRLP stores an RLP encoded block body into the database.
   280  func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
   281  	Must("write body", func() error {
   282  		return db.Put(numHashKey(bodyPrefix, number, hash), rlp)
   283  	})
   284  }
   285  
   286  // HasBody verifies the existence of a block body corresponding to the hash.
   287  func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
   288  	var has bool
   289  	Must("has body", func() (err error) {
   290  		has, err = db.Has(numHashKey(bodyPrefix, number, hash))
   291  		if err == common.ErrNotFound {
   292  			err = nil
   293  		}
   294  		return
   295  	})
   296  	return has
   297  }
   298  
   299  // ReadBody retrieves the block body corresponding to the hash.
   300  func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
   301  	data := ReadBodyRLP(db, hash, number)
   302  	if len(data) == 0 {
   303  		return nil
   304  	}
   305  	body := new(types.Body)
   306  	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
   307  		log.Error("Invalid block body RLP", "hash", hash, "err", err)
   308  		return nil
   309  	}
   310  	return body
   311  }
   312  
   313  // WriteBody stores a block body into the database.
   314  func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) {
   315  	data, err := rlp.EncodeToBytes(body)
   316  	if err != nil {
   317  		log.Crit("Failed to RLP encode body", "err", err)
   318  	}
   319  	WriteBodyRLP(db, hash, number, data)
   320  }
   321  
   322  // DeleteBody removes all block body data associated with a hash.
   323  func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) {
   324  	Must("delete block body", func() error {
   325  		return db.Delete(numHashKey(bodyPrefix, number, hash))
   326  	})
   327  }
   328  
   329  // ReadTd retrieves a block's total difficulty corresponding to the hash.
   330  func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
   331  	var data []byte
   332  	Must("read total difficulty", func() (err error) {
   333  		data, err = db.Get(tdKey(number, hash))
   334  		if err == common.ErrNotFound {
   335  			err = nil
   336  		}
   337  		return
   338  	})
   339  	if len(data) == 0 {
   340  		return nil
   341  	}
   342  	td := new(big.Int)
   343  	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
   344  		log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
   345  		return nil
   346  	}
   347  	return td
   348  }
   349  
   350  // WriteTd stores the total difficulty of a block into the database.
   351  func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
   352  	data, err := rlp.EncodeToBytes(td)
   353  	if err != nil {
   354  		log.Crit("Failed to RLP encode block total difficulty", "err", err)
   355  	}
   356  	Must("put total difficulty", func() error {
   357  		return db.Put(tdKey(number, hash), data)
   358  	})
   359  }
   360  
   361  // DeleteTd removes all block total difficulty data associated with a hash.
   362  func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
   363  	Must("delete total difficulty", func() error {
   364  		return db.Delete(tdKey(number, hash))
   365  	})
   366  }
   367  
   368  // ReadRawReceipts retrieves all the transaction receipts belonging to a block.
   369  // The receipt metadata fields are not guaranteed to be populated, so they
   370  // should not be used. Use ReadReceipts instead if the metadata is needed.
   371  func ReadRawReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts {
   372  	// Retrieve the flattened receipt slice
   373  	var data []byte
   374  	Must("get receipts", func() (err error) {
   375  		data, err = db.Get(numHashKey(blockReceiptsPrefix, number, hash))
   376  		if err == common.ErrNotFound {
   377  			err = nil
   378  		}
   379  		return
   380  	})
   381  	if len(data) == 0 {
   382  		return nil
   383  	}
   384  	// Convert the receipts from their storage form to their internal representation
   385  	var receipts types.ReceiptsForStorage
   386  	if err := rlp.DecodeBytes(data, &receipts); err != nil {
   387  		log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
   388  		return nil
   389  	}
   390  	return types.Receipts(receipts)
   391  }
   392  
   393  // ReadReceipts retrieves all the transaction receipts belonging to a block, including
   394  // its corresponding metadata fields. If it is unable to populate these metadata
   395  // fields then nil is returned.
   396  //
   397  // The current implementation populates these metadata fields by reading the receipts'
   398  // corresponding block body, so if the block body is not found it will return nil even
   399  // if the receipt itself is stored.
   400  func ReadReceipts(db common.Database, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts {
   401  	// We're deriving many fields from the block body, retrieve beside the receipt
   402  	receipts := ReadRawReceipts(db.ReceiptTable(), hash, number)
   403  	if receipts == nil {
   404  		return nil
   405  	}
   406  	body := ReadBody(db.BodyTable(), hash, number)
   407  	if body == nil {
   408  		log.Error("Missing body but have receipt", "hash", hash, "number", number)
   409  		return nil
   410  	}
   411  	if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil {
   412  		log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
   413  		return nil
   414  	}
   415  	return receipts
   416  }
   417  
   418  // WriteReceipts stores all the transaction receipts belonging to a block.
   419  func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   420  	// Convert the receipts into their storage form and serialize them
   421  	bytes, err := rlp.EncodeToBytes((types.ReceiptsForStorage)(receipts))
   422  	if err != nil {
   423  		log.Crit("Failed to encode block receipts", "err", err)
   424  	}
   425  	// Store the flattened receipt slice
   426  	Must("put receipts", func() error {
   427  		return db.Put(numHashKey(blockReceiptsPrefix, number, hash), bytes)
   428  	})
   429  }
   430  
   431  // DeleteReceipts removes all receipt data associated with a block hash.
   432  func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
   433  	Must("delete receipts", func() error {
   434  		return db.Delete(numHashKey(blockReceiptsPrefix, number, hash))
   435  	})
   436  }
   437  
   438  // ReadBlock retrieves an entire block corresponding to the hash, assembling it
   439  // back from the stored header and body. If either the header or body could not
   440  // be retrieved nil is returned.
   441  //
   442  // Note, due to concurrent download of header and block body the header and thus
   443  // canonical hash can be stored in the database but the body data not (yet).
   444  func ReadBlock(db common.Database, hash common.Hash, number uint64) *types.Block {
   445  	header := ReadHeader(db.HeaderTable(), hash, number)
   446  	if header == nil {
   447  		return nil
   448  	}
   449  	body := ReadBody(db.BodyTable(), hash, number)
   450  	if body == nil {
   451  		return nil
   452  	}
   453  	return types.NewBlockWith(header, body)
   454  }
   455  
   456  // WriteBlock serializes a block into the database, header and body separately.
   457  func WriteBlock(db common.Database, block *types.Block) {
   458  	WriteBody(db.BodyTable(), block.Hash(), block.NumberU64(), block.Body())
   459  	WriteHeader(db.GlobalTable(), db.HeaderTable(), block.Header())
   460  }
   461  
   462  // DeleteBlock removes all block data associated with a hash.
   463  func DeleteBlock(db common.Database, hash common.Hash, number uint64) {
   464  	DeleteReceipts(db.ReceiptTable(), hash, number)
   465  	DeleteHeader(db.GlobalTable(), db.HeaderTable(), hash, number)
   466  	DeleteBody(db.BodyTable(), hash, number)
   467  	DeleteTd(db.GlobalTable(), hash, number)
   468  }
   469  
   470  // FindCommonAncestor returns the last common ancestor of two block headers
   471  func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header {
   472  	for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
   473  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   474  		if a == nil {
   475  			return nil
   476  		}
   477  	}
   478  	for an := a.Number.Uint64(); an < b.Number.Uint64(); {
   479  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   480  		if b == nil {
   481  			return nil
   482  		}
   483  	}
   484  	for a.Hash() != b.Hash() {
   485  		a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
   486  		if a == nil {
   487  			return nil
   488  		}
   489  		b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1)
   490  		if b == nil {
   491  			return nil
   492  		}
   493  	}
   494  	return a
   495  }