mithril_stm/proof_system/concatenation/
aggregate_key.rs1use serde::{Deserialize, Serialize};
2
3use crate::{
4 ClosedKeyRegistration, MembershipDigest, RegistrationEntryForConcatenation, Stake, StmResult,
5 membership_commitment::{
6 MerkleBatchPath, MerkleTreeBatchCommitment, MerkleTreeConcatenationLeaf, MerkleTreeError,
7 },
8};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(bound(
13 serialize = "MerkleBatchPath<D::ConcatenationHash>: Serialize",
14 deserialize = "MerkleBatchPath<D::ConcatenationHash>: Deserialize<'de>"
15))]
16pub struct AggregateVerificationKeyForConcatenation<D: MembershipDigest> {
17 mt_commitment: MerkleTreeBatchCommitment<D::ConcatenationHash, MerkleTreeConcatenationLeaf>,
18 total_stake: Stake,
19}
20
21impl<D: MembershipDigest> AggregateVerificationKeyForConcatenation<D> {
22 pub(crate) fn get_merkle_tree_batch_commitment(
24 &self,
25 ) -> MerkleTreeBatchCommitment<D::ConcatenationHash, MerkleTreeConcatenationLeaf> {
26 self.mt_commitment.clone()
27 }
28
29 pub fn get_total_stake(&self) -> Stake {
31 self.total_stake
32 }
33
34 pub fn to_bytes(&self) -> Vec<u8> {
36 let mut bytes = Vec::new();
37 bytes.extend(self.mt_commitment.to_bytes());
38 bytes.extend(self.total_stake.to_be_bytes());
39
40 bytes
41 }
42
43 pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
44 let mut u64_bytes = [0u8; 8];
45 let size = bytes.len();
46
47 u64_bytes.copy_from_slice(&bytes[size - 8..]);
48 let stake = u64::from_be_bytes(u64_bytes);
49 let mt_commitment = MerkleTreeBatchCommitment::from_bytes(
50 bytes.get(..size - 8).ok_or(MerkleTreeError::SerializationError)?,
51 )?;
52 Ok(Self {
53 mt_commitment,
54 total_stake: stake,
55 })
56 }
57}
58
59impl<D: MembershipDigest> PartialEq for AggregateVerificationKeyForConcatenation<D> {
60 fn eq(&self, other: &Self) -> bool {
61 self.mt_commitment == other.mt_commitment && self.total_stake == other.total_stake
62 }
63}
64
65impl<D: MembershipDigest> Eq for AggregateVerificationKeyForConcatenation<D> {}
66
67impl<D: MembershipDigest> From<&ClosedKeyRegistration>
68 for AggregateVerificationKeyForConcatenation<D>
69{
70 fn from(reg: &ClosedKeyRegistration) -> Self {
71 Self {
72 mt_commitment: reg
73 .to_merkle_tree::<D::ConcatenationHash, RegistrationEntryForConcatenation>()
74 .to_merkle_tree_batch_commitment(),
75 total_stake: reg.total_stake,
76 }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use rand_chacha::ChaCha20Rng;
83 use rand_core::SeedableRng;
84
85 use crate::{
86 KeyRegistration, MithrilMembershipDigest, Parameters, RegistrationEntry,
87 VerificationKeyProofOfPossessionForConcatenation,
88 proof_system::AggregateVerificationKeyForConcatenation,
89 proof_system::concatenation::clerk::ConcatenationClerk, signature_scheme::BlsSigningKey,
90 };
91
92 type D = MithrilMembershipDigest;
93 mod golden {
94 use super::*;
95
96 const GOLDEN_BYTES: &[u8; 48] = &[
97 0, 0, 0, 0, 0, 0, 0, 2, 56, 37, 95, 107, 157, 98, 252, 194, 190, 204, 170, 26, 224, 10,
98 212, 7, 214, 89, 116, 196, 217, 122, 111, 56, 113, 253, 96, 45, 170, 121, 235, 159, 0,
99 0, 0, 0, 0, 0, 0, 2,
100 ];
101
102 fn golden_value() -> AggregateVerificationKeyForConcatenation<D> {
103 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
104 let params = Parameters {
105 m: 10,
106 k: 5,
107 phi_f: 0.8,
108 };
109 let sk_1 = BlsSigningKey::generate(&mut rng);
110 let sk_2 = BlsSigningKey::generate(&mut rng);
111 let pk_1 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_1);
112 let pk_2 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_2);
113
114 let mut key_reg = KeyRegistration::initialize();
115 let entry1 = RegistrationEntry::new(
116 pk_1,
117 1,
118 #[cfg(feature = "future_snark")]
119 None,
120 )
121 .unwrap();
122 let entry2 = RegistrationEntry::new(
123 pk_2,
124 1,
125 #[cfg(feature = "future_snark")]
126 None,
127 )
128 .unwrap();
129
130 key_reg.register_by_entry(&entry1).unwrap();
131 key_reg.register_by_entry(&entry2).unwrap();
132 let closed_key_reg = key_reg.close_registration();
133
134 let clerk = ConcatenationClerk::new_clerk_from_closed_key_registration(
135 ¶ms,
136 &closed_key_reg,
137 );
138
139 clerk.compute_aggregate_verification_key_for_concatenation()
140 }
141
142 #[test]
143 fn golden_conversions() {
144 let value = AggregateVerificationKeyForConcatenation::from_bytes(GOLDEN_BYTES)
145 .expect("This from bytes should not fail");
146 assert_eq!(golden_value(), value);
147
148 let serialized = AggregateVerificationKeyForConcatenation::to_bytes(&value);
149 let golden_serialized =
150 AggregateVerificationKeyForConcatenation::to_bytes(&golden_value());
151 assert_eq!(golden_serialized, serialized);
152 }
153 }
154
155 mod golden_json {
156 use super::*;
157
158 const GOLDEN_JSON: &str = r#"
159 {
160 "mt_commitment":{
161 "root":[56,37,95,107,157,98,252,194,190,204,170,26,224,10,212,7,214,89,116,196,217,122,111,56,113,253,96,45,170,121,235,159],
162 "nr_leaves":2,
163 "hasher":null
164 },
165 "total_stake":2
166 }
167 "#;
168
169 fn golden_value() -> AggregateVerificationKeyForConcatenation<D> {
170 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
171 let params = Parameters {
172 m: 10,
173 k: 5,
174 phi_f: 0.8,
175 };
176 let sk_1 = BlsSigningKey::generate(&mut rng);
177 let sk_2 = BlsSigningKey::generate(&mut rng);
178 let pk_1 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_1);
179 let pk_2 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_2);
180
181 let mut key_reg = KeyRegistration::initialize();
182 let entry1 = RegistrationEntry::new(
183 pk_1,
184 1,
185 #[cfg(feature = "future_snark")]
186 None,
187 )
188 .unwrap();
189 let entry2 = RegistrationEntry::new(
190 pk_2,
191 1,
192 #[cfg(feature = "future_snark")]
193 None,
194 )
195 .unwrap();
196
197 key_reg.register_by_entry(&entry1).unwrap();
198 key_reg.register_by_entry(&entry2).unwrap();
199 let closed_key_reg = key_reg.close_registration();
200
201 let clerk = ConcatenationClerk::new_clerk_from_closed_key_registration(
202 ¶ms,
203 &closed_key_reg,
204 );
205
206 clerk.compute_aggregate_verification_key_for_concatenation()
207 }
208
209 #[test]
210 fn golden_conversions() {
211 let value: AggregateVerificationKeyForConcatenation<D> =
212 serde_json::from_str(GOLDEN_JSON)
213 .expect("This JSON deserialization should not fail");
214
215 let serialized =
216 serde_json::to_string(&value).expect("This JSON serialization should not fail");
217 let golden_serialized = serde_json::to_string(&golden_value())
218 .expect("This JSON serialization should not fail");
219 assert_eq!(golden_serialized, serialized);
220 }
221 }
222}