Skip to content

Commit ee1060f

Browse files
committed
[bdk_chain_redesign] Simplify LocalChain
Remove the requirement that evicted blocks should have in-best-chain counterparts in the update.
1 parent 611d2e3 commit ee1060f

1 file changed

Lines changed: 34 additions & 51 deletions

File tree

crates/chain/src/local_chain.rs

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
use core::{convert::Infallible, ops::Deref};
22

3-
use alloc::{
4-
collections::{BTreeMap, BTreeSet},
5-
vec::Vec,
6-
};
3+
use alloc::collections::{BTreeMap, BTreeSet};
74
use bitcoin::BlockHash;
85

9-
use crate::{BlockId, ChainOracle};
6+
use crate::{Append, BlockId, ChainOracle};
107

118
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
129
pub struct LocalChain {
@@ -56,6 +53,12 @@ impl From<LocalChain> for BTreeMap<u32, BlockHash> {
5653
}
5754
}
5855

56+
impl From<BTreeMap<u32, BlockHash>> for LocalChain {
57+
fn from(value: BTreeMap<u32, BlockHash>) -> Self {
58+
Self { blocks: value }
59+
}
60+
}
61+
5962
impl LocalChain {
6063
pub fn tip(&self) -> Option<BlockId> {
6164
self.blocks
@@ -66,10 +69,7 @@ impl LocalChain {
6669

6770
/// This is like the sparsechain's logic, expect we must guarantee that all invalidated heights
6871
/// are to be re-filled.
69-
pub fn determine_changeset<U>(&self, update: &U) -> Result<ChangeSet, UpdateError>
70-
where
71-
U: AsRef<BTreeMap<u32, BlockHash>>,
72-
{
72+
pub fn determine_changeset(&self, update: &Self) -> Result<ChangeSet, UpdateNotConnectedError> {
7373
let update = update.as_ref();
7474
let update_tip = match update.keys().last().cloned() {
7575
Some(tip) => tip,
@@ -96,24 +96,9 @@ impl LocalChain {
9696
// the first block of height to invalidate (if any) should be represented in the update
9797
if let Some(first_invalid_height) = invalidate_from_height {
9898
if !update.contains_key(&first_invalid_height) {
99-
return Err(UpdateError::NotConnected(first_invalid_height));
100-
}
101-
}
102-
103-
let invalidated_heights = invalidate_from_height
104-
.into_iter()
105-
.flat_map(|from_height| self.blocks.range(from_height..).map(|(h, _)| h));
106-
107-
// invalidated heights must all exist in the update
108-
let mut missing_heights = Vec::<u32>::new();
109-
for invalidated_height in invalidated_heights {
110-
if !update.contains_key(invalidated_height) {
111-
missing_heights.push(*invalidated_height);
99+
return Err(UpdateNotConnectedError(first_invalid_height));
112100
}
113101
}
114-
if !missing_heights.is_empty() {
115-
return Err(UpdateError::MissingHeightsInUpdate(missing_heights));
116-
}
117102

118103
let mut changeset = BTreeMap::<u32, BlockHash>::new();
119104
for (height, new_hash) in update {
@@ -136,7 +121,7 @@ impl LocalChain {
136121
///
137122
/// [`determine_changeset`]: Self::determine_changeset
138123
/// [`apply_changeset`]: Self::apply_changeset
139-
pub fn apply_update(&mut self, update: Self) -> Result<ChangeSet, UpdateError> {
124+
pub fn apply_update(&mut self, update: Self) -> Result<ChangeSet, UpdateNotConnectedError> {
140125
let changeset = self.determine_changeset(&update)?;
141126
self.apply_changeset(changeset.clone());
142127
Ok(changeset)
@@ -160,7 +145,7 @@ impl LocalChain {
160145
derive(serde::Deserialize, serde::Serialize),
161146
serde(crate = "serde_crate")
162147
)]
163-
pub struct ChangeSet(pub BTreeMap<u32, BlockHash>);
148+
pub struct ChangeSet(pub(crate) BTreeMap<u32, BlockHash>);
164149

165150
impl Deref for ChangeSet {
166151
type Target = BTreeMap<u32, BlockHash>;
@@ -170,32 +155,30 @@ impl Deref for ChangeSet {
170155
}
171156
}
172157

173-
/// Represents an update failure of [`LocalChain`].
174-
#[derive(Clone, Debug, PartialEq)]
175-
pub enum UpdateError {
176-
/// The update cannot be applied to the chain because the chain suffix it represents did not
177-
/// connect to the existing chain. This error case contains the checkpoint height to include so
178-
/// that the chains can connect.
179-
NotConnected(u32),
180-
/// If the update results in displacements of original blocks, the update should include all new
181-
/// block hashes that have displaced the original block hashes. This error case contains the
182-
/// heights of all missing block hashes in the update.
183-
MissingHeightsInUpdate(Vec<u32>),
158+
impl Append for ChangeSet {
159+
fn append(&mut self, mut other: Self) {
160+
BTreeMap::append(&mut self.0, &mut other.0)
161+
}
184162
}
185163

186-
impl core::fmt::Display for UpdateError {
164+
/// Represents an update failure of [`LocalChain`] due to the update not connecting to the original
165+
/// chain.
166+
///
167+
/// The update cannot be applied to the chain because the chain suffix it represents did not
168+
/// connect to the existing chain. This error case contains the checkpoint height to include so
169+
/// that the chains can connect.
170+
#[derive(Clone, Debug, PartialEq)]
171+
pub struct UpdateNotConnectedError(u32);
172+
173+
impl core::fmt::Display for UpdateNotConnectedError {
187174
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
188-
match self {
189-
UpdateError::NotConnected(heights) => write!(
190-
f,
191-
"the update cannot connect with the chain, try include blockhash at height {}",
192-
heights
193-
),
194-
UpdateError::MissingHeightsInUpdate(missing_heights) => write!(
195-
f,
196-
"block hashes of these heights must be included in the update to succeed: {:?}",
197-
missing_heights
198-
),
199-
}
175+
write!(
176+
f,
177+
"the update cannot connect with the chain, try include block at height {}",
178+
self.0
179+
)
200180
}
201181
}
182+
183+
#[cfg(feature = "std")]
184+
impl std::error::Error for UpdateNotConnectedError {}

0 commit comments

Comments
 (0)