Skip to content

Commit e895611

Browse files
committed
refactor(chain): use BlockTree as header chain implementation
1 parent 878a077 commit e895611

12 files changed

Lines changed: 355 additions & 1045 deletions

File tree

src/chain/chain.rs

Lines changed: 201 additions & 494 deletions
Large diffs are not rendered by default.

src/chain/error.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub(crate) enum HeaderSyncError {
1313
MiscalculatedDifficulty,
1414
InvalidBits,
1515
FloatingHeaders,
16-
LessWorkFork,
1716
DbError,
1817
}
1918

@@ -43,9 +42,6 @@ impl Display for HeaderSyncError {
4342
f,
4443
"the peer sent us a chain that does not connect to any header of ours."
4544
),
46-
HeaderSyncError::LessWorkFork => {
47-
write!(f, "a peer sent us a fork with less work than our chain.")
48-
}
4945
HeaderSyncError::DbError => write!(f, "the database could not load a fork."),
5046
HeaderSyncError::InvalidBits => write!(
5147
f,

src/chain/graph.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use bitcoin::{
99

1010
use super::IndexedHeader;
1111

12+
const LOCATOR_INDEX: &[u32] = &[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
13+
1214
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
1315
pub(crate) struct Height(u32);
1416

@@ -28,7 +30,8 @@ impl Height {
2830
Self(self.0 + 1)
2931
}
3032

31-
fn checked_sub(&self, other: Height) -> Option<Self> {
33+
fn checked_sub(&self, other: impl Into<Height>) -> Option<Self> {
34+
let other = other.into();
3235
let height_sub_checked = self.0.checked_sub(other.0);
3336
height_sub_checked.map(Self)
3437
}
@@ -132,7 +135,7 @@ pub struct BlockTree {
132135

133136
#[allow(unused)]
134137
impl BlockTree {
135-
pub fn new(tip: impl Into<Tip>, network: Network) -> Self {
138+
pub(crate) fn new(tip: impl Into<Tip>, network: Network) -> Self {
136139
let tip = tip.into();
137140
Self {
138141
canonical_hashes: BTreeMap::new(),
@@ -143,7 +146,7 @@ impl BlockTree {
143146
}
144147
}
145148

146-
pub fn from_genesis(network: Network) -> Self {
149+
pub(crate) fn from_genesis(network: Network) -> Self {
147150
let genesis = genesis_block(network);
148151
let height = Height::new(0);
149152
let hash = genesis.block_hash();
@@ -164,7 +167,7 @@ impl BlockTree {
164167
}
165168
}
166169

167-
pub fn from_header(height: impl Into<Height>, header: Header, network: Network) -> Self {
170+
pub(crate) fn from_header(height: impl Into<Height>, header: Header, network: Network) -> Self {
168171
let height = height.into();
169172
let hash = header.block_hash();
170173
let tip = Tip {
@@ -184,7 +187,7 @@ impl BlockTree {
184187
}
185188
}
186189

187-
fn accept_header(&mut self, new_header: Header) -> AcceptHeaderChanges {
190+
pub(crate) fn accept_header(&mut self, new_header: Header) -> AcceptHeaderChanges {
188191
let new_hash = new_header.block_hash();
189192
let prev_hash = new_header.prev_blockhash;
190193

@@ -391,6 +394,9 @@ impl BlockTree {
391394

392395
pub(crate) fn block_hash_at_height(&self, height: impl Into<Height>) -> Option<BlockHash> {
393396
let height = height.into();
397+
if self.active_tip.height.eq(&height) {
398+
return Some(self.active_tip.hash);
399+
}
394400
self.canonical_hashes.get(&height).copied()
395401
}
396402

@@ -408,6 +414,14 @@ impl BlockTree {
408414
self.active_tip.height.to_u32()
409415
}
410416

417+
pub(crate) fn contains(&self, hash: BlockHash) -> bool {
418+
self.headers.contains_key(&hash) || self.active_tip.hash.eq(&hash)
419+
}
420+
421+
pub(crate) fn tip_hash(&self) -> BlockHash {
422+
self.active_tip.hash
423+
}
424+
411425
pub(crate) fn filter_hash(&self, block_hash: BlockHash) -> Option<FilterHash> {
412426
self.headers.get(&block_hash)?.filter_hash
413427
}
@@ -418,6 +432,26 @@ impl BlockTree {
418432
self.headers.get(hash)?.filter_hash
419433
}
420434

435+
pub(crate) fn locators(&self) -> Vec<BlockHash> {
436+
let mut locators = Vec::new();
437+
locators.push(self.active_tip.hash);
438+
for locator in LOCATOR_INDEX {
439+
let height = self.active_tip.height.checked_sub(*locator);
440+
match height {
441+
Some(height) => match self.block_hash_at_height(height) {
442+
Some(hash) => locators.push(hash),
443+
None => return locators.into_iter().rev().collect(),
444+
},
445+
None => return locators.into_iter().rev().collect(),
446+
}
447+
}
448+
locators.into_iter().rev().collect()
449+
}
450+
451+
pub(crate) fn internally_cached_headers(&self) -> usize {
452+
self.headers.len()
453+
}
454+
421455
pub(crate) fn iter(&self) -> BlockTreeIterator {
422456
BlockTreeIterator {
423457
block_tree: self,

src/chain/header_batch.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::ops::RangeFrom;
2-
31
use bitcoin::{block::Header, params::Params, Target};
42

53
use crate::impl_sourceless_error;
@@ -64,18 +62,6 @@ impl HeadersBatch {
6462
.expect("headers have at least one element by construction")
6563
}
6664

67-
pub(crate) fn len(&self) -> usize {
68-
self.batch.len()
69-
}
70-
71-
pub(crate) fn get(&self, index: usize) -> Option<&Header> {
72-
self.batch.get(index)
73-
}
74-
75-
pub(crate) fn get_slice(&self, index: RangeFrom<usize>) -> Option<&[Header]> {
76-
self.batch.get(index)
77-
}
78-
7965
pub(crate) fn inner(&self) -> &[Header] {
8066
&self.batch
8167
}

0 commit comments

Comments
 (0)