1
- use kes_summed_ed25519:: { kes:: Sum6Kes , traits:: KesSk } ;
1
+ use kes_summed_ed25519:: { kes:: Sum6Kes , traits:: KesSk , PublicKey } ;
2
2
use rand_chacha:: ChaCha20Rng ;
3
3
use rand_core:: { RngCore , SeedableRng } ;
4
4
@@ -11,6 +11,8 @@ use crate::{
11
11
test_utils:: { fake_data, mithril_fixture:: MithrilFixture } ,
12
12
} ;
13
13
14
+ use super :: precomputed_keskey;
15
+
14
16
/// A builder of mithril types.
15
17
pub struct MithrilFixtureBuilder {
16
18
protocol_parameters : ProtocolParameters ,
@@ -130,13 +132,9 @@ impl MithrilFixtureBuilder {
130
132
match self . stake_distribution_generation_method {
131
133
StakeDistributionGenerationMethod :: Custom ( _) => vec ! [ ] ,
132
134
_ => {
133
- let mut kes_keys_seed = [ 0u8 ; 32 ] ;
134
135
let signers_party_ids = ( 0 ..self . number_of_signers ) . map ( |party_index| {
135
136
if self . enable_signers_certification {
136
- self . build_party_with_operational_certificate (
137
- party_index,
138
- & mut kes_keys_seed,
139
- )
137
+ self . build_party_with_operational_certificate ( party_index)
140
138
} else {
141
139
party_index. to_string ( )
142
140
}
@@ -146,25 +144,47 @@ impl MithrilFixtureBuilder {
146
144
}
147
145
}
148
146
149
- fn build_party_with_operational_certificate (
150
- & self ,
151
- party_index : usize ,
152
- kes_key_seed : & mut [ u8 ] ,
153
- ) -> PartyId {
147
+ fn provide_kes_key < ' a > (
148
+ key_buffer : & ' a mut [ u8 ] ,
149
+ kes_key_seed : & ' a mut [ u8 ] ,
150
+ ) -> ( Sum6KesBytes , PublicKey ) {
151
+ if let Some ( cached_value) = precomputed_keskey:: cached_kes_key ( kes_key_seed) {
152
+ return cached_value;
153
+ }
154
+ // TODO We can log a warning to indicate that the cache is not used
155
+ MithrilFixtureBuilder :: generate_kes_key ( key_buffer, kes_key_seed)
156
+ }
157
+
158
+ fn generate_kes_key < ' a > (
159
+ key_buffer : & ' a mut [ u8 ] ,
160
+ kes_key_seed : & ' a mut [ u8 ] ,
161
+ ) -> ( Sum6KesBytes , PublicKey ) {
162
+ let ( kes_secret_key, kes_verification_key) = Sum6Kes :: keygen ( key_buffer, kes_key_seed) ;
163
+ let mut kes_bytes = Sum6KesBytes ( [ 0u8 ; Sum6Kes :: SIZE + 4 ] ) ;
164
+ kes_bytes. 0 . copy_from_slice ( & kes_secret_key. clone_sk ( ) ) ;
165
+ ( kes_bytes, kes_verification_key)
166
+ }
167
+
168
+ fn generate_cold_key_seed ( & self , party_index : usize ) -> Vec < u8 > {
154
169
let mut cold_key_seed: Vec < u8 > = ( party_index)
155
170
. to_le_bytes ( )
156
171
. iter ( )
157
172
. zip ( self . party_id_seed )
158
173
. map ( |( v1, v2) | v1 + v2)
159
174
. collect ( ) ;
160
175
cold_key_seed. resize ( 32 , 0 ) ;
176
+ cold_key_seed
177
+ }
178
+
179
+ fn build_party_with_operational_certificate ( & self , party_index : usize ) -> PartyId {
180
+ let cold_key_seed: Vec < u8 > = self . generate_cold_key_seed ( party_index) . to_vec ( ) ;
181
+ let mut kes_key_seed = cold_key_seed. clone ( ) ;
182
+
161
183
let keypair =
162
184
ColdKeyGenerator :: create_deterministic_keypair ( cold_key_seed. try_into ( ) . unwrap ( ) ) ;
163
- let mut dummy_buffer = [ 0u8 ; Sum6Kes :: SIZE + 4 ] ;
164
- let ( kes_secret_key, kes_verification_key) =
165
- Sum6Kes :: keygen ( & mut dummy_buffer, kes_key_seed) ;
166
- let mut kes_bytes = Sum6KesBytes ( [ 0u8 ; Sum6Kes :: SIZE + 4 ] ) ;
167
- kes_bytes. 0 . copy_from_slice ( & kes_secret_key. clone_sk ( ) ) ;
185
+ let mut kes_key_buffer = [ 0u8 ; Sum6Kes :: SIZE + 4 ] ;
186
+ let ( kes_bytes, kes_verification_key) =
187
+ MithrilFixtureBuilder :: provide_kes_key ( & mut kes_key_buffer, & mut kes_key_seed) ;
168
188
let operational_certificate = OpCert :: new ( kes_verification_key, 0 , 0 , keypair) ;
169
189
let party_id = operational_certificate
170
190
. compute_protocol_party_id ( )
@@ -188,6 +208,7 @@ impl MithrilFixtureBuilder {
188
208
#[ cfg( test) ]
189
209
mod tests {
190
210
use super :: * ;
211
+ use kes_summed_ed25519:: { kes:: Sum6Kes , traits:: KesSk , PublicKey } ;
191
212
use std:: collections:: BTreeSet ;
192
213
193
214
#[ test]
@@ -265,11 +286,11 @@ mod tests {
265
286
#[ test]
266
287
fn changing_party_id_seed_change_all_builded_party_ids ( ) {
267
288
let first_signers = MithrilFixtureBuilder :: default ( )
268
- . with_signers ( 20 )
289
+ . with_signers ( 10 )
269
290
. build ( )
270
291
. signers_with_stake ( ) ;
271
292
let different_party_id_seed_signers = MithrilFixtureBuilder :: default ( )
272
- . with_signers ( 20 )
293
+ . with_signers ( 10 )
273
294
. with_party_id_seed ( [ 1u8 ; 32 ] )
274
295
. build ( )
275
296
. signers_with_stake ( ) ;
@@ -279,4 +300,66 @@ mod tests {
279
300
assert ! ( !first_party_ids. contains( & party_id) ) ;
280
301
}
281
302
}
303
+
304
+ /// Verify that there is cached kes key for a number of party id.
305
+ /// If the cache is not up to date, it will generate the code to use as cache.
306
+ #[ test]
307
+ fn verify_kes_key_cache_content ( ) {
308
+ // Generate code that should be in the match instruction of cached_kes_key.
309
+ // It could be copy paste to update the cache.
310
+ fn generate_code ( party_ids : & Vec < ( & [ u8 ] , [ u8 ; 612 ] , PublicKey ) > ) -> String {
311
+ party_ids
312
+ . iter ( )
313
+ . map ( |( key, i, p) | format ! ( "{:?} => ({:?}, {:?})," , key, i, p. as_bytes( ) ) )
314
+ . collect :: < Vec < _ > > ( )
315
+ . join ( "\n " )
316
+ }
317
+
318
+ let precomputed_number = 10 ;
319
+
320
+ let fixture = MithrilFixtureBuilder :: default ( ) ;
321
+ let cold_keys: Vec < _ > = ( 0 ..precomputed_number)
322
+ . into_iter ( )
323
+ . map ( |party_index| fixture. generate_cold_key_seed ( party_index) )
324
+ . collect ( ) ;
325
+
326
+ let computed_keys_key: Vec < _ > = cold_keys
327
+ . iter ( )
328
+ . map ( |cold_key| {
329
+ let mut kes_key_buffer = [ 0u8 ; Sum6Kes :: SIZE + 4 ] ;
330
+ let mut kes_key_seed: Vec < u8 > = cold_key. clone ( ) ;
331
+ let ( kes_bytes, kes_verification_key) =
332
+ MithrilFixtureBuilder :: generate_kes_key ( & mut kes_key_buffer, & mut kes_key_seed) ;
333
+
334
+ ( cold_key. as_slice ( ) , kes_bytes. 0 , kes_verification_key)
335
+ } )
336
+ . collect ( ) ;
337
+
338
+ let cached_kes_key: Vec < _ > = cold_keys
339
+ . iter ( )
340
+ . filter_map ( |cold_key| {
341
+ precomputed_keskey:: cached_kes_key ( cold_key) . map (
342
+ |( kes_bytes, kes_verification_key) | {
343
+ ( cold_key. as_slice ( ) , kes_bytes. 0 , kes_verification_key)
344
+ } ,
345
+ )
346
+ } )
347
+ . collect ( ) ;
348
+
349
+ let expected_code = generate_code ( & computed_keys_key) ;
350
+ let actual_code = generate_code ( & cached_kes_key) ;
351
+
352
+ assert_eq ! (
353
+ computed_keys_key, cached_kes_key,
354
+ "Precomputed keskeys should be:\n {}\n but seems to be:\n {}" ,
355
+ expected_code, actual_code
356
+ ) ;
357
+
358
+ let kes_key_seed = fixture. generate_cold_key_seed ( precomputed_number) ;
359
+ assert ! (
360
+ precomputed_keskey:: cached_kes_key( kes_key_seed. as_slice( ) ) . is_none( ) ,
361
+ "We checked precomputed keskey up to {} but it seems to be more." ,
362
+ precomputed_number
363
+ ) ;
364
+ }
282
365
}
0 commit comments