| 187 | } |
| 188 | |
| 189 | ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing, bool segwit_active) |
| 190 | { |
| 191 | if (header.IsNull()) return READ_STATUS_INVALID; |
| 192 | |
| 193 | block = header; |
| 194 | block.vtx.resize(txn_available.size()); |
| 195 | |
| 196 | size_t tx_missing_offset = 0; |
| 197 | for (size_t i = 0; i < txn_available.size(); i++) { |
| 198 | if (!txn_available[i]) { |
| 199 | if (tx_missing_offset >= vtx_missing.size()) { |
| 200 | return READ_STATUS_INVALID; |
| 201 | } |
| 202 | block.vtx[i] = vtx_missing[tx_missing_offset++]; |
| 203 | } else { |
| 204 | block.vtx[i] = std::move(txn_available[i]); |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | // Make sure we can't call FillBlock again. |
| 209 | header.SetNull(); |
| 210 | txn_available.clear(); |
| 211 | |
| 212 | if (vtx_missing.size() != tx_missing_offset) { |
| 213 | return READ_STATUS_INVALID; |
| 214 | } |
| 215 | |
| 216 | // Check for possible mutations early now that we have a seemingly good block |
| 217 | IsBlockMutatedFn check_mutated{m_check_block_mutated_mock ? m_check_block_mutated_mock : IsBlockMutated}; |
| 218 | if (check_mutated(/*block=*/block, /*check_witness_root=*/segwit_active)) { |
| 219 | return READ_STATUS_FAILED; // Possible Short ID collision |
| 220 | } |
| 221 | |
| 222 | if (util::log::ShouldDebugLog(BCLog::CMPCTBLOCK)) { |
| 223 | const uint256 hash{block.GetHash()}; |
| 224 | uint32_t tx_missing_size{0}; |
| 225 | for (const auto& tx : vtx_missing) tx_missing_size += tx->ComputeTotalSize(); |
| 226 | LogDebug(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %u txn prefilled, %u txn from mempool (incl at least %u from extra pool) and %u txn (%u bytes) requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size(), tx_missing_size); |
| 227 | if (vtx_missing.size() < 5) { |
| 228 | for (const auto& tx : vtx_missing) { |
| 229 | LogDebug(BCLog::CMPCTBLOCK, "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString()); |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | return READ_STATUS_OK; |
| 235 | } |