Skip to content

Commit c93e02d

Browse files
committed
Little refactoring
1 parent e1367eb commit c93e02d

File tree

2 files changed

+236
-139
lines changed

2 files changed

+236
-139
lines changed

crates/dkg/src/verification.rs

Lines changed: 187 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -65,65 +65,72 @@ pub fn get_index_in_commitments(
6565
)))
6666
}
6767

68-
pub fn verify_seed_exchange_commitment<Setup>(
69-
verification_hashes: &VerificationHashes,
68+
#[cfg(feature = "auth_commitment")]
69+
fn verify_commitment_details<Setup>(
7070
seed_exchange: &SeedExchangeCommitment<Setup>,
71-
initial_commitment: &InitialCommitment<Setup>,
7271
) -> Result<(), Box<dyn std::error::Error>>
7372
where
7473
Setup: DkgSetup + DkgSetupTypes<Setup>,
7574
{
76-
#[cfg(feature = "auth_commitment")]
77-
{
78-
let commitment = &seed_exchange.commitment;
75+
let commitment = &seed_exchange.commitment;
7976

80-
if !verify_commitment(&seed_exchange.commitment) {
81-
return Err(Box::new(VerificationErrors::UnslashableError(format!(
82-
"Invalid field seeds_exchange_commitment.commitment.signature {},
77+
if !verify_commitment(&seed_exchange.commitment) {
78+
return Err(Box::new(VerificationErrors::UnslashableError(format!(
79+
"Invalid field seeds_exchange_commitment.commitment.signature {},
8380
message: {}
8481
pubkey: {},
8582
\n",
86-
commitment.signature, commitment.hash, commitment.pubkey
87-
))));
88-
}
83+
commitment.signature, commitment.hash, commitment.pubkey
84+
))));
8985
}
9086

91-
let shared_secret = &seed_exchange.shared_secret;
92-
let sk = match Setup::DkgSecretKey::from_bytes(&shared_secret.secret) {
93-
Ok(sk) => sk,
94-
Err(e) => {
95-
return Err(Box::new(VerificationErrors::SlashableError(format!(
96-
"Invalid field seeds_exchange_commitment.shared_secret.secret: {e} \n"
97-
))));
98-
}
99-
};
87+
let computed_commitment_hash = compute_seed_exchange_hash::<Setup>(seed_exchange);
10088

101-
#[cfg(feature = "auth_commitment")]
102-
{
103-
let computed_commitment_hash = compute_seed_exchange_hash::<Setup>(seed_exchange);
104-
105-
if computed_commitment_hash.to_vec() != seed_exchange.commitment.hash.as_ref() {
106-
return Err(Box::new(VerificationErrors::SlashableError(
107-
format!(
108-
"Invalid field seeds_exchange_commitment.commitment.hash. Expected: {:?}, got hash: {:?}\n",
109-
seed_exchange.commitment.hash,
110-
hex::encode(computed_commitment_hash.to_vec())
111-
),
112-
)));
113-
}
89+
if computed_commitment_hash.to_vec() != seed_exchange.commitment.hash.as_ref() {
90+
return Err(Box::new(VerificationErrors::SlashableError(
91+
format!(
92+
"Invalid field seeds_exchange_commitment.commitment.hash. Expected: {:?}, got hash: {:?}\n",
93+
seed_exchange.commitment.hash,
94+
hex::encode(computed_commitment_hash.to_vec())
95+
),
96+
)));
11497
}
11598

116-
let dest_id = match get_index_in_commitments(
99+
Ok(())
100+
}
101+
102+
fn validate_shared_secret<Setup>(
103+
seed_exchange: &SeedExchangeCommitment<Setup>,
104+
) -> Result<Setup::DkgSecretKey, Box<dyn std::error::Error>>
105+
where
106+
Setup: DkgSetup + DkgSetupTypes<Setup>,
107+
{
108+
let shared_secret = &seed_exchange.shared_secret;
109+
Setup::DkgSecretKey::from_bytes(&shared_secret.secret).map_err(|e| {
110+
Box::new(VerificationErrors::SlashableError(format!(
111+
"Invalid field seeds_exchange_commitment.shared_secret.secret: {e} \n"
112+
))) as Box<dyn std::error::Error>
113+
})
114+
}
115+
116+
fn verify_polynomial_evaluation_for_seed<Setup>(
117+
verification_hashes: &VerificationHashes,
118+
seed_exchange: &SeedExchangeCommitment<Setup>,
119+
initial_commitment: &InitialCommitment<Setup>,
120+
sk: &Setup::DkgSecretKey,
121+
) -> Result<(), Box<dyn std::error::Error>>
122+
where
123+
Setup: DkgSetup + DkgSetupTypes<Setup>,
124+
{
125+
let dest_id = get_index_in_commitments(
117126
verification_hashes,
118127
&seed_exchange.shared_secret.dst_base_hash,
119-
) {
120-
Ok(id) => id,
121-
Err(e) => {
122-
return Err(Box::new(VerificationErrors::SlashableError(format!(
123-
"Invalid field seeds_exchange_commitment.shared_secret.dst_base_hash: {e} \n"
124-
))));
125-
}
126-
};
128+
)
129+
.map_err(|e| {
130+
Box::new(VerificationErrors::SlashableError(format!(
131+
"Invalid field seeds_exchange_commitment.shared_secret.dst_base_hash: {e} \n"
132+
))) as Box<dyn std::error::Error>
133+
})?;
127134

128135
// F(0) is always reserved for the aggregated key so we need to start from 1
129136
let dest_id = dest_id + 1;
@@ -148,6 +155,31 @@ where
148155
Ok(())
149156
}
150157

158+
pub fn verify_seed_exchange_commitment<Setup>(
159+
verification_hashes: &VerificationHashes,
160+
seed_exchange: &SeedExchangeCommitment<Setup>,
161+
initial_commitment: &InitialCommitment<Setup>,
162+
) -> Result<(), Box<dyn std::error::Error>>
163+
where
164+
Setup: DkgSetup + DkgSetupTypes<Setup>,
165+
{
166+
#[cfg(feature = "auth_commitment")]
167+
{
168+
verify_commitment_details(seed_exchange)?;
169+
}
170+
171+
let sk = validate_shared_secret(seed_exchange)?;
172+
173+
verify_polynomial_evaluation_for_seed(
174+
verification_hashes,
175+
seed_exchange,
176+
initial_commitment,
177+
&sk,
178+
)?;
179+
180+
Ok(())
181+
}
182+
151183
fn compute_base_hash<Setup>(
152184
settings: &GenerateSettings,
153185
pubkeys: &[RawBytes<Setup::Point>],
@@ -261,9 +293,8 @@ fn compute_agg_key_from_dkg<C: Curve>(
261293
Ok(coefficients[0])
262294
}
263295

264-
pub fn verify_generation_hashes<Setup>(
296+
fn verify_message_cleartext<Setup>(
265297
generations: &[Generation<Setup>],
266-
settings: &GenerateSettings,
267298
) -> Result<(), Box<dyn std::error::Error>>
268299
where
269300
Setup: DkgSetup + DkgSetupTypes<Setup>,
@@ -282,7 +313,16 @@ where
282313
)));
283314
}
284315
}
316+
Ok(())
317+
}
285318

