saito_core/core/msg/
ghost_chain_sync.rs

1use crate::core::defs::{PrintForLog, SaitoHash, Timestamp};
2use std::fmt::{Debug, Formatter};
3
4pub struct GhostChainSync {
5    pub start: SaitoHash,
6    pub prehashes: Vec<SaitoHash>,
7    pub previous_block_hashes: Vec<SaitoHash>,
8    pub block_ids: Vec<u64>,
9    pub block_ts: Vec<Timestamp>,
10    pub txs: Vec<bool>,
11    pub gts: Vec<bool>,
12}
13
14impl GhostChainSync {
15    pub fn serialize(&self) -> Vec<u8> {
16        [
17            self.start.as_slice(),
18            (self.prehashes.len() as u32).to_be_bytes().as_slice(),
19            self.prehashes.concat().as_slice(),
20            self.previous_block_hashes.concat().as_slice(),
21            self.block_ids
22                .iter()
23                .map(|id| id.to_be_bytes().to_vec())
24                .collect::<Vec<Vec<u8>>>()
25                .concat()
26                .as_slice(),
27            self.block_ts
28                .iter()
29                .map(|id| id.to_be_bytes().to_vec())
30                .collect::<Vec<Vec<u8>>>()
31                .concat()
32                .as_slice(),
33            self.txs
34                .iter()
35                .map(|id| (*id as u8).to_be_bytes().to_vec())
36                .collect::<Vec<Vec<u8>>>()
37                .concat()
38                .as_slice(),
39            self.gts
40                .iter()
41                .map(|id| (*id as u8).to_be_bytes().to_vec())
42                .collect::<Vec<Vec<u8>>>()
43                .concat()
44                .as_slice(),
45        ]
46        .concat()
47    }
48    pub fn deserialize(buffer: Vec<u8>) -> GhostChainSync {
49        let start: SaitoHash = buffer[0..32].to_vec().try_into().unwrap();
50        let count: usize = u32::from_be_bytes(buffer[32..36].try_into().unwrap()) as usize;
51        let mut prehashes: Vec<SaitoHash> = vec![];
52        let mut previous_block_hashes = vec![];
53        let mut block_ids = vec![];
54        let mut block_ts = vec![];
55        let mut txs = vec![];
56        let mut gts = vec![];
57
58        let buffer = &buffer[36..buffer.len()];
59        let buf = buffer[0..(count * 32)].to_vec();
60        for i in 0..count {
61            prehashes.push(buf[i * 32..(i + 1) * 32].try_into().unwrap());
62        }
63        let buf = buffer[(count * 32)..(count * 64)].to_vec();
64        for i in 0..count {
65            previous_block_hashes.push(buf[i * 32..(i + 1) * 32].try_into().unwrap());
66        }
67        let buf = buffer[(count * 64)..(count * 72)].to_vec();
68        for i in 0..count {
69            block_ids.push(u64::from_be_bytes(
70                buf[i * 8..(i + 1) * 8].try_into().unwrap(),
71            ));
72        }
73        let buf = buffer[(count * 72)..(count * 80)].to_vec();
74        for i in 0..count {
75            block_ts.push(Timestamp::from_be_bytes(
76                buf[i * 8..(i + 1) * 8].try_into().unwrap(),
77            ));
78        }
79        let buf = buffer[(count * 80)..(count * 81)].to_vec();
80        for i in 0..count {
81            txs.push(buf[i] != 0);
82        }
83        let buf = buffer[(count * 81)..(count * 82)].to_vec();
84        for i in 0..count {
85            gts.push(buf[i] != 0);
86        }
87
88        GhostChainSync {
89            start,
90            prehashes,
91            previous_block_hashes,
92            block_ids,
93            block_ts,
94            txs,
95            gts,
96        }
97    }
98}
99
100impl Debug for GhostChainSync {
101    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102        f.debug_struct("GhostChainSync")
103            .field("start", &self.start.to_hex())
104            .field(
105                "prehashes",
106                &self
107                    .prehashes
108                    .iter()
109                    .map(|h| h.to_hex())
110                    .collect::<Vec<String>>(),
111            )
112            .field(
113                "prev_block_hashes",
114                &self
115                    .previous_block_hashes
116                    .iter()
117                    .map(|h| h.to_hex())
118                    .collect::<Vec<String>>(),
119            )
120            .field("block_ids", &self.block_ids)
121            .field("block_ts", &self.block_ts)
122            .field("txs", &self.txs)
123            .field("gts", &self.gts)
124            .finish()
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::core::msg::ghost_chain_sync::GhostChainSync;
131
132    #[test]
133    fn serialize_test() {
134        let chain = GhostChainSync {
135            start: [1; 32],
136            prehashes: vec![[2; 32], [3; 32]],
137            previous_block_hashes: vec![[4; 32], [5; 32]],
138            block_ids: vec![10, 20],
139            block_ts: vec![100, 200],
140            txs: vec![false, true],
141            gts: vec![true, false],
142        };
143        let buffer = chain.serialize();
144        let chain2 = GhostChainSync::deserialize(buffer);
145        assert_eq!(chain.start, chain2.start);
146        assert_eq!(chain.prehashes, chain2.prehashes);
147        assert_eq!(chain.previous_block_hashes, chain2.previous_block_hashes);
148        assert_eq!(chain.block_ids, chain2.block_ids);
149        assert_eq!(chain.block_ts, chain2.block_ts);
150        assert_eq!(chain.txs, chain2.txs);
151        assert_eq!(chain.gts, chain2.gts);
152    }
153}