1
- use kes_summed_ed25519:: { kes:: Sum6Kes , traits:: KesSk } ;
1
+ use kes_summed_ed25519:: { kes:: Sum6Kes , traits:: KesSk , PublicKey as KesPublicKey } ;
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_kes_key;
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,61 @@ 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 {
154
- let mut cold_key_seed: Vec < u8 > = ( party_index)
147
+ fn provide_kes_key ( kes_key_seed : & mut [ u8 ] ) -> ( Sum6KesBytes , KesPublicKey ) {
148
+ if let Some ( ( kes_bytes, kes_verification_key) ) =
149
+ MithrilFixtureBuilder :: cached_kes_key ( kes_key_seed)
150
+ {
151
+ ( kes_bytes, kes_verification_key)
152
+ } else {
153
+ println ! (
154
+ "KES key not found in test cache, generating a new one for the seed {:?}." ,
155
+ kes_key_seed
156
+ ) ;
157
+ MithrilFixtureBuilder :: generate_kes_key ( kes_key_seed)
158
+ }
159
+ }
160
+
161
+ fn cached_kes_key ( kes_key_seed : & [ u8 ] ) -> Option < ( Sum6KesBytes , KesPublicKey ) > {
162
+ precomputed_kes_key:: cached_kes_key ( kes_key_seed) . map (
163
+ |( kes_bytes, kes_verification_key) | {
164
+ let kes_verification_key = KesPublicKey :: from_bytes ( & kes_verification_key) . unwrap ( ) ;
165
+ let kes_bytes = Sum6KesBytes ( kes_bytes) ;
166
+
167
+ ( kes_bytes, kes_verification_key)
168
+ } ,
169
+ )
170
+ }
171
+
172
+ fn generate_kes_key ( kes_key_seed : & mut [ u8 ] ) -> ( Sum6KesBytes , KesPublicKey ) {
173
+ let mut key_buffer = [ 0u8 ; Sum6Kes :: SIZE + 4 ] ;
174
+
175
+ let ( kes_secret_key, kes_verification_key) = Sum6Kes :: keygen ( & mut key_buffer, kes_key_seed) ;
176
+ let mut kes_bytes = Sum6KesBytes ( [ 0u8 ; Sum6Kes :: SIZE + 4 ] ) ;
177
+ kes_bytes. 0 . copy_from_slice ( & kes_secret_key. clone_sk ( ) ) ;
178
+
179
+ ( kes_bytes, kes_verification_key)
180
+ }
181
+
182
+ fn generate_cold_key_seed ( & self , party_index : usize ) -> Vec < u8 > {
183
+ let mut cold_key_seed: Vec < _ > = ( party_index)
155
184
. to_le_bytes ( )
156
185
. iter ( )
157
186
. zip ( self . party_id_seed )
158
187
. map ( |( v1, v2) | v1 + v2)
159
188
. collect ( ) ;
160
189
cold_key_seed. resize ( 32 , 0 ) ;
190
+
191
+ cold_key_seed
192
+ }
193
+
194
+ fn build_party_with_operational_certificate ( & self , party_index : usize ) -> PartyId {
195
+ let cold_key_seed = self . generate_cold_key_seed ( party_index) . to_vec ( ) ;
196
+ let mut kes_key_seed = cold_key_seed. clone ( ) ;
197
+
161
198
let keypair =
162
199
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 ( ) ) ;
200
+ let ( kes_bytes, kes_verification_key) =
201
+ MithrilFixtureBuilder :: provide_kes_key ( & mut kes_key_seed) ;
168
202
let operational_certificate = OpCert :: new ( kes_verification_key, 0 , 0 , keypair) ;
169
203
let party_id = operational_certificate
170
204
. compute_protocol_party_id ( )
@@ -265,11 +299,11 @@ mod tests {
265
299
#[ test]
266
300
fn changing_party_id_seed_change_all_builded_party_ids ( ) {
267
301
let first_signers = MithrilFixtureBuilder :: default ( )
268
- . with_signers ( 20 )
302
+ . with_signers ( 10 )
269
303
. build ( )
270
304
. signers_with_stake ( ) ;
271
305
let different_party_id_seed_signers = MithrilFixtureBuilder :: default ( )
272
- . with_signers ( 20 )
306
+ . with_signers ( 10 )
273
307
. with_party_id_seed ( [ 1u8 ; 32 ] )
274
308
. build ( )
275
309
. signers_with_stake ( ) ;
@@ -279,4 +313,65 @@ mod tests {
279
313
assert ! ( !first_party_ids. contains( & party_id) ) ;
280
314
}
281
315
}
316
+
317
+ /// Verify that there is a cached kes key for a number of party id.
318
+ /// If the cache is not up to date, the test will generate the code that can be copied/pasted into the [precomputed_kes_key] module.
319
+ /// The number of party id that should be in cache is defined with `precomputed_number`
320
+ #[ test]
321
+ fn verify_kes_key_cache_content ( ) {
322
+ // Generate code that should be in the `cached_kes_key` function of the `precomputed_kes_key.rs` file.
323
+ // It can be copied and pasted to update the cache.
324
+ fn generate_code ( party_ids : & Vec < ( & [ u8 ] , [ u8 ; 612 ] , KesPublicKey ) > ) -> String {
325
+ party_ids
326
+ . iter ( )
327
+ . map ( |( key, i, p) | format ! ( "{:?} => ({:?}, {:?})," , key, i, p. as_bytes( ) ) )
328
+ . collect :: < Vec < _ > > ( )
329
+ . join ( "\n " )
330
+ }
331
+
332
+ let precomputed_number = 10 ;
333
+
334
+ let fixture = MithrilFixtureBuilder :: default ( ) ;
335
+ let cold_keys: Vec < _ > = ( 0 ..precomputed_number)
336
+ . map ( |party_index| fixture. generate_cold_key_seed ( party_index) )
337
+ . collect ( ) ;
338
+
339
+ let computed_keys_key: Vec < _ > = cold_keys
340
+ . iter ( )
341
+ . map ( |cold_key| {
342
+ let mut kes_key_seed: Vec < u8 > = cold_key. clone ( ) ;
343
+ let ( kes_bytes, kes_verification_key) =
344
+ MithrilFixtureBuilder :: generate_kes_key ( & mut kes_key_seed) ;
345
+
346
+ ( cold_key. as_slice ( ) , kes_bytes. 0 , kes_verification_key)
347
+ } )
348
+ . collect ( ) ;
349
+
350
+ let cached_kes_key: Vec < _ > = cold_keys
351
+ . iter ( )
352
+ . filter_map ( |cold_key| {
353
+ MithrilFixtureBuilder :: cached_kes_key ( cold_key) . map (
354
+ |( kes_bytes, kes_verification_key) | {
355
+ ( cold_key. as_slice ( ) , kes_bytes. 0 , kes_verification_key)
356
+ } ,
357
+ )
358
+ } )
359
+ . collect ( ) ;
360
+
361
+ let expected_code = generate_code ( & computed_keys_key) ;
362
+ let actual_code = generate_code ( & cached_kes_key) ;
363
+
364
+ assert_eq ! (
365
+ computed_keys_key, cached_kes_key,
366
+ "Precomputed KES keys should be:\n {}\n but seems to be:\n {}" ,
367
+ expected_code, actual_code
368
+ ) ;
369
+
370
+ let kes_key_seed = fixture. generate_cold_key_seed ( precomputed_number) ;
371
+ assert ! (
372
+ MithrilFixtureBuilder :: cached_kes_key( kes_key_seed. as_slice( ) ) . is_none( ) ,
373
+ "We checked precomputed KES keys up to {} but it seems to be more." ,
374
+ precomputed_number
375
+ ) ;
376
+ }
282
377
}
0 commit comments