319+
fn verify_signatures_and_commitments<Setup>(
320+
generations: &[Generation<Setup>],
321+
settings: &GenerateSettings,
322+
) -> Result<(), Box<dyn std::error::Error>>
323+
where
324+
Setup: DkgSetup + DkgSetupTypes<Setup>,
325+
{
286326
let message_mapping = Setup::TargetCryptography::precompute_message_mapping(
287327
generations[0].message_cleartext.as_bytes(),
288328
);
@@ -301,8 +341,7 @@ where
301341
}
302342

303343
let initial_commitment = generate_initial_commitment(generation, settings);
304-
let ok = verify_initial_commitment_hash::<Setup>(&initial_commitment);
305-
if !ok {
344+
if !verify_initial_commitment_hash::<Setup>(&initial_commitment) {
306345
return Err(Box::new(VerificationErrors::UnslashableError(format!(
307346
"Invalid initial commitment hash {}",
308347
initial_commitment.hash
@@ -312,36 +351,38 @@ where
312351
Ok(())
313352
}
314353

315-
pub fn verify_generations<Setup>(
354+
pub fn verify_generation_hashes<Setup>(
316355
generations: &[Generation<Setup>],
317356
settings: &GenerateSettings,
318-
agg_key: &Setup::DkgPubkey,
319357
) -> Result<(), Box<dyn std::error::Error>>
320358
where
321359
Setup: DkgSetup + DkgSetupTypes<Setup>,
322360
{
323-
if generations.len() != settings.n as usize {
324-
return Err(Box::new(std::io::Error::new(
325-
std::io::ErrorKind::InvalidData,
326-
"Invalid number of generations",
327-
)));
328-
}
329-
330-
verify_generation_hashes(generations, settings)?;
361+
verify_message_cleartext(generations)?;
362+
verify_signatures_and_commitments(generations, settings)
363+
}
331364

365+
fn sort_and_deserialize_vectors<Setup>(
366+
generations: &[Generation<Setup>],
367+
) -> (Vec<Generation<Setup>>, Vec<Vec<Setup::Point>>)
368+
where
369+
Setup: DkgSetup + DkgSetupTypes<Setup>,
370+
{
332371
let mut sorted = generations.to_vec();
333372
sorted.sort_by(|a, b| a.base_hash.cmp(&b.base_hash));
334-
335373
let verification_vectors = deserialize_verification_vectors::<Setup>(&sorted);
374+
(sorted, verification_vectors)
375+
}
336376

337-
let ids: Vec<Setup::Scalar> = sorted
338-
.iter()
339-
.enumerate()
340-
.map(|(i, _)| Setup::Scalar::from_u32((i + 1) as u32))
341-
.collect();
342-
343-
let computed_key = compute_agg_key_from_dkg::<Setup::Curve>(&verification_vectors, &ids)?;
344-
377+
fn verify_computed_agg_key<Setup>(
378+
verification_vectors: &[Vec<Setup::Point>],
379+
ids: &[Setup::Scalar],
380+
agg_key: &Setup::DkgPubkey,
381+
) -> Result<(), Box<dyn std::error::Error>>
382+
where
383+
Setup: DkgSetup + DkgSetupTypes<Setup>,
384+
{
385+
let computed_key = compute_agg_key_from_dkg::<Setup::Curve>(verification_vectors, ids)?;
345386
if agg_key.to_bytes() != computed_key.to_bytes() {
346387
return Err(Box::new(std::io::Error::new(
347388
std::io::ErrorKind::InvalidData,
@@ -351,15 +392,25 @@ where
351392
),
352393
)));
353394
}
395+
Ok(())
396+
}
354397

355-
let partial_keys: Vec<Setup::Point> = sorted
398+
fn verify_lagrange_interpolation_for_agg_key<Setup>(
399+
sorted_generations: &[Generation<Setup>],
400+
ids: &[Setup::Scalar],
401+
agg_key: &Setup::DkgPubkey,
402+
) -> Result<(), Box<dyn std::error::Error>>
403+
where
404+
Setup: DkgSetup + DkgSetupTypes<Setup>,
405+
{
406+
let partial_keys: Vec<Setup::Point> = sorted_generations
356407
.iter()
357408
.map(|generation| {
358409
Setup::Point::from_bytes(&generation.partial_pubkey).expect("Invalid g1 point")
359410
})
360411
.collect();
361412

362-
let computed_key = lagrange_interpolation::<Setup::Curve>(&partial_keys, &ids)?;
413+
let computed_key = lagrange_interpolation::<Setup::Curve>(&partial_keys, ids)?;
363414

364415
if computed_key.to_bytes() != agg_key.to_bytes() {
365416
return Err(Box::new(std::io::Error::new(
@@ -370,6 +421,34 @@ where
370421
),
371422
)));
372423
}
424+
Ok(())
425+
}
426+
427+
pub fn verify_generations<Setup>(
428+
generations: &[Generation<Setup>],
429+
settings: &GenerateSettings,
430+
agg_key: &Setup::DkgPubkey,
431+
) -> Result<(), Box<dyn std::error::Error>>
432+
where
433+
Setup: DkgSetup + DkgSetupTypes<Setup>,
434+
{
435+
if generations.len() != settings.n as usize {
436+
return Err(Box::new(std::io::Error::new(
437+
std::io::ErrorKind::InvalidData,
438+
"Invalid number of generations",
439+
)));
440+
}
441+
442+
verify_generation_hashes(generations, settings)?;
443+
444+
let (sorted, verification_vectors) = sort_and_deserialize_vectors(generations);
445+
446+
let ids: Vec<Setup::Scalar> = (1..=sorted.len())
447+
.map(|i| Setup::Scalar::from_u32(i as u32))
448+
.collect();
449+
450+
verify_computed_agg_key::<Setup>(&verification_vectors, &ids, agg_key)?;
451+
verify_lagrange_interpolation_for_agg_key::<Setup>(&sorted, &ids, agg_key)?;
373452

374453
Ok(())
375454
}
@@ -453,6 +532,44 @@ where
453532
Ok(())
454533
}
455534

535+
fn verify_partial_signature<Setup>(
536+
bad_partial: &BadPartialShare<Setup>,
537+
key: &Setup::DkgPubkey,
538+
) -> Result<(), Box<dyn std::error::Error>>
539+
where
540+
Setup: DkgSetup + DkgSetupTypes<Setup>,
541+
{
542+
let sig =
543+
Setup::DkgSignature::from_bytes_safe(&bad_partial.data.message_signature).map_err(|e| {
544+
Box::new(VerificationErrors::SlashableError(format!(
545+
"While uncompressing data.bad_partial.data.message_signature {}",
546+
e
547+
))) as Box<dyn std::error::Error>
548+
})?;
549+
550+
if !key.verify_signature(bad_partial.data.message_cleartext.as_bytes(), &sig) {
551+
return Err(Box::new(VerificationErrors::SlashableError(format!(
552+
"Invalid partial signature {} from key {}",
553+
sig, key
554+
))));
555+
}
556+
Ok(())
557+
}
558+
559+
fn get_perpetrator_key<Setup>(
560+
bad_partial: &BadPartialShare<Setup>,
561+
) -> Result<Setup::DkgPubkey, Box<dyn std::error::Error>>
562+
where
563+
Setup: DkgSetup + DkgSetupTypes<Setup>,
564+
{
565+
Setup::DkgPubkey::from_bytes_safe(&bad_partial.data.partial_pubkey).map_err(|e| {
566+
Box::new(VerificationErrors::SlashableError(format!(
567+
"While uncompressing data.bad_partial.data.partial_pubkey {}",
568+
e
569+
))) as Box<dyn std::error::Error>
570+
})
571+
}
572+
456573
pub fn prove_wrong_final_key_generation<Setup>(
457574
data: &BadPartialShareData<Setup>,
458575
) -> Result<(), Box<dyn std::error::Error>>
@@ -471,29 +588,9 @@ where
471588
let perpetrator_index =
472589
find_perpetrator_index(&data.bad_partial.data.base_hash, &sorted_generation)?;
473590

474-
let key =
475-
Setup::DkgPubkey::from_bytes_safe(&data.bad_partial.data.partial_pubkey).map_err(|e| {
476-
VerificationErrors::SlashableError(format!(
477-
"While uncompressing data.bad_partial.data.partial_pubkey {}",
478-
e
479-
))
480-
})?;
481-
482-
let sig = Setup::DkgSignature::from_bytes_safe(&data.bad_partial.data.message_signature)
483-
.map_err(|e| {
484-
VerificationErrors::SlashableError(format!(
485-
"While uncompressing data.bad_partial.data.message_signature {}",
486-
e
487-
))
488-
})?;
489-
490-
if !key.verify_signature(data.bad_partial.data.message_cleartext.as_bytes(), &sig) {
491-
return Err(Box::new(VerificationErrors::SlashableError(format!(
492-
"Invalid partial signature {} from key {}",
493-
sig, key
494-
))));
495-
}
591+
let key = get_perpetrator_key(&data.bad_partial)?;
496592

593+
verify_partial_signature(&data.bad_partial, &key)?;
497594
verify_expected_key::<Setup>(&sorted_generation, perpetrator_index, &key)?;
498595

499596
Ok(())

0 commit comments

Comments
 (0)