Skip to content

Commit c5ca040

Browse files
committed
feat: add unit tests for backwards/forwards compatible serialization
1 parent df7c51a commit c5ca040

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

libsigner/src/events.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,8 @@ pub fn get_signers_db_signer_set_message_id(name: &str) -> Option<(u32, u32)> {
627627

628628
#[cfg(test)]
629629
mod tests {
630+
use blockstack_lib::chainstate::nakamoto::NakamotoBlockHeader;
631+
630632
use super::*;
631633

632634
#[test]
@@ -644,4 +646,101 @@ mod tests {
644646
let name = "signer--2";
645647
assert!(get_signers_db_signer_set_message_id(name).is_none());
646648
}
649+
650+
// Older version of BlockProposal to ensure backwards compatibility
651+
652+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
653+
/// BlockProposal sent to signers
654+
pub struct BlockProposalOld {
655+
/// The block itself
656+
pub block: NakamotoBlock,
657+
/// The burn height the block is mined during
658+
pub burn_height: u64,
659+
/// The reward cycle the block is mined during
660+
pub reward_cycle: u64,
661+
}
662+
663+
impl StacksMessageCodec for BlockProposalOld {
664+
fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), CodecError> {
665+
self.block.consensus_serialize(fd)?;
666+
self.burn_height.consensus_serialize(fd)?;
667+
self.reward_cycle.consensus_serialize(fd)?;
668+
Ok(())
669+
}
670+
671+
fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, CodecError> {
672+
let block = NakamotoBlock::consensus_deserialize(fd)?;
673+
let burn_height = u64::consensus_deserialize(fd)?;
674+
let reward_cycle = u64::consensus_deserialize(fd)?;
675+
Ok(BlockProposalOld {
676+
block,
677+
burn_height,
678+
reward_cycle,
679+
})
680+
}
681+
}
682+
683+
#[test]
684+
/// Test that the old version of the code can deserialize the new
685+
/// version without crashing.
686+
fn test_old_deserialization_works() {
687+
let header = NakamotoBlockHeader::empty();
688+
let block = NakamotoBlock {
689+
header,
690+
txs: vec![],
691+
};
692+
let new_block_proposal = BlockProposal {
693+
block: block.clone(),
694+
burn_height: 1,
695+
reward_cycle: 2,
696+
block_proposal_data: BlockProposalData::from_current_version(),
697+
};
698+
let mut bytes = vec![];
699+
new_block_proposal.consensus_serialize(&mut bytes).unwrap();
700+
let old_block_proposal =
701+
BlockProposalOld::consensus_deserialize(&mut bytes.as_slice()).unwrap();
702+
assert_eq!(old_block_proposal.block, block);
703+
assert_eq!(
704+
old_block_proposal.burn_height,
705+
new_block_proposal.burn_height
706+
);
707+
assert_eq!(
708+
old_block_proposal.reward_cycle,
709+
new_block_proposal.reward_cycle
710+
);
711+
// assert_eq!();
712+
}
713+
714+
#[test]
715+
/// Test that the old version of the code can be serialized
716+
/// and then deserialized into the new version.
717+
fn test_old_proposal_can_deserialize() {
718+
let header = NakamotoBlockHeader::empty();
719+
let block = NakamotoBlock {
720+
header,
721+
txs: vec![],
722+
};
723+
let old_block_proposal = BlockProposalOld {
724+
block: block.clone(),
725+
burn_height: 1,
726+
reward_cycle: 2,
727+
};
728+
let mut bytes = vec![];
729+
old_block_proposal.consensus_serialize(&mut bytes).unwrap();
730+
let new_block_proposal =
731+
BlockProposal::consensus_deserialize(&mut bytes.as_slice()).unwrap();
732+
assert_eq!(new_block_proposal.block, block);
733+
assert_eq!(
734+
new_block_proposal.burn_height,
735+
old_block_proposal.burn_height
736+
);
737+
assert_eq!(
738+
new_block_proposal.reward_cycle,
739+
old_block_proposal.reward_cycle
740+
);
741+
assert_eq!(
742+
new_block_proposal.block_proposal_data.server_version,
743+
String::new()
744+
);
745+
}
647746
}

0 commit comments

Comments
 (0)