Skip to content

Commit 3fbb7d4

Browse files
committed
refactor(chain): use BlockTree as header chain implementation
1 parent ea94b48 commit 3fbb7d4

File tree

12 files changed

+347
-1065
lines changed

12 files changed

+347
-1065
lines changed

src/chain/chain.rs

Lines changed: 191 additions & 501 deletions
Large diffs are not rendered by default.

src/chain/error.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ pub(crate) enum HeaderSyncError {
88
HeadersNotConnected,
99
InvalidHeaderWork,
1010
InvalidHeaderTimes,
11-
PreCheckpointFork,
1211
InvalidCheckpoint,
1312
MiscalculatedDifficulty,
1413
InvalidBits,
1514
FloatingHeaders,
16-
LessWorkFork,
1715
DbError,
1816
}
1917

@@ -30,9 +28,6 @@ impl Display for HeaderSyncError {
3028
HeaderSyncError::InvalidHeaderTimes => {
3129
write!(f, "one or more headers does not have a valid block time.")
3230
}
33-
HeaderSyncError::PreCheckpointFork => {
34-
write!(f, "the sync peer sent us a discontinuous chain.")
35-
}
3631
HeaderSyncError::InvalidCheckpoint => {
3732
write!(f, "a checkpoint in the chain did not match.")
3833
}
@@ -43,9 +38,6 @@ impl Display for HeaderSyncError {
4338
f,
4439
"the peer sent us a chain that does not connect to any header of ours."
4540
),
46-
HeaderSyncError::LessWorkFork => {
47-
write!(f, "a peer sent us a fork with less work than our chain.")
48-
}
4941
HeaderSyncError::DbError => write!(f, "the database could not load a fork."),
5042
HeaderSyncError::InvalidBits => write!(
5143
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();
@@ -166,7 +169,7 @@ impl BlockTree {
166169
}
167170
}
168171

169-
pub fn from_header(height: impl Into<Height>, header: Header, network: Network) -> Self {
172+
pub(crate) fn from_header(height: impl Into<Height>, header: Header, network: Network) -> Self {
170173
let height = height.into();
171174
let hash = header.block_hash();
172175
let tip = Tip {
@@ -186,7 +189,7 @@ impl BlockTree {
186189
}
187190
}
188191

189-
fn accept_header(&mut self, new_header: Header) -> AcceptHeaderChanges {
192+
pub(crate) fn accept_header(&mut self, new_header: Header) -> AcceptHeaderChanges {
190193
let new_hash = new_header.block_hash();
191194
let prev_hash = new_header.prev_blockhash;
192195

@@ -385,6 +388,9 @@ impl BlockTree {
385388

386389
pub(crate) fn block_hash_at_height(&self, height: impl Into<Height>) -> Option<BlockHash> {
387390
let height = height.into();
391+
if self.active_tip.height.eq(&height) {
392+
return Some(self.active_tip.hash);
393+
}
388394
self.canonical_hashes.get(&height).copied()
389395
}
390396

@@ -402,6 +408,14 @@ impl BlockTree {
402408
self.active_tip.height.to_u32()
403409
}
404410

411+
pub(crate) fn contains(&self, hash: BlockHash) -> bool {
412+
self.headers.contains_key(&hash) || self.active_tip.hash.eq(&hash)
413+
}
414+
415+
pub(crate) fn tip_hash(&self) -> BlockHash {
416+
self.active_tip.hash
417+
}
418+
405419
pub(crate) fn filter_hash(&self, block_hash: BlockHash) -> Option<FilterHash> {
406420
self.headers.get(&block_hash)?.filter_hash
407421
}
@@ -412,6 +426,26 @@ impl BlockTree {
412426
self.headers.get(hash)?.filter_hash
413427
}
414428

429+
pub(crate) fn locators(&self) -> Vec<BlockHash> {
430+
let mut locators = Vec::new();
431+
locators.push(self.active_tip.hash);
432+
for locator in LOCATOR_INDEX {
433+
let height = self.active_tip.height.checked_sub(*locator);
434+
match height {
435+
Some(height) => match self.block_hash_at_height(height) {
436+
Some(hash) => locators.push(hash),
437+
None => return locators.into_iter().rev().collect(),
438+
},
439+
None => return locators.into_iter().rev().collect(),
440+
}
441+
}
442+
locators.into_iter().rev().collect()
443+
}
444+
445+
pub(crate) fn internally_cached_headers(&self) -> usize {
446+
self.headers.len()
447+
}
448+
415449
pub(crate) fn iter(&self) -> BlockTreeIterator {
416450
BlockTreeIterator {
417451
block_tree: self,

src/chain/header_batch.rs

Lines changed: 2 additions & 23 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;
@@ -57,27 +55,8 @@ impl HeadersBatch {
5755
.expect("headers have at least one element by construction")
5856
}
5957

60-
// This should connect to the last header we have
61-
pub(crate) fn first(&self) -> &Header {
62-
self.batch
63-
.first()
64-
.expect("headers have at least one element by construction")
65-
}
66-
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-
79-
pub(crate) fn inner(&self) -> &[Header] {
80-
&self.batch
58+
pub(crate) fn into_iter(self) -> impl Iterator<Item = Header> {
59+
self.batch.into_iter()
8160
}
8261
}
8362

0 commit comments

Comments
 (0)