@@ -435,7 +435,7 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
435435 Ok ( ( ) )
436436 }
437437
438- /// Serialize the canonical linear relation to bytes.
438+ /// Serialize the linear relation to bytes.
439439 ///
440440 /// The output format is:
441441 /// - [Ne: u32] number of equations
@@ -444,7 +444,7 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
444444 /// - [Nt: u32] number of terms
445445 /// - Nt × [scalar_index: u32, group_index: u32] term entries
446446 /// - Followed by all group elements in serialized form
447- pub fn label ( & self ) -> Result < Vec < u8 > , Error > {
447+ pub fn label ( & self ) -> Vec < u8 > {
448448 let mut out = Vec :: new ( ) ;
449449
450450 // Replicate the original LinearRelationReprBuilder ordering behavior
@@ -473,7 +473,10 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
473473 // Build the RHS terms
474474 let mut rhs_terms = Vec :: new ( ) ;
475475 for ( scalar_var, group_var) in constraint_terms {
476- let group_elem = self . group_elements . get ( * group_var) ?;
476+ let group_elem = self
477+ . group_elements
478+ . get ( * group_var)
479+ . expect ( "Group element not found" ) ;
477480 let group_index = repr_index ( group_elem. to_bytes ( ) ) ;
478481 rhs_terms. push ( ( scalar_var. 0 as u32 , group_index) ) ;
479482 }
@@ -505,19 +508,32 @@ impl<G: PrimeGroup> CanonicalLinearRelation<G> {
505508 out. extend_from_slice ( elem_repr. as_ref ( ) ) ;
506509 }
507510
508- Ok ( out)
511+ out
509512 }
510513}
511514
512- impl < G : PrimeGroup > TryFrom < LinearRelation < G > > for CanonicalLinearRelation < G > {
515+ impl < G : PrimeGroup > TryFrom < & LinearRelation < G > > for CanonicalLinearRelation < G > {
513516 type Error = Error ;
514517
515- fn try_from ( relation : LinearRelation < G > ) -> Result < Self , Self :: Error > {
516- assert_eq ! (
517- relation. image. len( ) ,
518- relation. linear_map. linear_combinations. len( ) ,
519- "Number of equations and image variables must match"
520- ) ;
518+ fn try_from ( relation : & LinearRelation < G > ) -> Result < Self , Self :: Error > {
519+ // Number of equations and image variables must match
520+ if relation. image . len ( ) != relation. linear_map . linear_combinations . len ( ) {
521+ return Err ( Error :: InvalidInstanceWitnessPair ) ;
522+ }
523+
524+ // If the image is the identity, then the relation must be trivial, or else the proof will be unsound
525+ if !relation. image ( ) . is_ok_and ( |img| img. iter ( ) . all ( |& x| x != G :: identity ( ) ) ) {
526+ return Err ( Error :: InvalidInstanceWitnessPair ) ;
527+ }
528+
529+ // Empty relations (without constraints) cannot be proven
530+ if relation. linear_map . linear_combinations . is_empty ( ) {
531+ return Err ( Error :: InvalidInstanceWitnessPair ) ;
532+ }
533+
534+ if relation. linear_map . linear_combinations . iter ( ) . any ( |lc| lc. 0 . is_empty ( ) ) {
535+ return Err ( Error :: InvalidInstanceWitnessPair ) ;
536+ }
521537
522538 let mut canonical = CanonicalLinearRelation :: new ( ) ;
523539 canonical. num_scalars = relation. linear_map . num_scalars ;
@@ -532,7 +548,7 @@ impl<G: PrimeGroup> TryFrom<LinearRelation<G>> for CanonicalLinearRelation<G> {
532548 canonical. process_constraint (
533549 * image_var,
534550 equation,
535- & relation,
551+ relation,
536552 & mut weighted_group_cache,
537553 ) ?;
538554 }
@@ -709,20 +725,6 @@ impl<G: PrimeGroup> LinearRelation<G> {
709725 . collect ( )
710726 }
711727
712- /// Returns a binary label describing the linear map.
713- ///
714- /// The format is:
715- /// - [Ne: u32] number of equations
716- /// - For each equation:
717- /// - [output_point_index: u32]
718- /// - [Nt: u32] number of terms
719- /// - Nt × [scalar_index: u32, point_index: u32] term entries
720- pub fn label ( & self ) -> Vec < u8 > {
721- // XXX. We should return an error if the group elements are not assigned, instead of panicking.
722- let canonical: CanonicalLinearRelation < G > = self . clone ( ) . try_into ( ) . unwrap ( ) ;
723- canonical. label ( ) . unwrap ( )
724- }
725-
726728 /// Convert this LinearRelation into a non-interactive zero-knowledge protocol
727729 /// using the ShakeCodec and a specified context/domain separator.
728730 ///
@@ -758,7 +760,8 @@ impl<G: PrimeGroup> LinearRelation<G> {
758760 self ,
759761 session_identifier : & [ u8 ] ,
760762 ) -> Nizk < SchnorrProof < G > , Shake128DuplexSponge < G > > {
761- let schnorr = SchnorrProof :: from ( self ) ;
763+ let schnorr =
764+ SchnorrProof :: try_from ( self ) . expect ( "Failed to convert LinearRelation to SchnorrProof" ) ;
762765 Nizk :: new ( session_identifier, schnorr)
763766 }
764767}
0 commit comments