Skip to content

Commit d160549

Browse files
committed
test(chain): Test apply_update with a single CheckPoint<Header>
1 parent 932a77f commit d160549

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

crates/chain/src/local_chain.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,67 @@ where
734734
Ok((new_tip, changeset))
735735
}
736736
}
737+
738+
#[cfg(test)]
739+
mod test {
740+
use super::*;
741+
742+
use alloc::vec::Vec;
743+
use bitcoin::block::Header;
744+
use bitcoin::consensus::encode::deserialize_hex;
745+
use bitcoin::hashes::Hash;
746+
747+
// Test that `apply_update` can connect 1 header at a time
748+
// and fails if the hashes don't line up.
749+
#[test]
750+
fn test_apply_update_single_header() {
751+
let headers: Vec<Header> = [
752+
"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f2002000000",
753+
"0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f1c96cc459dbb0c7bbc722af14f913da868779290ad48ff87ee314ebb8ae08f384b166069ffff7f2001000000",
754+
"0000002078ce518c7dcfd99ad5859c35bd2be15794c0e5dc8e60c1fea3b0461c45da181ca80f828504f88c645ea46cfcf93156269807e3bd409e1317271a1546d238e9b24c166069ffff7f2001000000",
755+
"000000200dfd6c5af6ea3cb341a08db344f93743d94b630d122867faff855f6310e58864e6e0c859fda703d66d051b86f16f09b0cead182f3cbe13767cd91b6371ec252c4c166069ffff7f2000000000",
756+
]
757+
.into_iter()
758+
.map(|s| deserialize_hex::<Header>(s).expect("failed to deserialize header"))
759+
.collect();
760+
761+
let header_0 = headers[0];
762+
let header_1 = headers[1];
763+
let header_2 = headers[2];
764+
let header_3 = headers[3];
765+
766+
let (mut chain, _) = LocalChain::from_genesis(header_0);
767+
768+
// Apply 1 `CheckPoint<Header>` at a time
769+
for (height, header) in (1..).zip([header_1, header_2, header_3]) {
770+
let changeset = chain.apply_update(CheckPoint::new(height, header)).unwrap();
771+
assert_eq!(
772+
changeset,
773+
ChangeSet {
774+
blocks: [(height, Some(headers[height as usize]))].into()
775+
},
776+
);
777+
}
778+
assert_eq!(chain.tip.iter().count(), 4);
779+
for height in 0..4 {
780+
assert!(chain
781+
.get(height)
782+
.is_some_and(|cp| cp.hash() == headers[height as usize].block_hash()))
783+
}
784+
785+
// `apply_update` should error if the hashes don't line up
786+
chain = LocalChain::from_blocks([(0, header_0), (1, header_1)].into()).unwrap();
787+
let mut header_2_alt = header_2;
788+
header_2_alt.prev_blockhash = BlockHash::all_zeros();
789+
let res = chain.apply_update(CheckPoint::new(2, header_2_alt));
790+
assert!(
791+
matches!(
792+
res,
793+
Err(CannotConnectError {
794+
try_include_height: 1
795+
})
796+
),
797+
"`apply_update` failed to detect hash conflict"
798+
);
799+
}
800+
}

0 commit comments

Comments
 (0)