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