| 213 | } |
| 214 | |
| 215 | bool HeadersSyncState::ValidateAndStoreRedownloadedHeader(const CBlockHeader& header) |
| 216 | { |
| 217 | Assume(m_download_state == State::REDOWNLOAD); |
| 218 | if (m_download_state != State::REDOWNLOAD) return false; |
| 219 | |
| 220 | int64_t next_height = m_redownload_buffer_last_height + 1; |
| 221 | |
| 222 | // Ensure that we're working on a header that connects to the chain we're |
| 223 | // downloading. |
| 224 | if (header.hashPrevBlock != m_redownload_buffer_last_hash) { |
| 225 | LogDebug(BCLog::NET, "Initial headers sync aborted with peer=%d: non-continuous headers at height=%i (redownload phase)\n", m_id, next_height); |
| 226 | return false; |
| 227 | } |
| 228 | |
| 229 | // Check that the difficulty adjustments are within our tolerance: |
| 230 | uint32_t previous_nBits{0}; |
| 231 | if (!m_redownloaded_headers.empty()) { |
| 232 | previous_nBits = m_redownloaded_headers.back().nBits; |
| 233 | } else { |
| 234 | previous_nBits = m_chain_start.nBits; |
| 235 | } |
| 236 | |
| 237 | if (!PermittedDifficultyTransition(m_consensus_params, next_height, |
| 238 | previous_nBits, header.nBits)) { |
| 239 | LogDebug(BCLog::NET, "Initial headers sync aborted with peer=%d: invalid difficulty transition at height=%i (redownload phase)\n", m_id, next_height); |
| 240 | return false; |
| 241 | } |
| 242 | |
| 243 | // Track work on the redownloaded chain |
| 244 | m_redownload_chain_work += GetBlockProof(header); |
| 245 | |
| 246 | if (m_redownload_chain_work >= m_minimum_required_work) { |
| 247 | m_process_all_remaining_headers = true; |
| 248 | } |
| 249 | |
| 250 | // If we're at a header for which we previously stored a commitment, verify |
| 251 | // it is correct. Failure will result in aborting download. |
| 252 | // Also, don't check commitments once we've gotten to our target blockhash; |
| 253 | // it's possible our peer has extended its chain between our first sync and |
| 254 | // our second, and we don't want to return failure after we've seen our |
| 255 | // target blockhash just because we ran out of commitments. |
| 256 | if (!m_process_all_remaining_headers && next_height % m_params.commitment_period == m_commit_offset) { |
| 257 | if (m_header_commitments.size() == 0) { |
| 258 | LogDebug(BCLog::NET, "Initial headers sync aborted with peer=%d: commitment overrun at height=%i (redownload phase)\n", m_id, next_height); |
| 259 | // Somehow our peer managed to feed us a different chain and |
| 260 | // we've run out of commitments. |
| 261 | return false; |
| 262 | } |
| 263 | bool commitment = m_hasher(header.GetHash()) & 1; |
| 264 | bool expected_commitment = m_header_commitments.front(); |
| 265 | m_header_commitments.pop_front(); |
| 266 | if (commitment != expected_commitment) { |
| 267 | LogDebug(BCLog::NET, "Initial headers sync aborted with peer=%d: commitment mismatch at height=%i (redownload phase)\n", m_id, next_height); |
| 268 | return false; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | // Store this header for later processing. |
nothing calls this directly
no test coverage detected