2
2
3
3
use ark_ec:: CurveGroup ;
4
4
use ark_poly:: { DenseUVPolynomial , Polynomial , univariate:: DensePolynomial } ;
5
+ use ark_serialize:: serialize_to_vec;
5
6
use ark_std:: marker:: PhantomData ;
6
7
use ark_std:: rand:: Rng ;
7
8
use std:: { iter:: successors, num:: NonZeroU32 } ;
@@ -29,6 +30,44 @@ impl FeldmanVssPublicParam {
29
30
}
30
31
}
31
32
33
+ impl < C : CurveGroup > FeldmanVss < C > {
34
+ /// sample a random polynomial for VSS `secret`, returns the poly and its feldman commitment
35
+ pub ( crate ) fn rand_poly_and_commit < R : Rng > (
36
+ pp : & FeldmanVssPublicParam ,
37
+ secret : C :: ScalarField ,
38
+ rng : & mut R ,
39
+ ) -> ( DensePolynomial < C :: ScalarField > , Vec < C :: Affine > ) {
40
+ // sample random polynomial of degree t-1 (s.t. any t evaluations can interpolate this poly)
41
+ // f(X) = Sum a_i * X^i
42
+ let mut poly = DensePolynomial :: < C :: ScalarField > :: rand ( pp. t . get ( ) as usize - 1 , rng) ;
43
+ // f(0) = a_0 set to the secret, this index access will never panic since t>0
44
+ poly. coeffs [ 0 ] = secret;
45
+
46
+ // prepare commitment, u = (g^a_0, g^a_1, ..., g^a_t-1)
47
+ let commitment = C :: generator ( ) . batch_mul ( & poly. coeffs ) ;
48
+
49
+ ( poly, commitment)
50
+ }
51
+
52
+ /// given a secret-embedded polynomial, compute the Shamir secret shares
53
+ /// node i \in {0,.. ,n-1} get f(i+1)
54
+ pub ( crate ) fn compute_shares (
55
+ pp : & FeldmanVssPublicParam ,
56
+ poly : & DensePolynomial < C :: ScalarField > ,
57
+ ) -> impl Iterator < Item = C :: ScalarField > {
58
+ ( 0 ..pp. n . get ( ) ) . map ( |node_idx| poly. evaluate ( & ( node_idx + 1 ) . into ( ) ) )
59
+ }
60
+
61
+ /// same as [`Self::compute_shares()`], but output an iterator of bytes
62
+ pub ( crate ) fn compute_serialized_shares (
63
+ pp : & FeldmanVssPublicParam ,
64
+ poly : & DensePolynomial < C :: ScalarField > ,
65
+ ) -> impl Iterator < Item = Vec < u8 > > {
66
+ Self :: compute_shares ( pp, poly)
67
+ . map ( |s| serialize_to_vec ! [ s] . expect ( "ark_serialize valid shares never panic" ) )
68
+ }
69
+ }
70
+
32
71
impl < C : CurveGroup > VerifiableSecretSharing for FeldmanVss < C > {
33
72
type PublicParam = FeldmanVssPublicParam ;
34
73
type Secret = C :: ScalarField ;
@@ -40,29 +79,17 @@ impl<C: CurveGroup> VerifiableSecretSharing for FeldmanVss<C> {
40
79
rng : & mut R ,
41
80
secret : Self :: Secret ,
42
81
) -> ( Vec < Self :: SecretShare > , Self :: Commitment ) {
43
- // sample random polynomial of degree t-1 (s.t. any t evaluations can interpolate this poly)
44
- // f(X) = Sum a_i * X^i
45
- let mut poly = DensePolynomial :: < Self :: Secret > :: rand ( pp. t . get ( ) as usize - 1 , rng) ;
46
- // f(0) = a_0 set to the secret, this index access will never panic since t>0
47
- poly. coeffs [ 0 ] = secret;
48
-
49
- // prepare shares, node i \in {0,.. ,n-1} get f(i+1)
50
- let shares: Vec < Self :: SecretShare > = ( 0 ..pp. n . get ( ) )
51
- . map ( |node_idx| poly. evaluate ( & ( node_idx + 1 ) . into ( ) ) )
52
- . collect ( ) ;
53
-
54
- // prepare commitment, u = (g^a_0, g^a_1, ..., g^a_t-1)
55
- let commitment = C :: generator ( ) . batch_mul ( & poly. coeffs ) ;
56
-
57
- ( shares, commitment)
82
+ let ( poly, comm) = Self :: rand_poly_and_commit ( pp, secret, rng) ;
83
+ let shares = Self :: compute_shares ( pp, & poly) . collect ( ) ;
84
+ ( shares, comm)
58
85
}
59
86
60
87
fn verify (
61
88
pp : & Self :: PublicParam ,
62
89
node_idx : usize ,
63
90
share : & Self :: SecretShare ,
64
91
commitment : & Self :: Commitment ,
65
- ) -> Result < bool , VssError > {
92
+ ) -> Result < ( ) , VssError > {
66
93
let n = pp. n . get ( ) as usize ;
67
94
let t = pp. t . get ( ) as usize ;
68
95
@@ -86,7 +113,11 @@ impl<C: CurveGroup> VerifiableSecretSharing for FeldmanVss<C> {
86
113
VssError :: InternalError ( "commitments and powers mismatched length" . to_string ( ) )
87
114
} ) ?;
88
115
89
- Ok ( C :: generator ( ) . mul ( share) == eval_in_exp)
116
+ if C :: generator ( ) . mul ( share) == eval_in_exp {
117
+ Ok ( ( ) )
118
+ } else {
119
+ Err ( VssError :: FailedVerification )
120
+ }
90
121
}
91
122
92
123
fn reconstruct (
@@ -140,29 +171,27 @@ mod tests {
140
171
let ( shares, commitment) = FeldmanVss :: < C > :: share ( & pp, rng, secret) ;
141
172
for ( node_idx, s) in shares. iter ( ) . enumerate ( ) {
142
173
// happy path
143
- assert ! ( FeldmanVss :: <C >:: verify( & pp, node_idx, s, & commitment) . unwrap ( ) ) ;
174
+ assert ! ( FeldmanVss :: <C >:: verify( & pp, node_idx, s, & commitment) . is_ok ( ) ) ;
144
175
145
176
// sad path
146
177
// wrong node_idx should fail
147
- assert ! (
148
- !FeldmanVss :: <C >:: verify( & pp, node_idx + 1 , s, & commitment) . unwrap_or( false )
149
- ) ;
178
+ assert ! ( FeldmanVss :: <C >:: verify( & pp, node_idx + 1 , s, & commitment) . is_err( ) ) ;
150
179
151
180
// wrong secret share should fail
152
181
assert ! (
153
- ! FeldmanVss :: <C >:: verify(
182
+ FeldmanVss :: <C >:: verify(
154
183
& pp,
155
184
node_idx,
156
185
& C :: ScalarField :: rand( rng) ,
157
186
& commitment,
158
187
)
159
- . unwrap ( )
188
+ . is_err ( )
160
189
) ;
161
190
162
191
// wrong commitment should fail
163
192
let mut bad_comm = commitment. clone ( ) ;
164
193
bad_comm[ 1 ] = C :: Affine :: default ( ) ;
165
- assert ! ( ! FeldmanVss :: <C >:: verify( & pp, node_idx, s, & bad_comm) . unwrap ( ) ) ;
194
+ assert ! ( FeldmanVss :: <C >:: verify( & pp, node_idx, s, & bad_comm) . is_err ( ) ) ;
166
195
167
196
// incomplete/dropped commitment should fail
168
197
bad_comm. pop ( ) ;
0 commit comments