hypercall_blocks/
entry.rs1use crate::BlockLogHeader;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct BlockLogEntry<C> {
10 pub header: BlockLogHeader,
11 pub commands: Vec<C>,
12}
13
14#[cfg(test)]
15mod tests {
16 use super::*;
17
18 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19 struct TestCommand {
20 id: u64,
21 payload: Vec<u8>,
22 }
23
24 #[test]
25 fn block_log_entry_roundtrips_with_commands() {
26 let entry = BlockLogEntry {
27 header: header(2),
28 commands: vec![
29 TestCommand {
30 id: 1,
31 payload: vec![1, 2, 3],
32 },
33 TestCommand {
34 id: 2,
35 payload: vec![4, 5, 6],
36 },
37 ],
38 };
39
40 assert_eq!(msgpack_roundtrip(&entry), entry);
41 }
42
43 #[test]
44 fn block_log_entry_roundtrips_empty_command_batch() {
45 let entry = BlockLogEntry::<TestCommand> {
46 header: header(0),
47 commands: Vec::new(),
48 };
49
50 assert_eq!(msgpack_roundtrip(&entry), entry);
51 }
52
53 #[test]
54 fn block_entry_equality_includes_header_and_commands() {
55 let base = BlockLogEntry {
56 header: header(1),
57 commands: vec![TestCommand {
58 id: 1,
59 payload: vec![1],
60 }],
61 };
62
63 let mut changed_header = base.clone();
64 changed_header.header.batch_seq += 1;
65 assert_ne!(base, changed_header);
66
67 let mut changed_command = base.clone();
68 changed_command.commands[0].payload.push(2);
69 assert_ne!(base, changed_command);
70 }
71
72 fn header(command_count: u64) -> BlockLogHeader {
73 BlockLogHeader {
74 batch_seq: 7,
75 prev_block_hash: [1; 32],
76 commands_hash: [2; 32],
77 batch_root: [3; 32],
78 command_count,
79 first_seq: 42,
80 timestamp: 1_700_000_000,
81 signer: [4; 20],
82 signature: vec![5; 65],
83 }
84 }
85
86 fn msgpack_roundtrip<T>(value: &T) -> T
87 where
88 T: Clone + PartialEq + std::fmt::Debug + Serialize + for<'de> Deserialize<'de>,
89 {
90 let bytes = rmp_serde::to_vec_named(value).expect("serialize block log entry");
91 rmp_serde::from_slice(&bytes).expect("deserialize block log entry")
92 }
93}