@@ -9,7 +9,7 @@ use crate::{
99 codec:: { CodecError , Decode , Encode , ParameterizedDecode } ,
1010 field:: { decode_fieldvec, FieldElement , FieldElementWithInteger } ,
1111 flp:: {
12- szk:: { Szk , SzkJointShare , SzkProofShare , SzkQueryShare , SzkQueryState } ,
12+ szk:: { Szk , SzkInputShare , SzkJointShare , SzkQueryShare , SzkQueryState } ,
1313 Type ,
1414 } ,
1515 vdaf:: {
@@ -20,7 +20,7 @@ use crate::{
2020 } ,
2121 vidpf:: {
2222 Vidpf , VidpfError , VidpfInput , VidpfKey , VidpfPublicShare , VidpfServerId , VidpfWeight ,
23- VIDPF_PROOF_SIZE ,
23+ VIDPF_PROOF_SIZE , VIDPF_SEED_SIZE ,
2424 } ,
2525} ;
2626
@@ -35,17 +35,18 @@ use super::xof::XofTurboShake128;
3535const NONCE_SIZE : usize = 16 ;
3636
3737pub ( crate ) const USAGE_PROVE_RAND : u8 = 0 ;
38- pub ( crate ) const USAGE_PROOF_SHARE : u8 = 1 ;
39- pub ( crate ) const USAGE_QUERY_RAND : u8 = 2 ;
40- pub ( crate ) const USAGE_JOINT_RAND_SEED : u8 = 3 ;
41- pub ( crate ) const USAGE_JOINT_RAND_PART : u8 = 4 ;
42- pub ( crate ) const USAGE_JOINT_RAND : u8 = 5 ;
43- pub ( crate ) const USAGE_ONEHOT_CHECK : u8 = 6 ;
44- pub ( crate ) const USAGE_PAYLOAD_CHECK : u8 = 7 ;
45- pub ( crate ) const USAGE_EVAL_PROOF : u8 = 8 ;
46- pub ( crate ) const USAGE_NODE_PROOF : u8 = 9 ;
47- pub ( crate ) const USAGE_EXTEND : u8 = 10 ;
48- pub ( crate ) const USAGE_CONVERT : u8 = 11 ;
38+ pub ( crate ) const USAGE_WEIGHT_SHARE : u8 = 1 ;
39+ pub ( crate ) const USAGE_PROOF_SHARE : u8 = 2 ;
40+ pub ( crate ) const USAGE_QUERY_RAND : u8 = 3 ;
41+ pub ( crate ) const USAGE_JOINT_RAND_SEED : u8 = 4 ;
42+ pub ( crate ) const USAGE_JOINT_RAND_PART : u8 = 5 ;
43+ pub ( crate ) const USAGE_JOINT_RAND : u8 = 6 ;
44+ pub ( crate ) const USAGE_ONEHOT_CHECK : u8 = 7 ;
45+ pub ( crate ) const USAGE_PAYLOAD_CHECK : u8 = 8 ;
46+ pub ( crate ) const USAGE_EVAL_PROOF : u8 = 9 ;
47+ pub ( crate ) const USAGE_NODE_PROOF : u8 = 10 ;
48+ pub ( crate ) const USAGE_EXTEND : u8 = 11 ;
49+ pub ( crate ) const USAGE_CONVERT : u8 = 12 ;
4950
5051pub ( crate ) fn dst_usage ( usage : u8 ) -> [ u8 ; 8 ] {
5152 const VERSION : u8 = 0 ;
@@ -67,7 +68,7 @@ pub struct Mastic<T: Type> {
6768impl < T : Type > Mastic < T > {
6869 /// Creates a new instance of Mastic, with a specific attribute length and weight type.
6970 pub fn new ( algorithm_id : u32 , typ : T , bits : usize ) -> Result < Self , VdafError > {
70- let vidpf = Vidpf :: new ( bits, typ. input_len ( ) + 1 ) ?;
71+ let vidpf = Vidpf :: new ( bits, 1 + typ. output_len ( ) ) ?;
7172 let szk = Szk :: new ( typ, algorithm_id) ;
7273 Ok ( Self {
7374 id : algorithm_id. to_le_bytes ( ) ,
@@ -152,19 +153,19 @@ pub struct MasticInputShare<F: FieldElement> {
152153 /// VIDPF key share.
153154 vidpf_key : VidpfKey ,
154155
155- /// The proof share.
156- proof_share : SzkProofShare < F > ,
156+ /// SZK input share.
157+ szk_input_share : SzkInputShare < F > ,
157158}
158159
159160impl < F : FieldElement > Encode for MasticInputShare < F > {
160161 fn encode ( & self , bytes : & mut Vec < u8 > ) -> Result < ( ) , CodecError > {
161162 bytes. extend_from_slice ( & self . vidpf_key . 0 [ ..] ) ;
162- self . proof_share . encode ( bytes) ?;
163+ self . szk_input_share . encode ( bytes) ?;
163164 Ok ( ( ) )
164165 }
165166
166167 fn encoded_len ( & self ) -> Option < usize > {
167- Some ( 16 + self . proof_share . encoded_len ( ) ?)
168+ Some ( VIDPF_SEED_SIZE + self . szk_input_share . encoded_len ( ) ?)
168169 }
169170}
170171
@@ -177,17 +178,11 @@ impl<'a, T: Type> ParameterizedDecode<(&'a Mastic<T>, usize)> for MasticInputSha
177178 return Err ( CodecError :: UnexpectedValue ) ;
178179 }
179180 let vidpf_key = VidpfKey :: decode ( bytes) ?;
180- let proof_share = SzkProofShare :: decode_with_param (
181- & (
182- * agg_id == 0 ,
183- mastic. szk . typ . proof_len ( ) ,
184- mastic. szk . typ . joint_rand_len ( ) != 0 ,
185- ) ,
186- bytes,
187- ) ?;
181+ let szk_input_share =
182+ SzkInputShare :: decode_with_param ( & ( & mastic. szk , * agg_id == 0 ) , bytes) ?;
188183 Ok ( Self {
189184 vidpf_key,
190- proof_share ,
185+ szk_input_share ,
191186 } )
192187 }
193188}
@@ -202,7 +197,7 @@ impl<F: FieldElement> ConstantTimeEq for MasticInputShare<F> {
202197 fn ct_eq ( & self , other : & MasticInputShare < F > ) -> Choice {
203198 self . vidpf_key
204199 . ct_eq ( & other. vidpf_key )
205- . bitand ( self . proof_share . ct_eq ( & other. proof_share ) )
200+ . bitand ( self . szk_input_share . ct_eq ( & other. szk_input_share ) )
206201 }
207202}
208203
@@ -270,47 +265,28 @@ impl<T: Type> Mastic<T> {
270265 }
271266
272267 // The output with which we program the VIDPF is a counter and the encoded measurement.
273- let mut beta = VidpfWeight ( self . szk . typ . encode_measurement ( weight) ?) ;
274- beta. 0 . insert ( 0 , T :: Field :: one ( ) ) ;
268+ let encoded_weight = self . szk . typ . encode_measurement ( weight) ?;
269+ let mut beta = Vec :: with_capacity ( 1 + self . szk . typ . output_len ( ) ) ;
270+ beta. push ( T :: Field :: one ( ) ) ;
271+ beta. append ( & mut self . szk . typ . truncate ( encoded_weight. clone ( ) ) ?) ;
275272
276273 // Compute the measurement shares for each aggregator by generating VIDPF
277274 // keys for the measurement and evaluating each of them.
278- let public_share = self
279- . vidpf
280- . gen_with_keys ( ctx, & vidpf_keys, alpha, & beta, nonce) ?;
275+ let public_share =
276+ self . vidpf
277+ . gen_with_keys ( ctx, & vidpf_keys, alpha, & VidpfWeight ( beta) , nonce) ?;
281278
282- let leader_beta_share = self . vidpf . get_beta_share (
283- ctx,
284- VidpfServerId :: S0 ,
285- & public_share,
286- & vidpf_keys[ 0 ] ,
287- nonce,
288- ) ?;
289- let helper_beta_share = self . vidpf . get_beta_share (
290- ctx,
291- VidpfServerId :: S1 ,
292- & public_share,
293- & vidpf_keys[ 1 ] ,
294- nonce,
295- ) ?;
296-
297- let [ leader_szk_proof_share, helper_szk_proof_share] = self . szk . prove (
298- ctx,
299- & leader_beta_share. as_ref ( ) [ 1 ..] ,
300- & helper_beta_share. as_ref ( ) [ 1 ..] ,
301- & beta. as_ref ( ) [ 1 ..] ,
302- szk_random,
303- joint_random_opt,
304- nonce,
305- ) ?;
279+ let [ leader_szk_input_share, helper_szk_input_share] =
280+ self . szk
281+ . prove ( ctx, & encoded_weight, szk_random, joint_random_opt, nonce) ?;
306282 let [ leader_vidpf_key, helper_vidpf_key] = vidpf_keys;
307283 let leader_share = MasticInputShare {
308284 vidpf_key : leader_vidpf_key,
309- proof_share : leader_szk_proof_share ,
285+ szk_input_share : leader_szk_input_share ,
310286 } ;
311287 let helper_share = MasticInputShare {
312288 vidpf_key : helper_vidpf_key,
313- proof_share : helper_szk_proof_share ,
289+ szk_input_share : helper_szk_input_share ,
314290 } ;
315291 Ok ( ( public_share, vec ! [ leader_share, helper_share] ) )
316292 }
@@ -405,15 +381,15 @@ impl<'a, T: Type> ParameterizedDecode<(&'a Mastic<T>, &'a MasticAggregationParam
405381#[ derive( Clone , Debug , PartialEq ) ]
406382pub struct MasticPrepareShare < F : FieldElement > {
407383 /// [`Vidpf`] evaluation proof, which guarantees one-hotness and payload consistency.
408- eval_proof : [ u8 ; VIDPF_PROOF_SIZE ] ,
384+ vidpf_eval_proof : [ u8 ; VIDPF_PROOF_SIZE ] ,
409385
410386 /// If [`Szk`]` verification of the root weight is needed, a verification message.
411387 szk_query_share_opt : Option < SzkQueryShare < F > > ,
412388}
413389
414390impl < F : FieldElement > Encode for MasticPrepareShare < F > {
415391 fn encode ( & self , bytes : & mut Vec < u8 > ) -> Result < ( ) , CodecError > {
416- bytes. extend_from_slice ( & self . eval_proof ) ;
392+ bytes. extend_from_slice ( & self . vidpf_eval_proof ) ;
417393 match & self . szk_query_share_opt {
418394 Some ( query_share) => query_share. encode ( bytes) ,
419395 None => Ok ( ( ) ) ,
@@ -436,8 +412,8 @@ impl<F: FieldElement> ParameterizedDecode<MasticPrepareState<F>> for MasticPrepa
436412 prep_state : & MasticPrepareState < F > ,
437413 bytes : & mut Cursor < & [ u8 ] > ,
438414 ) -> Result < Self , CodecError > {
439- let mut eval_proof = [ 0 ; VIDPF_PROOF_SIZE ] ;
440- bytes. read_exact ( & mut eval_proof [ ..] ) ?;
415+ let mut vidpf_eval_proof = [ 0 ; VIDPF_PROOF_SIZE ] ;
416+ bytes. read_exact ( & mut vidpf_eval_proof [ ..] ) ?;
441417 let requires_joint_rand = prep_state. szk_query_state . is_some ( ) ;
442418 let szk_query_share_opt = prep_state
443419 . verifier_len
@@ -446,7 +422,7 @@ impl<F: FieldElement> ParameterizedDecode<MasticPrepareState<F>> for MasticPrepa
446422 } )
447423 . transpose ( ) ?;
448424 Ok ( Self {
449- eval_proof ,
425+ vidpf_eval_proof ,
450426 szk_query_share_opt,
451427 } )
452428 }
@@ -523,6 +499,32 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
523499 & mut prefix_tree,
524500 ) ?;
525501
502+ // Set the weight of the root node to the weight we expect for each level of the three.
503+ {
504+ let encoded_weight_share = match input_share. szk_input_share {
505+ SzkInputShare :: Leader {
506+ ref uncompressed_meas_share,
507+ ..
508+ } => uncompressed_meas_share. clone ( ) ,
509+ SzkInputShare :: Helper {
510+ ref share_seed_and_blind,
511+ ..
512+ } => self . szk . derive_helper_meas_share ( share_seed_and_blind, ctx) ,
513+ } ;
514+
515+ let mut beta_share = Vec :: with_capacity ( 1 + self . szk . typ . output_len ( ) ) ;
516+ beta_share. push ( T :: Field :: zero ( ) ) ;
517+ beta_share. append ( & mut self . szk . typ . truncate ( encoded_weight_share) ?) ;
518+ if agg_id == 1 {
519+ beta_share[ 0 ] = T :: Field :: one ( ) ;
520+ for x in beta_share. iter_mut ( ) {
521+ * x = -* x;
522+ }
523+ }
524+
525+ prefix_tree. root . as_mut ( ) . unwrap ( ) . value . share = VidpfWeight ( beta_share) ;
526+ }
527+
526528 let root = prefix_tree. root . as_ref ( ) . unwrap ( ) ;
527529
528530 // Onehot and payload checks
@@ -539,11 +541,12 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
539541
540542 // Traverse the prefix tree breadth-first.
541543 let mut q = VecDeque :: with_capacity ( 100 ) ;
542- q. push_back ( root. left . as_ref ( ) . unwrap ( ) ) ;
543- q. push_back ( root. right . as_ref ( ) . unwrap ( ) ) ;
544+ q. push_back ( root) ;
544545 while let Some ( node) = q. pop_front ( ) {
545546 // Update onehot proof.
546- onehot_check_xof. update ( & node. value . state . node_proof ) ;
547+ if let Some ( ref node_proof) = node. value . state . node_proof {
548+ onehot_check_xof. update ( node_proof) ;
549+ }
547550
548551 // Update payload check.
549552 if let ( Some ( left) , Some ( right) ) = ( node. left . as_ref ( ) , node. right . as_ref ( ) ) {
@@ -583,7 +586,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
583586 c. get_encoded ( ) . unwrap ( )
584587 } ;
585588
586- let eval_proof = {
589+ let vidpf_eval_proof = {
587590 let mut eval_proof_xof =
588591 XofTurboShake128 :: init ( verify_key, & [ & dst_usage ( USAGE_EVAL_PROOF ) , & self . id , ctx] ) ;
589592 eval_proof_xof. update ( & onehot_check) ;
@@ -592,53 +595,48 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
592595 eval_proof_xof. into_seed ( ) . 0
593596 } ;
594597
595- let mut truncated_out_shares =
596- Vec :: with_capacity ( self . szk . typ . output_len ( ) * prefixes. len ( ) ) ;
597- for VidpfWeight ( mut out_share) in out_shares. into_iter ( ) {
598- let mut truncated_out_share = self . szk . typ . truncate ( out_share. drain ( 1 ..) . collect ( ) ) ?;
599- truncated_out_shares. append ( & mut out_share) ;
600- truncated_out_shares. append ( & mut truncated_out_share) ;
601- }
598+ let output_shares = MasticOutputShare :: from (
599+ out_shares
600+ . into_iter ( )
601+ . flat_map ( |VidpfWeight ( out_share) | out_share)
602+ . collect :: < Vec < _ > > ( ) ,
603+ ) ;
602604
603605 Ok ( if agg_param. require_weight_check {
604606 // Range check.
605- let VidpfWeight ( beta_share) =
606- self . vidpf
607- . get_beta_share ( ctx, id, public_share, & input_share. vidpf_key , nonce) ?;
608607 let ( szk_query_share, szk_query_state) = self . szk . query (
609608 ctx,
610609 agg_param
611610 . level_and_prefixes
612611 . level ( )
613612 . try_into ( )
614613 . map_err ( |_| VdafError :: Vidpf ( VidpfError :: InvalidInputLength ) ) ?,
615- & beta_share[ 1 ..] ,
616- & input_share. proof_share ,
614+ & input_share. szk_input_share ,
617615 verify_key,
618616 nonce,
619617 ) ?;
620618
621619 let verifier_len = szk_query_share. flp_verifier . len ( ) ;
622620 (
623621 MasticPrepareState {
624- output_shares : MasticOutputShare :: from ( truncated_out_shares ) ,
622+ output_shares,
625623 szk_query_state,
626624 verifier_len : Some ( verifier_len) ,
627625 } ,
628626 MasticPrepareShare {
629- eval_proof ,
627+ vidpf_eval_proof ,
630628 szk_query_share_opt : Some ( szk_query_share) ,
631629 } ,
632630 )
633631 } else {
634632 (
635633 MasticPrepareState {
636- output_shares : MasticOutputShare :: from ( truncated_out_shares ) ,
634+ output_shares,
637635 szk_query_state : None ,
638636 verifier_len : None ,
639637 } ,
640638 MasticPrepareShare {
641- eval_proof ,
639+ vidpf_eval_proof ,
642640 szk_query_share_opt : None ,
643641 } ,
644642 )
@@ -663,7 +661,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
663661 "Received more than two prepare shares" . to_string ( ) ,
664662 ) ) ;
665663 } ;
666- if leader_share. eval_proof != helper_share. eval_proof {
664+ if leader_share. vidpf_eval_proof != helper_share. vidpf_eval_proof {
667665 return Err ( VdafError :: Uncategorized (
668666 "Vidpf proof verification failed" . to_string ( ) ,
669667 ) ) ;
0 commit comments