muta_protocol/codec/
epoch.rs

1use std::convert::TryFrom;
2
3use bytes::Bytes;
4use prost::Message;
5
6use crate::{
7    codec::{
8        primitive::{Address, Hash},
9        CodecError, ProtocolCodecSync,
10    },
11    field, impl_default_bytes_codec_for,
12    types::primitive as protocol_primitive,
13    types::Bloom,
14    ProtocolError, ProtocolResult,
15};
16
17// #####################
18// Protobuf
19// #####################
20
21#[derive(Clone, Message)]
22pub struct Epoch {
23    #[prost(message, tag = "1")]
24    pub header: Option<EpochHeader>,
25
26    #[prost(message, repeated, tag = "2")]
27    pub ordered_tx_hashes: Vec<Hash>,
28}
29
30#[derive(Clone, Message)]
31pub struct EpochHeader {
32    #[prost(message, tag = "1")]
33    pub chain_id: Option<Hash>,
34
35    #[prost(uint64, tag = "2")]
36    pub epoch_id: u64,
37
38    #[prost(message, tag = "3")]
39    pub pre_hash: Option<Hash>,
40
41    #[prost(uint64, tag = "4")]
42    pub timestamp: u64,
43
44    #[prost(message, repeated, tag = "5")]
45    pub logs_bloom: Vec<Vec<u8>>,
46
47    #[prost(message, tag = "6")]
48    pub order_root: Option<Hash>,
49
50    #[prost(message, repeated, tag = "7")]
51    pub confirm_root: Vec<Hash>,
52
53    #[prost(message, tag = "8")]
54    pub state_root: Option<Hash>,
55
56    #[prost(message, repeated, tag = "9")]
57    pub receipt_root: Vec<Hash>,
58
59    #[prost(message, repeated, tag = "10")]
60    pub cycles_used: Vec<u64>,
61
62    #[prost(message, tag = "11")]
63    pub proposer: Option<Address>,
64
65    #[prost(message, tag = "12")]
66    pub proof: Option<Proof>,
67
68    #[prost(uint64, tag = "13")]
69    pub validator_version: u64,
70
71    #[prost(message, repeated, tag = "14")]
72    pub validators: Vec<Validator>,
73
74    #[prost(uint64, tag = "15")]
75    pub exec_epoch_id: u64,
76}
77
78#[derive(Clone, Message)]
79pub struct Proof {
80    #[prost(uint64, tag = "1")]
81    pub epoch_id: u64,
82
83    #[prost(uint64, tag = "2")]
84    pub round: u64,
85
86    #[prost(message, tag = "3")]
87    pub epoch_hash: Option<Hash>,
88
89    #[prost(bytes, tag = "4")]
90    pub signature: Vec<u8>,
91
92    #[prost(bytes, tag = "5")]
93    pub bitmap: Vec<u8>,
94}
95
96#[derive(Clone, Message)]
97pub struct Validator {
98    #[prost(message, tag = "1")]
99    pub address: Option<Address>,
100
101    #[prost(uint32, tag = "2")]
102    pub propose_weight: u32,
103
104    #[prost(uint32, tag = "3")]
105    pub vote_weight: u32,
106}
107
108#[derive(Clone, Message)]
109pub struct Pill {
110    #[prost(message, tag = "1")]
111    pub epoch: Option<Epoch>,
112
113    #[prost(message, repeated, tag = "2")]
114    pub propose_hashes: Vec<Hash>,
115}
116
117// #################
118// Conversion
119// #################
120
121// Epoch
122
123impl From<epoch::Epoch> for Epoch {
124    fn from(epoch: epoch::Epoch) -> Epoch {
125        let header = Some(EpochHeader::from(epoch.header));
126        let ordered_tx_hashes = epoch
127            .ordered_tx_hashes
128            .into_iter()
129            .map(Hash::from)
130            .collect::<Vec<_>>();
131
132        Epoch {
133            header,
134            ordered_tx_hashes,
135        }
136    }
137}
138
139impl TryFrom<Epoch> for epoch::Epoch {
140    type Error = ProtocolError;
141
142    fn try_from(epoch: Epoch) -> Result<epoch::Epoch, Self::Error> {
143        let header = field!(epoch.header, "Epoch", "header")?;
144
145        let mut ordered_tx_hashes = Vec::new();
146        for hash in epoch.ordered_tx_hashes {
147            ordered_tx_hashes.push(protocol_primitive::Hash::try_from(hash)?);
148        }
149
150        let epoch = epoch::Epoch {
151            header: epoch::EpochHeader::try_from(header)?,
152            ordered_tx_hashes,
153        };
154
155        Ok(epoch)
156    }
157}
158
159// EpochHeader
160
161impl From<epoch::EpochHeader> for EpochHeader {
162    fn from(epoch_header: epoch::EpochHeader) -> EpochHeader {
163        let chain_id = Some(Hash::from(epoch_header.chain_id));
164        let pre_hash = Some(Hash::from(epoch_header.pre_hash));
165        let order_root = Some(Hash::from(epoch_header.order_root));
166        let state_root = Some(Hash::from(epoch_header.state_root));
167        let proposer = Some(Address::from(epoch_header.proposer));
168        let proof = Some(Proof::from(epoch_header.proof));
169
170        let logs_bloom = epoch_header
171            .logs_bloom
172            .into_iter()
173            .map(|bloom| bloom.as_bytes().to_vec())
174            .collect::<Vec<_>>();
175        let confirm_root = epoch_header
176            .confirm_root
177            .into_iter()
178            .map(Hash::from)
179            .collect::<Vec<_>>();
180        let receipt_root = epoch_header
181            .receipt_root
182            .into_iter()
183            .map(Hash::from)
184            .collect::<Vec<_>>();
185        let validators = epoch_header
186            .validators
187            .into_iter()
188            .map(Validator::from)
189            .collect::<Vec<_>>();
190
191        EpochHeader {
192            chain_id,
193            epoch_id: epoch_header.epoch_id,
194            exec_epoch_id: epoch_header.exec_epoch_id,
195            pre_hash,
196            timestamp: epoch_header.timestamp,
197            logs_bloom,
198            order_root,
199            confirm_root,
200            state_root,
201            receipt_root,
202            cycles_used: epoch_header.cycles_used,
203            proposer,
204            proof,
205            validator_version: epoch_header.validator_version,
206            validators,
207        }
208    }
209}
210
211impl TryFrom<EpochHeader> for epoch::EpochHeader {
212    type Error = ProtocolError;
213
214    fn try_from(epoch_header: EpochHeader) -> Result<epoch::EpochHeader, Self::Error> {
215        let chain_id = field!(epoch_header.chain_id, "EpochHeader", "chain_id")?;
216        let pre_hash = field!(epoch_header.pre_hash, "EpochHeader", "pre_hash")?;
217        let order_root = field!(epoch_header.order_root, "EpochHeader", "order_root")?;
218        let state_root = field!(epoch_header.state_root, "EpochHeader", "state_root")?;
219        let proposer = field!(epoch_header.proposer, "EpochHeader", "proposer")?;
220        let proof = field!(epoch_header.proof, "EpochHeader", "proof")?;
221
222        let mut logs_bloom = Vec::new();
223        for bloom in epoch_header.logs_bloom {
224            logs_bloom.push(Bloom::from_slice(&bloom));
225        }
226
227        let mut confirm_root = Vec::new();
228        for root in epoch_header.confirm_root {
229            confirm_root.push(protocol_primitive::Hash::try_from(root)?);
230        }
231
232        let mut receipt_root = Vec::new();
233        for root in epoch_header.receipt_root {
234            receipt_root.push(protocol_primitive::Hash::try_from(root)?);
235        }
236
237        let mut validators = Vec::new();
238        for validator in epoch_header.validators {
239            validators.push(epoch::Validator::try_from(validator)?);
240        }
241
242        let proof = epoch::EpochHeader {
243            chain_id: protocol_primitive::Hash::try_from(chain_id)?,
244            epoch_id: epoch_header.epoch_id,
245            exec_epoch_id: epoch_header.exec_epoch_id,
246            pre_hash: protocol_primitive::Hash::try_from(pre_hash)?,
247            timestamp: epoch_header.timestamp,
248            logs_bloom,
249            order_root: protocol_primitive::Hash::try_from(order_root)?,
250            confirm_root,
251            state_root: protocol_primitive::Hash::try_from(state_root)?,
252            receipt_root,
253            cycles_used: epoch_header.cycles_used,
254            proposer: protocol_primitive::Address::try_from(proposer)?,
255            proof: epoch::Proof::try_from(proof)?,
256            validator_version: epoch_header.validator_version,
257            validators,
258        };
259
260        Ok(proof)
261    }
262}
263
264// Proof
265
266impl From<epoch::Proof> for Proof {
267    fn from(proof: epoch::Proof) -> Proof {
268        let epoch_hash = Some(Hash::from(proof.epoch_hash));
269
270        Proof {
271            epoch_id: proof.epoch_id,
272            round: proof.round,
273            epoch_hash,
274            signature: proof.signature.to_vec(),
275            bitmap: proof.bitmap.to_vec(),
276        }
277    }
278}
279
280impl TryFrom<Proof> for epoch::Proof {
281    type Error = ProtocolError;
282
283    fn try_from(proof: Proof) -> Result<epoch::Proof, Self::Error> {
284        let epoch_hash = field!(proof.epoch_hash, "Proof", "epoch_hash")?;
285
286        let proof = epoch::Proof {
287            epoch_id:   proof.epoch_id,
288            round:      proof.round,
289            epoch_hash: protocol_primitive::Hash::try_from(epoch_hash)?,
290            signature:  Bytes::from(proof.signature),
291            bitmap:     Bytes::from(proof.bitmap),
292        };
293
294        Ok(proof)
295    }
296}
297
298// Validator
299
300impl From<epoch::Validator> for Validator {
301    fn from(validator: epoch::Validator) -> Validator {
302        let address = Some(Address::from(validator.address));
303
304        Validator {
305            address,
306            propose_weight: u32::from(validator.propose_weight),
307            vote_weight: u32::from(validator.vote_weight),
308        }
309    }
310}
311
312impl TryFrom<Validator> for epoch::Validator {
313    type Error = ProtocolError;
314
315    fn try_from(validator: Validator) -> Result<epoch::Validator, Self::Error> {
316        let address = field!(validator.address, "Validator", "address")?;
317
318        let validator = epoch::Validator {
319            address:        protocol_primitive::Address::try_from(address)?,
320            propose_weight: validator.propose_weight as u8,
321            vote_weight:    validator.vote_weight as u8,
322        };
323
324        Ok(validator)
325    }
326}
327
328// Pill
329
330impl From<epoch::Pill> for Pill {
331    fn from(pill: epoch::Pill) -> Pill {
332        let epoch = Some(Epoch::from(pill.epoch));
333        let propose_hashes = pill
334            .propose_hashes
335            .into_iter()
336            .map(Hash::from)
337            .collect::<Vec<_>>();
338
339        Pill {
340            epoch,
341            propose_hashes,
342        }
343    }
344}
345
346impl TryFrom<Pill> for epoch::Pill {
347    type Error = ProtocolError;
348
349    fn try_from(pill: Pill) -> Result<epoch::Pill, Self::Error> {
350        let epoch = field!(pill.epoch, "Pill", "epoch")?;
351
352        let mut propose_hashes = Vec::new();
353        for hash in pill.propose_hashes {
354            propose_hashes.push(protocol_primitive::Hash::try_from(hash)?);
355        }
356
357        let pill = epoch::Pill {
358            epoch: epoch::Epoch::try_from(epoch)?,
359            propose_hashes,
360        };
361
362        Ok(pill)
363    }
364}
365
366// #################
367// Codec
368// #################
369
370impl_default_bytes_codec_for!(epoch, [Epoch, EpochHeader, Proof, Validator, Pill]);
371
372#[cfg(test)]
373mod test {
374    #[test]
375    fn test_u8_convert_u32() {
376        for i in u8::min_value()..u8::max_value() {
377            let j = u32::from(i);
378            assert_eq!(i, (j as u8));
379        }
380    }
381}