Skip to content

Commit 194263c

Browse files
authored
Merge pull request #522 from rustaceanrob/11-21-header-ext
Remove `HeadersBatch` for extension trait
2 parents ce67d9c + fc3cc46 commit 194263c

File tree

3 files changed

+52
-97
lines changed

3 files changed

+52
-97
lines changed

src/chain/chain.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@ use super::{
1313
error::{CFHeaderSyncError, CFilterSyncError, HeaderSyncError},
1414
graph::{AcceptHeaderChanges, BlockTree, HeaderRejection},
1515
CFHeaderChanges, ChainState, Filter, FilterCheck, FilterHeaderRequest, FilterRequest,
16-
FilterRequestState, HeightMonitor, PeerId,
16+
FilterRequestState, HeaderValidationExt, HeightMonitor, PeerId,
1717
};
1818
use crate::IndexedFilter;
19-
use crate::{
20-
chain::{header_batch::HeadersBatch, BlockHeaderChanges},
21-
messages::Event,
22-
Dialog, Info, Progress,
23-
};
19+
use crate::{chain::BlockHeaderChanges, messages::Event, Dialog, Info, Progress};
2420

2521
const FILTER_BASIC: u8 = 0x00;
2622
const CF_HEADER_BATCH_SIZE: u32 = 1_999;
@@ -91,11 +87,18 @@ impl Chain {
9187
// Sync the chain with headers from a peer, adjusting to reorgs if needed
9288
pub(crate) fn sync_chain(
9389
&mut self,
94-
message: Vec<Header>,
90+
header_batch: Vec<Header>,
9591
) -> Result<Vec<BlockHash>, HeaderSyncError> {
96-
let header_batch = HeadersBatch::new(message).map_err(|_| HeaderSyncError::EmptyMessage)?;
92+
if header_batch.is_empty() {
93+
return Err(HeaderSyncError::EmptyMessage);
94+
}
9795
// If our chain already has the last header in the message there is no new information
98-
if self.header_chain.contains(header_batch.last().block_hash()) {
96+
if self.header_chain.contains(
97+
header_batch
98+
.last()
99+
.expect("non-empty check above.")
100+
.block_hash(),
101+
) {
99102
return Ok(Vec::new());
100103
}
101104
// We check first if the peer is sending us nonsense
@@ -153,21 +156,16 @@ impl Chain {
153156
}
154157

155158
// These are invariants in all batches of headers we receive
156-
fn sanity_check(&mut self, header_batch: &HeadersBatch) -> Result<(), HeaderSyncError> {
157-
// All the headers connect with each other and is the difficulty adjustment not absurd
159+
fn sanity_check(&mut self, header_batch: &[Header]) -> Result<(), HeaderSyncError> {
158160
if !header_batch.connected() {
159161
return Err(HeaderSyncError::HeadersNotConnected);
160162
}
161-
162-
// All headers pass their own proof of work and the network minimum
163-
if !header_batch.individually_valid_pow() {
163+
if !header_batch.passes_own_pow() {
164164
return Err(HeaderSyncError::InvalidHeaderWork);
165165
}
166-
167-
if !header_batch.bits_adhere_transition(self.network) {
166+
if !header_batch.bits_adhere_transition_threshold(self.network) {
168167
return Err(HeaderSyncError::InvalidBits);
169168
}
170-
171169
Ok(())
172170
}
173171

src/chain/header_batch.rs

Lines changed: 0 additions & 78 deletions
This file was deleted.

src/chain/mod.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub mod checkpoints;
1111
#[allow(dead_code)]
1212
pub(crate) mod error;
1313
pub(crate) mod graph;
14-
pub(crate) mod header_batch;
1514

1615
use std::collections::HashMap;
1716

@@ -20,7 +19,7 @@ use bitcoin::hashes::{sha256d, Hash};
2019
use bitcoin::Amount;
2120
use bitcoin::{
2221
bip158::BlockFilter, block::Header, params::Params, BlockHash, FilterHash, FilterHeader,
23-
ScriptBuf, Work,
22+
ScriptBuf, Target, Work,
2423
};
2524

2625
use crate::network::PeerId;
@@ -284,6 +283,42 @@ impl ZerolikeExt for Work {
284283
}
285284
}
286285

286+
trait HeaderValidationExt {
287+
// Headers are logically connected.
288+
fn connected(&self) -> bool;
289+
// Each header passes its own work target.
290+
fn passes_own_pow(&self) -> bool;
291+
// Targets do not change out of the acceptable range.
292+
fn bits_adhere_transition_threshold(&self, params: impl AsRef<Params>) -> bool;
293+
}
294+
295+
impl HeaderValidationExt for &[Header] {
296+
fn connected(&self) -> bool {
297+
self.iter()
298+
.zip(self.iter().skip(1))
299+
.all(|(first, second)| first.block_hash().eq(&second.prev_blockhash))
300+
}
301+
302+
fn passes_own_pow(&self) -> bool {
303+
!self.iter().any(|header| {
304+
let target = header.target();
305+
let valid_pow = header.validate_pow(target);
306+
valid_pow.is_err()
307+
})
308+
}
309+
310+
fn bits_adhere_transition_threshold(&self, params: impl AsRef<Params>) -> bool {
311+
let params = params.as_ref();
312+
if params.allow_min_difficulty_blocks {
313+
return true;
314+
}
315+
self.iter().zip(self.iter().skip(1)).all(|(first, second)| {
316+
let transition = Target::from_compact(first.bits).max_transition_threshold(params);
317+
Target::from_compact(second.bits).le(&transition)
318+
})
319+
}
320+
}
321+
287322
// Emulation of `GetBlockSubsidy` in Bitcoin Core: https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1944
288323
pub(crate) fn block_subsidy(height: u32) -> Amount {
289324
let halvings = height / SUBSIDY_HALVING_INTERVAL;

0 commit comments

Comments
 (0)