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 .key_registration
74 .clone()
75 .into_merkle_tree::<D::ConcatenationHash, RegistrationEntryForConcatenation>()
76 .to_merkle_tree_batch_commitment(),
77 total_stake: reg.total_stake,
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use rand_chacha::ChaCha20Rng;
85 use rand_core::SeedableRng;
86
87 use crate::{
88 KeyRegistration, MithrilMembershipDigest, Parameters, RegistrationEntry,
89 VerificationKeyProofOfPossessionForConcatenation,
90 proof_system::AggregateVerificationKeyForConcatenation,
91 proof_system::concatenation::clerk::ConcatenationClerk, signature_scheme::BlsSigningKey,
92 };
93
94 type D = MithrilMembershipDigest;
95 mod golden {
96 use super::*;
97
98 const GOLDEN_BYTES: &[u8; 48] = &[
99 0, 0, 0, 0, 0, 0, 0, 2, 56, 37, 95, 107, 157, 98, 252, 194, 190, 204, 170, 26, 224, 10,
100 212, 7, 214, 89, 116, 196, 217, 122, 111, 56, 113, 253, 96, 45, 170, 121, 235, 159, 0,
101 0, 0, 0, 0, 0, 0, 2,
102 ];
103
104 fn golden_value() -> AggregateVerificationKeyForConcatenation<D> {
105 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
106 let params = Parameters {
107 m: 10,
108 k: 5,
109 phi_f: 0.8,
110 };
111 let sk_1 = BlsSigningKey::generate(&mut rng);
112 let sk_2 = BlsSigningKey::generate(&mut rng);
113 let pk_1 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_1);
114 let pk_2 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_2);
115
116 let mut key_reg = KeyRegistration::initialize();
117 let entry1 = RegistrationEntry::new(pk_1, 1).unwrap();
118 let entry2 = RegistrationEntry::new(pk_2, 1).unwrap();
119
120 key_reg.register_by_entry(&entry1).unwrap();
121 key_reg.register_by_entry(&entry2).unwrap();
122 let closed_key_reg = key_reg.close_registration();
123
124 let clerk = ConcatenationClerk::new_clerk_from_closed_key_registration(
125 ¶ms,
126 &closed_key_reg,
127 );
128
129 clerk.compute_aggregate_verification_key_for_concatenation()
130 }
131
132 #[test]
133 fn golden_conversions() {
134 let value = AggregateVerificationKeyForConcatenation::from_bytes(GOLDEN_BYTES)
135 .expect("This from bytes should not fail");
136 assert_eq!(golden_value(), value);
137
138 let serialized = AggregateVerificationKeyForConcatenation::to_bytes(&value);
139 let golden_serialized =
140 AggregateVerificationKeyForConcatenation::to_bytes(&golden_value());
141 assert_eq!(golden_serialized, serialized);
142 }
143 }
144
145 mod golden_json {
146 use super::*;
147
148 const GOLDEN_JSON: &str = r#"
149 {
150 "mt_commitment":{
151 "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],
152 "nr_leaves":2,
153 "hasher":null
154 },
155 "total_stake":2
156 }
157 "#;
158
159 fn golden_value() -> AggregateVerificationKeyForConcatenation<D> {
160 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
161 let params = Parameters {
162 m: 10,
163 k: 5,
164 phi_f: 0.8,
165 };
166 let sk_1 = BlsSigningKey::generate(&mut rng);
167 let sk_2 = BlsSigningKey::generate(&mut rng);
168 let pk_1 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_1);
169 let pk_2 = VerificationKeyProofOfPossessionForConcatenation::from(&sk_2);
170
171 let mut key_reg = KeyRegistration::initialize();
172 let entry1 = RegistrationEntry::new(pk_1, 1).unwrap();
173 let entry2 = RegistrationEntry::new(pk_2, 1).unwrap();
174
175 key_reg.register_by_entry(&entry1).unwrap();
176 key_reg.register_by_entry(&entry2).unwrap();
177 let closed_key_reg = key_reg.close_registration();
178
179 let clerk = ConcatenationClerk::new_clerk_from_closed_key_registration(
180 ¶ms,
181 &closed_key_reg,
182 );
183
184 clerk.compute_aggregate_verification_key_for_concatenation()
185 }
186
187 #[test]
188 fn golden_conversions() {
189 let value: AggregateVerificationKeyForConcatenation<D> =
190 serde_json::from_str(GOLDEN_JSON)
191 .expect("This JSON deserialization should not fail");
192
193 let serialized =
194 serde_json::to_string(&value).expect("This JSON serialization should not fail");
195 let golden_serialized = serde_json::to_string(&golden_value())
196 .expect("This JSON serialization should not fail");
197 assert_eq!(golden_serialized, serialized);
198 }
199 }
200}