snarkos_node_bft/helpers/
signed_proposals.rs1use snarkos_node_sync::locators::NUM_RECENT_BLOCKS;
17use snarkvm::{
18 console::{
19 account::{Address, Signature},
20 network::Network,
21 types::Field,
22 },
23 prelude::{FromBytes, IoResult, Read, ToBytes, Write, error},
24};
25
26use std::{collections::HashMap, ops::Deref};
27
28#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct SignedProposals<N: Network>(pub HashMap<Address<N>, (u64, Field<N>, Signature<N>)>);
32
33impl<N: Network> SignedProposals<N> {
34 pub fn is_valid(&self, expected_signer: Address<N>) -> bool {
36 self.0.iter().all(|(_, (_, _, signature))| signature.to_address() == expected_signer)
37 }
38}
39
40impl<N: Network> ToBytes for SignedProposals<N> {
41 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
42 u32::try_from(self.0.len()).map_err(error)?.write_le(&mut writer)?;
44 for (address, (round, batch_id, signature)) in &self.0 {
46 address.write_le(&mut writer)?;
48 round.write_le(&mut writer)?;
50 batch_id.write_le(&mut writer)?;
52 signature.write_le(&mut writer)?;
54 }
55
56 Ok(())
57 }
58}
59
60impl<N: Network> FromBytes for SignedProposals<N> {
61 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
62 let num_signed_proposals = u32::read_le(&mut reader)?;
64
65 let max_certificates = N::LATEST_MAX_CERTIFICATES();
66 if num_signed_proposals as usize > max_certificates as usize * NUM_RECENT_BLOCKS {
68 return Err(error(format!(
69 "Number of signed proposals ({num_signed_proposals}) is greater than the maximum ({max_certificates} * {NUM_RECENT_BLOCKS})",
70 )));
71 }
72 let mut signed_proposals = HashMap::with_capacity(num_signed_proposals as usize);
74 for _ in 0..num_signed_proposals {
75 let address = FromBytes::read_le(&mut reader)?;
77 let round = FromBytes::read_le(&mut reader)?;
79 let batch_id = FromBytes::read_le(&mut reader)?;
81 let signature = FromBytes::read_le(&mut reader)?;
83 signed_proposals.insert(address, (round, batch_id, signature));
85 }
86
87 Ok(Self(signed_proposals))
88 }
89}
90
91impl<N: Network> Deref for SignedProposals<N> {
92 type Target = HashMap<Address<N>, (u64, Field<N>, Signature<N>)>;
93
94 fn deref(&self) -> &Self::Target {
95 &self.0
96 }
97}
98
99impl<N: Network> Default for SignedProposals<N> {
100 fn default() -> Self {
102 Self(Default::default())
103 }
104}
105
106#[cfg(test)]
107pub(crate) mod tests {
108 use super::*;
109 use snarkvm::{
110 console::{account::PrivateKey, network::MainnetV0},
111 utilities::{TestRng, Uniform},
112 };
113
114 use rand::Rng;
115
116 type CurrentNetwork = MainnetV0;
117
118 const ITERATIONS: usize = 100;
119
120 pub(crate) fn sample_signed_proposals(
121 signer: &PrivateKey<CurrentNetwork>,
122 rng: &mut TestRng,
123 ) -> SignedProposals<CurrentNetwork> {
124 let mut signed_proposals: HashMap<_, _> = Default::default();
125 for _ in 0..CurrentNetwork::LATEST_MAX_CERTIFICATES() {
126 let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
127 let address = Address::try_from(&private_key).unwrap();
128
129 let round = rng.r#gen();
131 let batch_id = Field::rand(rng);
132 let signature = signer.sign(&[batch_id], rng).unwrap();
133 signed_proposals.insert(address, (round, batch_id, signature));
134 }
135
136 SignedProposals(signed_proposals)
137 }
138
139 #[test]
140 fn test_bytes() {
141 let rng = &mut TestRng::default();
142 let singer_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
143
144 for _ in 0..ITERATIONS {
145 let expected = sample_signed_proposals(&singer_private_key, rng);
146 let expected_bytes = expected.to_bytes_le().unwrap();
148 assert_eq!(expected, SignedProposals::read_le(&expected_bytes[..]).unwrap());
149 }
150 }
151
152 #[test]
153 fn test_is_valid() {
154 let rng = &mut TestRng::default();
155
156 for _ in 0..ITERATIONS {
157 let singer_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
158 let singer_address = Address::try_from(&singer_private_key).unwrap();
159 let signed_proposals = sample_signed_proposals(&singer_private_key, rng);
160 assert!(signed_proposals.is_valid(singer_address));
162 }
163 }
164}