1+ //! # Group Morphism and Preimage Handling
2+ //!
3+ //! This module provides utilities for describing and manipulating **linear group morphisms**,
4+ //! supporting sigma protocols over group-based statements (e.g., discrete logarithms, DLEQ proofs). See Maurer09.
5+ //!
6+ //! It includes:
7+ //! - `LinearCombination`: a sparse representation of scalar multiplication relations
8+ //! - `Morphism`: a collection of linear combinations acting on group elements
9+ //! - `GroupMorphismPreimage`: a higher-level structure managing morphisms and their associated images
10+
111use group:: { Group , GroupEncoding } ;
212
13+ /// A sparse linear combination of scalars and group elements.
14+ ///
15+ /// Stores indices into external lists of scalars and group elements.
16+ /// Used to define individual constraints inside a Morphism.
317pub struct LinearCombination {
418 pub scalar_indices : Vec < usize > ,
519 pub element_indices : Vec < usize > ,
620}
721
22+ /// A Morphism represents a list of linear combinations over group elements.
23+ ///
24+ /// It supports dynamic allocation of scalars and elements,
25+ /// and evaluates by performing multi-scalar multiplications.
26+
827pub struct Morphism < G : Group > {
928 pub linear_combination : Vec < LinearCombination > ,
1029 pub group_elements : Vec < G > ,
1130 pub num_scalars : usize ,
1231 pub num_elements : usize ,
1332}
1433
34+ /// Perform a simple multi-scalar multiplication (MSM) over scalars and points.
1535fn msm_pr < G : Group > ( scalars : & [ G :: Scalar ] , bases : & [ G ] ) -> G {
1636 let mut acc = G :: identity ( ) ;
1737 for ( s, p) in scalars. iter ( ) . zip ( bases. iter ( ) ) {
@@ -21,6 +41,7 @@ fn msm_pr<G: Group>(scalars: &[G::Scalar], bases: &[G]) -> G {
2141}
2242
2343impl < G : Group > Morphism < G > {
44+ /// Creates a new empty Morphism.
2445 pub fn new ( ) -> Self {
2546 Self {
2647 linear_combination : Vec :: new ( ) ,
@@ -30,14 +51,19 @@ impl<G: Group> Morphism<G> {
3051 }
3152 }
3253
54+ /// Adds a new linear combination constraint.
3355 pub fn append ( & mut self , lc : LinearCombination ) {
3456 self . linear_combination . push ( lc) ;
3557 }
3658
59+ /// Returns the number of constraint statements.
3760 pub fn num_statements ( & self ) -> usize {
3861 self . linear_combination . len ( )
3962 }
4063
64+ /// Evaluate the Morphism given a set of scalar values.
65+ ///
66+ /// Computes all linear combinations using the provided scalars and returns their group outputs.
4167 pub fn evaluate ( & self , scalars : & [ <G as Group >:: Scalar ] ) -> Vec < G > {
4268 self . linear_combination . iter ( ) . map ( |lc| {
4369 let coefficients: Vec < _ > = lc. scalar_indices . iter ( ) . map ( |& i| scalars[ i] . clone ( ) ) . collect ( ) ;
@@ -47,32 +73,44 @@ impl<G: Group> Morphism<G> {
4773 }
4874}
4975
76+ /// A wrapper struct coupling a Morphism and the corresponding expected image elements.
77+ ///
78+ /// Provides a higher-level API to build proof instances from sparse constraints. The equations are manipulated solely through 2 lists:
79+ /// - the index of a set of Group elements (maintained in Morphism)
80+ /// - the index of a set of scalars (provided as input for the execution)
5081pub struct GroupMorphismPreimage < G >
5182where
5283 G : Group + GroupEncoding ,
5384{
85+ /// The underlying morphism describing the structure of the statement.
5486 pub morphism : Morphism < G > ,
87+ /// Indices pointing to elements representing the "target" images for each constraint.
5588 pub image : Vec < usize > ,
5689}
5790
5891impl < G > GroupMorphismPreimage < G >
5992where
6093 G : Group + GroupEncoding ,
6194{
95+ /// Create a new empty GroupMorphismPreimage.
6296 pub fn new ( ) -> Self {
6397 Self {
6498 morphism : Morphism :: new ( ) ,
6599 image : Vec :: new ( ) ,
66100 }
67101 }
68102
103+ /// Computes the number of bytes needed when serializing all the current commitments.
69104 pub fn commit_bytes_len ( & self ) -> usize {
70105 let repr_len = <G :: Repr as Default >:: default ( )
71106 . as_ref ( )
72107 . len ( ) ; // size of encoded point
73108 self . morphism . num_statements ( ) * repr_len // total size of a commit
74109 }
75110
111+ /// Append a new equation relating scalars to group elements.
112+ ///
113+ /// `lhs` is the index of the image, and `rhs` is a list of (scalar_idx, element_idx) pairs.
76114 pub fn append_equation ( & mut self , lhs : usize , rhs : & [ ( usize , usize ) ] ) {
77115 let lc = LinearCombination {
78116 scalar_indices : rhs. iter ( ) . map ( |& ( s, _) | s) . collect ( ) ,
@@ -82,15 +120,17 @@ where
82120 self . image . push ( lhs) ;
83121 }
84122
85- // Allocate n new Scalar's
123+ /// Allocate space for `n` new scalars and return their indices.
86124 pub fn allocate_scalars ( & mut self , n : usize ) -> Vec < usize > {
87125 let start = self . morphism . num_scalars ;
88126 let indices: Vec < usize > = ( start..start + n) . collect ( ) ;
89127 self . morphism . num_scalars += n;
90128 indices
91129 }
92130
93- // Allocate n new emplacments for Group elements (completed with set_elements for assignation)
131+ /// Allocate space for `n` new group elements and return their indices.
132+ ///
133+ /// The allocated elements are initially set to the identity.
94134 pub fn allocate_elements ( & mut self , n : usize ) -> Vec < usize > {
95135 let start = self . morphism . num_elements ;
96136 let indices: Vec < usize > = ( start..start + n) . collect ( ) ;
@@ -101,12 +141,14 @@ where
101141 indices
102142 }
103143
144+ /// Set the value of group elements at a given index, inside the list of allocated group elements.
104145 pub fn set_elements ( & mut self , elements : & [ ( usize , G ) ] ) {
105146 for & ( i, ref elt) in elements {
106147 self . morphism . group_elements [ i] = elt. clone ( ) ;
107148 }
108149 }
109150
151+ /// Return the group elements corresponding to the image indices.
110152 pub fn image ( & self ) -> Vec < G > {
111153 let mut result = Vec :: new ( ) ;
112154 for i in & self . image {
0 commit comments