| 2104 | } |
| 2105 | |
| 2106 | bool ProcessBlock(CValidationState &state, CNode *pFrom, CBlock *pBlock, CDiskBlockPos *dbp) { |
| 2107 | int64_t llBeginTime = GetTimeMillis(); |
| 2108 | // LogPrint(BCLog::INFO, "ProcessBlock() enter:%lld\n", llBeginTime); |
| 2109 | AssertLockHeld(cs_main); |
| 2110 | // Check for duplicate |
| 2111 | uint256 blockHash = pBlock->GetHash(); |
| 2112 | uint32_t blockHeight = pBlock->GetHeight(); |
| 2113 | if (mapBlockIndex.count(blockHash)) |
| 2114 | return state.Invalid(ERRORMSG("[%u] block(%s) exists", blockHeight, blockHash.ToString()), 0, "duplicate"); |
| 2115 | |
| 2116 | if (mapOrphanBlocks.count(blockHash)) |
| 2117 | return state.Invalid(ERRORMSG("[%u] (orphan) block(%s) exists", blockHeight, blockHash.ToString()), 0, "duplicate"); |
| 2118 | |
| 2119 | int64_t llBeginCheckBlockTime = GetTimeMillis(); |
| 2120 | auto spCW = std::make_shared<CCacheWrapper>(pCdMan); |
| 2121 | |
| 2122 | // Preliminary checks |
| 2123 | if (!CheckBlock(*pBlock, state, *spCW, false)) { |
| 2124 | LogPrint(BCLog::INFO, "[%d] CheckBlock elapse time: %lld ms\n", chainActive.Height(), |
| 2125 | GetTimeMillis() - llBeginCheckBlockTime); |
| 2126 | |
| 2127 | return ERRORMSG("[%d] CheckBlock FAILED: block#%s", chainActive.Height(), pBlock->GetHash().GetHex()); |
| 2128 | } |
| 2129 | |
| 2130 | // If we don't already have its previous block, shunt it off to holding area until we get it |
| 2131 | if (!pBlock->GetPrevBlockHash().IsNull() && !mapBlockIndex.count(pBlock->GetPrevBlockHash())) { |
| 2132 | if (pBlock->GetHeight() > (uint32_t)nSyncTipHeight) { |
| 2133 | LogPrint(BCLog::DEBUG, "[%d] syncTipHeight=%d\n", pBlock->GetHeight(), nSyncTipHeight); |
| 2134 | nSyncTipHeight = pBlock->GetHeight(); |
| 2135 | } |
| 2136 | |
| 2137 | // Accept orphans as long as there is a node to request its parents from |
| 2138 | if (pFrom) { |
| 2139 | bool success = PruneOrphanBlocks(pBlock->GetHeight()); |
| 2140 | if (success) { |
| 2141 | COrphanBlock *pblock2 = new COrphanBlock(); |
| 2142 | CDataStream ss(SER_DISK, CLIENT_VERSION); |
| 2143 | ss << *pBlock; |
| 2144 | pblock2->vchBlock = vector<uint8_t>(ss.begin(), ss.end()); |
| 2145 | pblock2->blockHash = blockHash; |
| 2146 | pblock2->prevBlockHash = pBlock->GetPrevBlockHash(); |
| 2147 | pblock2->height = pBlock->GetHeight(); |
| 2148 | mapOrphanBlocks.insert(make_pair(blockHash, pblock2)); |
| 2149 | mapOrphanBlocksByPrev.insert(make_pair(pblock2->prevBlockHash, pblock2)); |
| 2150 | setOrphanBlock.insert(pblock2); |
| 2151 | } |
| 2152 | |
| 2153 | // Ask this guy to fill in what we're missing |
| 2154 | LogPrint(BCLog::NET, |
| 2155 | "receive an orphan block height=%d hash=%s, %s it, leading to getblocks (current block height=%d, " |
| 2156 | "current block hash=%s, orphan blocks=%d)\n", |
| 2157 | pBlock->GetHeight(), pBlock->GetHash().GetHex(), success ? "keep" : "abandon", |
| 2158 | chainActive.Height(), chainActive.Tip()->GetBlockHash().GetHex(), mapOrphanBlocksByPrev.size()); |
| 2159 | |
| 2160 | PushGetBlocksOnCondition(pFrom, chainActive.Tip(), GetOrphanRoot(blockHash)); |
| 2161 | } |
| 2162 | return true; |
| 2163 | } |
no test coverage detected