OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / blockchain / process.go
diff --git a/vendor/github.com/btcsuite/btcd/blockchain/process.go b/vendor/github.com/btcsuite/btcd/blockchain/process.go
deleted file mode 100644 (file)
index fa438a8..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright (c) 2013-2017 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-package blockchain
-
-import (
-       "fmt"
-       "time"
-
-       "github.com/btcsuite/btcd/chaincfg/chainhash"
-       "github.com/btcsuite/btcd/database"
-       "github.com/btcsuite/btcutil"
-)
-
-// BehaviorFlags is a bitmask defining tweaks to the normal behavior when
-// performing chain processing and consensus rules checks.
-type BehaviorFlags uint32
-
-const (
-       // BFFastAdd may be set to indicate that several checks can be avoided
-       // for the block since it is already known to fit into the chain due to
-       // already proving it correct links into the chain up to a known
-       // checkpoint.  This is primarily used for headers-first mode.
-       BFFastAdd BehaviorFlags = 1 << iota
-
-       // BFNoPoWCheck may be set to indicate the proof of work check which
-       // ensures a block hashes to a value less than the required target will
-       // not be performed.
-       BFNoPoWCheck
-
-       // BFDryRun may be set to indicate the block should not modify the chain
-       // or memory chain index.  This is useful to test that a block is valid
-       // without modifying the current state.
-       BFDryRun
-
-       // BFNone is a convenience value to specifically indicate no flags.
-       BFNone BehaviorFlags = 0
-)
-
-// blockExists determines whether a block with the given hash exists either in
-// the main chain or any side chains.
-//
-// This function is safe for concurrent access.
-func (b *BlockChain) blockExists(hash *chainhash.Hash) (bool, error) {
-       // Check block index first (could be main chain or side chain blocks).
-       if b.index.HaveBlock(hash) {
-               return true, nil
-       }
-
-       // Check in the database.
-       var exists bool
-       err := b.db.View(func(dbTx database.Tx) error {
-               var err error
-               exists, err = dbTx.HasBlock(hash)
-               if err != nil || !exists {
-                       return err
-               }
-
-               // Ignore side chain blocks in the database.  This is necessary
-               // because there is not currently any record of the associated
-               // block index data such as its block height, so it's not yet
-               // possible to efficiently load the block and do anything useful
-               // with it.
-               //
-               // Ultimately the entire block index should be serialized
-               // instead of only the current main chain so it can be consulted
-               // directly.
-               _, err = dbFetchHeightByHash(dbTx, hash)
-               if isNotInMainChainErr(err) {
-                       exists = false
-                       return nil
-               }
-               return err
-       })
-       return exists, err
-}
-
-// processOrphans determines if there are any orphans which depend on the passed
-// block hash (they are no longer orphans if true) and potentially accepts them.
-// It repeats the process for the newly accepted blocks (to detect further
-// orphans which may no longer be orphans) until there are no more.
-//
-// The flags do not modify the behavior of this function directly, however they
-// are needed to pass along to maybeAcceptBlock.
-//
-// This function MUST be called with the chain state lock held (for writes).
-func (b *BlockChain) processOrphans(hash *chainhash.Hash, flags BehaviorFlags) error {
-       // Start with processing at least the passed hash.  Leave a little room
-       // for additional orphan blocks that need to be processed without
-       // needing to grow the array in the common case.
-       processHashes := make([]*chainhash.Hash, 0, 10)
-       processHashes = append(processHashes, hash)
-       for len(processHashes) > 0 {
-               // Pop the first hash to process from the slice.
-               processHash := processHashes[0]
-               processHashes[0] = nil // Prevent GC leak.
-               processHashes = processHashes[1:]
-
-               // Look up all orphans that are parented by the block we just
-               // accepted.  This will typically only be one, but it could
-               // be multiple if multiple blocks are mined and broadcast
-               // around the same time.  The one with the most proof of work
-               // will eventually win out.  An indexing for loop is
-               // intentionally used over a range here as range does not
-               // reevaluate the slice on each iteration nor does it adjust the
-               // index for the modified slice.
-               for i := 0; i < len(b.prevOrphans[*processHash]); i++ {
-                       orphan := b.prevOrphans[*processHash][i]
-                       if orphan == nil {
-                               log.Warnf("Found a nil entry at index %d in the "+
-                                       "orphan dependency list for block %v", i,
-                                       processHash)
-                               continue
-                       }
-
-                       // Remove the orphan from the orphan pool.
-                       orphanHash := orphan.block.Hash()
-                       b.removeOrphanBlock(orphan)
-                       i--
-
-                       // Potentially accept the block into the block chain.
-                       _, err := b.maybeAcceptBlock(orphan.block, flags)
-                       if err != nil {
-                               return err
-                       }
-
-                       // Add this block to the list of blocks to process so
-                       // any orphan blocks that depend on this block are
-                       // handled too.
-                       processHashes = append(processHashes, orphanHash)
-               }
-       }
-       return nil
-}
-
-// ProcessBlock is the main workhorse for handling insertion of new blocks into
-// the block chain.  It includes functionality such as rejecting duplicate
-// blocks, ensuring blocks follow all rules, orphan handling, and insertion into
-// the block chain along with best chain selection and reorganization.
-//
-// When no errors occurred during processing, the first return value indicates
-// whether or not the block is on the main chain and the second indicates
-// whether or not the block is an orphan.
-//
-// This function is safe for concurrent access.
-func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bool, bool, error) {
-       b.chainLock.Lock()
-       defer b.chainLock.Unlock()
-
-       fastAdd := flags&BFFastAdd == BFFastAdd
-       dryRun := flags&BFDryRun == BFDryRun
-
-       blockHash := block.Hash()
-       log.Tracef("Processing block %v", blockHash)
-
-       // The block must not already exist in the main chain or side chains.
-       exists, err := b.blockExists(blockHash)
-       if err != nil {
-               return false, false, err
-       }
-       if exists {
-               str := fmt.Sprintf("already have block %v", blockHash)
-               return false, false, ruleError(ErrDuplicateBlock, str)
-       }
-
-       // The block must not already exist as an orphan.
-       if _, exists := b.orphans[*blockHash]; exists {
-               str := fmt.Sprintf("already have block (orphan) %v", blockHash)
-               return false, false, ruleError(ErrDuplicateBlock, str)
-       }
-
-       // Perform preliminary sanity checks on the block and its transactions.
-       err = checkBlockSanity(block, b.chainParams.PowLimit, b.timeSource, flags)
-       if err != nil {
-               return false, false, err
-       }
-
-       // Find the previous checkpoint and perform some additional checks based
-       // on the checkpoint.  This provides a few nice properties such as
-       // preventing old side chain blocks before the last checkpoint,
-       // rejecting easy to mine, but otherwise bogus, blocks that could be
-       // used to eat memory, and ensuring expected (versus claimed) proof of
-       // work requirements since the previous checkpoint are met.
-       blockHeader := &block.MsgBlock().Header
-       checkpointNode, err := b.findPreviousCheckpoint()
-       if err != nil {
-               return false, false, err
-       }
-       if checkpointNode != nil {
-               // Ensure the block timestamp is after the checkpoint timestamp.
-               checkpointTime := time.Unix(checkpointNode.timestamp, 0)
-               if blockHeader.Timestamp.Before(checkpointTime) {
-                       str := fmt.Sprintf("block %v has timestamp %v before "+
-                               "last checkpoint timestamp %v", blockHash,
-                               blockHeader.Timestamp, checkpointTime)
-                       return false, false, ruleError(ErrCheckpointTimeTooOld, str)
-               }
-               if !fastAdd {
-                       // Even though the checks prior to now have already ensured the
-                       // proof of work exceeds the claimed amount, the claimed amount
-                       // is a field in the block header which could be forged.  This
-                       // check ensures the proof of work is at least the minimum
-                       // expected based on elapsed time since the last checkpoint and
-                       // maximum adjustment allowed by the retarget rules.
-                       duration := blockHeader.Timestamp.Sub(checkpointTime)
-                       requiredTarget := CompactToBig(b.calcEasiestDifficulty(
-                               checkpointNode.bits, duration))
-                       currentTarget := CompactToBig(blockHeader.Bits)
-                       if currentTarget.Cmp(requiredTarget) > 0 {
-                               str := fmt.Sprintf("block target difficulty of %064x "+
-                                       "is too low when compared to the previous "+
-                                       "checkpoint", currentTarget)
-                               return false, false, ruleError(ErrDifficultyTooLow, str)
-                       }
-               }
-       }
-
-       // Handle orphan blocks.
-       prevHash := &blockHeader.PrevBlock
-       prevHashExists, err := b.blockExists(prevHash)
-       if err != nil {
-               return false, false, err
-       }
-       if !prevHashExists {
-               if !dryRun {
-                       log.Infof("Adding orphan block %v with parent %v",
-                               blockHash, prevHash)
-                       b.addOrphanBlock(block)
-               }
-
-               return false, true, nil
-       }
-
-       // The block has passed all context independent checks and appears sane
-       // enough to potentially accept it into the block chain.
-       isMainChain, err := b.maybeAcceptBlock(block, flags)
-       if err != nil {
-               return false, false, err
-       }
-
-       // Don't process any orphans or log when the dry run flag is set.
-       if !dryRun {
-               // Accept any orphan blocks that depend on this block (they are
-               // no longer orphans) and repeat for those accepted blocks until
-               // there are no more.
-               err := b.processOrphans(blockHash, flags)
-               if err != nil {
-                       return false, false, err
-               }
-
-               log.Debugf("Accepted block %v", blockHash)
-       }
-
-       return isMainChain, false, nil
-}