github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/blockchain/process.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/mit-dci/lit/btcutil"
    11  	"github.com/mit-dci/lit/btcutil/chaincfg/chainhash"
    12  	"github.com/mit-dci/lit/btcutil/database"
    13  )
    14  
    15  // BehaviorFlags is a bitmask defining tweaks to the normal behavior when
    16  // performing chain processing and consensus rules checks.
    17  type BehaviorFlags uint32
    18  
    19  const (
    20  	// BFFastAdd may be set to indicate that several checks can be avoided
    21  	// for the block since it is already known to fit into the chain due to
    22  	// already proving it correct links into the chain up to a known
    23  	// checkpoint.  This is primarily used for headers-first mode.
    24  	BFFastAdd BehaviorFlags = 1 << iota
    25  
    26  	// BFNoPoWCheck may be set to indicate the proof of work check which
    27  	// ensures a block hashes to a value less than the required target will
    28  	// not be performed.
    29  	BFNoPoWCheck
    30  
    31  	// BFDryRun may be set to indicate the block should not modify the chain
    32  	// or memory chain index.  This is useful to test that a block is valid
    33  	// without modifying the current state.
    34  	BFDryRun
    35  
    36  	// BFNone is a convenience value to specifically indicate no flags.
    37  	BFNone BehaviorFlags = 0
    38  )
    39  
    40  // blockExists determines whether a block with the given hash exists either in
    41  // the main chain or any side chains.
    42  //
    43  // This function MUST be called with the chain state lock held (for reads).
    44  func (b *BlockChain) blockExists(hash *chainhash.Hash) (bool, error) {
    45  	// Check memory chain first (could be main chain or side chain blocks).
    46  	if _, ok := b.index[*hash]; ok {
    47  		return true, nil
    48  	}
    49  
    50  	// Check in the database.
    51  	var exists bool
    52  	err := b.db.View(func(dbTx database.Tx) error {
    53  		var err error
    54  		exists, err = dbTx.HasBlock(hash)
    55  		return err
    56  	})
    57  	return exists, err
    58  }
    59  
    60  // processOrphans determines if there are any orphans which depend on the passed
    61  // block hash (they are no longer orphans if true) and potentially accepts them.
    62  // It repeats the process for the newly accepted blocks (to detect further
    63  // orphans which may no longer be orphans) until there are no more.
    64  //
    65  // The flags do not modify the behavior of this function directly, however they
    66  // are needed to pass along to maybeAcceptBlock.
    67  //
    68  // This function MUST be called with the chain state lock held (for writes).
    69  func (b *BlockChain) processOrphans(hash *chainhash.Hash, flags BehaviorFlags) error {
    70  	// Start with processing at least the passed hash.  Leave a little room
    71  	// for additional orphan blocks that need to be processed without
    72  	// needing to grow the array in the common case.
    73  	processHashes := make([]*chainhash.Hash, 0, 10)
    74  	processHashes = append(processHashes, hash)
    75  	for len(processHashes) > 0 {
    76  		// Pop the first hash to process from the slice.
    77  		processHash := processHashes[0]
    78  		processHashes[0] = nil // Prevent GC leak.
    79  		processHashes = processHashes[1:]
    80  
    81  		// Look up all orphans that are parented by the block we just
    82  		// accepted.  This will typically only be one, but it could
    83  		// be multiple if multiple blocks are mined and broadcast
    84  		// around the same time.  The one with the most proof of work
    85  		// will eventually win out.  An indexing for loop is
    86  		// intentionally used over a range here as range does not
    87  		// reevaluate the slice on each iteration nor does it adjust the
    88  		// index for the modified slice.
    89  		for i := 0; i < len(b.prevOrphans[*processHash]); i++ {
    90  			orphan := b.prevOrphans[*processHash][i]
    91  			if orphan == nil {
    92  				continue
    93  			}
    94  
    95  			// Remove the orphan from the orphan pool.
    96  			orphanHash := orphan.block.Hash()
    97  			b.removeOrphanBlock(orphan)
    98  			i--
    99  
   100  			// Potentially accept the block into the block chain.
   101  			_, err := b.maybeAcceptBlock(orphan.block, flags)
   102  			if err != nil {
   103  				return err
   104  			}
   105  
   106  			// Add this block to the list of blocks to process so
   107  			// any orphan blocks that depend on this block are
   108  			// handled too.
   109  			processHashes = append(processHashes, orphanHash)
   110  		}
   111  	}
   112  	return nil
   113  }
   114  
   115  // ProcessBlock is the main workhorse for handling insertion of new blocks into
   116  // the block chain.  It includes functionality such as rejecting duplicate
   117  // blocks, ensuring blocks follow all rules, orphan handling, and insertion into
   118  // the block chain along with best chain selection and reorganization.
   119  //
   120  // When no errors occurred during processing, the first return value indicates
   121  // whether or not the block is on the main chain and the second indicates
   122  // whether or not the block is an orphan.
   123  //
   124  // This function is safe for concurrent access.
   125  func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bool, bool, error) {
   126  	b.chainLock.Lock()
   127  	defer b.chainLock.Unlock()
   128  
   129  	fastAdd := flags&BFFastAdd == BFFastAdd
   130  	dryRun := flags&BFDryRun == BFDryRun
   131  
   132  	blockHash := block.Hash()
   133  
   134  	// The block must not already exist in the main chain or side chains.
   135  	exists, err := b.blockExists(blockHash)
   136  	if err != nil {
   137  		return false, false, err
   138  	}
   139  	if exists {
   140  		str := fmt.Sprintf("already have block %v", blockHash)
   141  		return false, false, ruleError(ErrDuplicateBlock, str)
   142  	}
   143  
   144  	// The block must not already exist as an orphan.
   145  	if _, exists := b.orphans[*blockHash]; exists {
   146  		str := fmt.Sprintf("already have block (orphan) %v", blockHash)
   147  		return false, false, ruleError(ErrDuplicateBlock, str)
   148  	}
   149  
   150  	// Perform preliminary sanity checks on the block and its transactions.
   151  	err = checkBlockSanity(block, b.chainParams.PowLimit, b.timeSource, flags)
   152  	if err != nil {
   153  		return false, false, err
   154  	}
   155  
   156  	// Find the previous checkpoint and perform some additional checks based
   157  	// on the checkpoint.  This provides a few nice properties such as
   158  	// preventing old side chain blocks before the last checkpoint,
   159  	// rejecting easy to mine, but otherwise bogus, blocks that could be
   160  	// used to eat memory, and ensuring expected (versus claimed) proof of
   161  	// work requirements since the previous checkpoint are met.
   162  	blockHeader := &block.MsgBlock().Header
   163  	checkpointBlock, err := b.findPreviousCheckpoint()
   164  	if err != nil {
   165  		return false, false, err
   166  	}
   167  	if checkpointBlock != nil {
   168  		// Ensure the block timestamp is after the checkpoint timestamp.
   169  		checkpointHeader := &checkpointBlock.MsgBlock().Header
   170  		checkpointTime := checkpointHeader.Timestamp
   171  		if blockHeader.Timestamp.Before(checkpointTime) {
   172  			str := fmt.Sprintf("block %v has timestamp %v before "+
   173  				"last checkpoint timestamp %v", blockHash,
   174  				blockHeader.Timestamp, checkpointTime)
   175  			return false, false, ruleError(ErrCheckpointTimeTooOld, str)
   176  		}
   177  		if !fastAdd {
   178  			// Even though the checks prior to now have already ensured the
   179  			// proof of work exceeds the claimed amount, the claimed amount
   180  			// is a field in the block header which could be forged.  This
   181  			// check ensures the proof of work is at least the minimum
   182  			// expected based on elapsed time since the last checkpoint and
   183  			// maximum adjustment allowed by the retarget rules.
   184  			duration := blockHeader.Timestamp.Sub(checkpointTime)
   185  			requiredTarget := CompactToBig(b.calcEasiestDifficulty(
   186  				checkpointHeader.Bits, duration))
   187  			currentTarget := CompactToBig(blockHeader.Bits)
   188  			if currentTarget.Cmp(requiredTarget) > 0 {
   189  				str := fmt.Sprintf("block target difficulty of %064x "+
   190  					"is too low when compared to the previous "+
   191  					"checkpoint", currentTarget)
   192  				return false, false, ruleError(ErrDifficultyTooLow, str)
   193  			}
   194  		}
   195  	}
   196  
   197  	// Handle orphan blocks.
   198  	prevHash := &blockHeader.PrevBlock
   199  	prevHashExists, err := b.blockExists(prevHash)
   200  	if err != nil {
   201  		return false, false, err
   202  	}
   203  	if !prevHashExists {
   204  		if !dryRun {
   205  			b.addOrphanBlock(block)
   206  		}
   207  
   208  		return false, true, nil
   209  	}
   210  
   211  	// The block has passed all context independent checks and appears sane
   212  	// enough to potentially accept it into the block chain.
   213  	isMainChain, err := b.maybeAcceptBlock(block, flags)
   214  	if err != nil {
   215  		return false, false, err
   216  	}
   217  
   218  	// Don't process any orphans or log when the dry run flag is set.
   219  	if !dryRun {
   220  		// Accept any orphan blocks that depend on this block (they are
   221  		// no longer orphans) and repeat for those accepted blocks until
   222  		// there are no more.
   223  		err := b.processOrphans(blockHash, flags)
   224  		if err != nil {
   225  			return false, false, err
   226  		}
   227  
   228  	}
   229  
   230  	return isMainChain, false, nil
   231  }