[bdk_chain_redesign] Test LocalChain

This is mostly copying over the relevant tests from `SparseChain`.
Changes are made to `local_chain::ChangeSet` to re-add the ability to
remove blocks.
This commit is contained in:
志宇
2023-04-20 15:29:20 +08:00
parent 7175a82c04
commit 1003fe2ee6
3 changed files with 214 additions and 9 deletions

View File

@@ -62,6 +62,15 @@ impl From<BTreeMap<u32, BlockHash>> for LocalChain {
}
impl LocalChain {
pub fn from_blocks<B>(blocks: B) -> Self
where
B: IntoIterator<Item = BlockId>,
{
Self {
blocks: blocks.into_iter().map(|b| (b.height, b.hash)).collect(),
}
}
pub fn tip(&self) -> Option<BlockId> {
self.blocks
.iter()
@@ -109,19 +118,37 @@ impl LocalChain {
}
}
let mut changeset = BTreeMap::<u32, BlockHash>::new();
for (height, new_hash) in update {
let mut changeset: BTreeMap<u32, Option<BlockHash>> = match invalidate_from_height {
Some(first_invalid_height) => {
// the first block of height to invalidate should be represented in the update
if !update.contains_key(&first_invalid_height) {
return Err(UpdateNotConnectedError(first_invalid_height));
}
self.blocks
.range(first_invalid_height..)
.map(|(height, _)| (*height, None))
.collect()
}
None => BTreeMap::new(),
};
for (height, update_hash) in update {
let original_hash = self.blocks.get(height);
if Some(new_hash) != original_hash {
changeset.insert(*height, *new_hash);
if Some(update_hash) != original_hash {
changeset.insert(*height, Some(*update_hash));
}
}
Ok(changeset)
}
/// Applies the given `changeset`.
pub fn apply_changeset(&mut self, mut changeset: ChangeSet) {
self.blocks.append(&mut changeset)
pub fn apply_changeset(&mut self, changeset: ChangeSet) {
for (height, blockhash) in changeset {
match blockhash {
Some(blockhash) => self.blocks.insert(height, blockhash),
None => self.blocks.remove(&height),
};
}
}
/// Updates [`LocalChain`] with an update [`LocalChain`].
@@ -137,7 +164,10 @@ impl LocalChain {
}
pub fn initial_changeset(&self) -> ChangeSet {
self.blocks.clone()
self.blocks
.iter()
.map(|(&height, &hash)| (height, Some(hash)))
.collect()
}
pub fn heights(&self) -> BTreeSet<u32> {
@@ -148,7 +178,7 @@ impl LocalChain {
/// This is the return value of [`determine_changeset`] and represents changes to [`LocalChain`].
///
/// [`determine_changeset`]: LocalChain::determine_changeset
type ChangeSet = BTreeMap<u32, BlockHash>;
pub type ChangeSet = BTreeMap<u32, Option<BlockHash>>;
impl Append for ChangeSet {
fn append(&mut self, mut other: Self) {
@@ -163,7 +193,7 @@ impl Append for ChangeSet {
/// connect to the existing chain. This error case contains the checkpoint height to include so
/// that the chains can connect.
#[derive(Clone, Debug, PartialEq)]
pub struct UpdateNotConnectedError(u32);
pub struct UpdateNotConnectedError(pub u32);
impl core::fmt::Display for UpdateNotConnectedError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {