1
1
//! Implementation of Feldman VSS
2
2
3
- use ark_ec:: CurveGroup ;
3
+ use ark_ec:: { CurveGroup , scalar_mul :: BatchMulPreprocessing } ;
4
4
use ark_poly:: { DenseUVPolynomial , Polynomial , univariate:: DensePolynomial } ;
5
5
use ark_serialize:: { CanonicalSerialize , SerializationError , serialize_to_vec} ;
6
6
use ark_std:: marker:: PhantomData ;
7
7
use ark_std:: rand:: Rng ;
8
- use derive_more:: { Deref , From , IntoIterator } ;
8
+ use derive_more:: { Debug , Deref , From , IntoIterator } ;
9
9
use multisig:: Committee ;
10
10
use rayon:: prelude:: * ;
11
11
use serde:: { Deserialize , Serialize } ;
12
12
use serde_with:: serde_as;
13
- use std:: { iter:: successors, num:: NonZeroUsize , ops:: Add } ;
13
+ use std:: { iter:: successors, num:: NonZeroUsize , ops:: Add , sync :: Arc } ;
14
14
15
15
use crate :: {
16
16
interpolation:: { interpolate, interpolate_in_exponent} ,
@@ -21,23 +21,48 @@ use crate::{
21
21
#[ derive( Debug , Clone ) ]
22
22
pub struct FeldmanVss < C : CurveGroup > ( PhantomData < C > ) ;
23
23
24
- #[ derive( Debug , Clone , Copy ) ]
25
- pub struct FeldmanVssPublicParam {
24
+ #[ derive( Debug , Clone ) ]
25
+ pub struct FeldmanVssPublicParam < C : CurveGroup > {
26
26
// reconstruction threshold t
27
27
pub t : NonZeroUsize ,
28
28
// total number of nodes
29
29
pub n : NonZeroUsize ,
30
+
31
+ // preprocessing lookup table to accelerate batch_mul
32
+ #[ debug( skip) ]
33
+ table : Option < Arc < BatchMulPreprocessing < C > > > ,
30
34
}
31
35
32
- impl FeldmanVssPublicParam {
36
+ impl < C : CurveGroup > FeldmanVssPublicParam < C > {
33
37
pub fn new ( t : NonZeroUsize , n : NonZeroUsize ) -> Self {
34
- Self { t, n }
38
+ Self { t, n, table : None }
35
39
}
36
40
37
41
pub fn from ( c : & Committee ) -> Self {
38
42
Self :: new ( c. one_honest_threshold ( ) , c. size ( ) )
39
43
}
40
44
45
+ /// `Self::from().with_lookup_table()`: this precompute a lookup table for faster commit
46
+ pub fn with_lookup_table ( self ) -> Self {
47
+ let table = BatchMulPreprocessing :: new ( C :: generator ( ) , self . t . get ( ) ) ;
48
+ Self {
49
+ t : self . t ,
50
+ n : self . n ,
51
+ table : Some ( Arc :: new ( table) ) ,
52
+ }
53
+ }
54
+
55
+ /// compute Feldman commit (potentially with accelerated lookup table)
56
+ /// ASSUME: coeffs has length t, we skip checks and avoid returning Result, not publicly visble
57
+ pub ( crate ) fn commit ( & self , coeffs : & [ C :: ScalarField ] ) -> FeldmanCommitment < C > {
58
+ if let Some ( table) = self . table . as_ref ( ) {
59
+ table. batch_mul ( coeffs) . into ( )
60
+ } else {
61
+ let base = C :: generator ( ) ;
62
+ FeldmanCommitment :: new ( coeffs. par_iter ( ) . map ( |s| base * s) . collect :: < Vec < _ > > ( ) )
63
+ }
64
+ }
65
+
41
66
pub fn threshold ( & self ) -> usize {
42
67
self . t . get ( )
43
68
}
@@ -50,7 +75,7 @@ impl FeldmanVssPublicParam {
50
75
impl < C : CurveGroup > FeldmanVss < C > {
51
76
/// sample a random polynomial for VSS `secret`, returns the poly and its feldman commitment
52
77
pub ( crate ) fn rand_poly_and_commit < R : Rng > (
53
- pp : & FeldmanVssPublicParam ,
78
+ pp : & FeldmanVssPublicParam < C > ,
54
79
secret : C :: ScalarField ,
55
80
rng : & mut R ,
56
81
) -> ( DensePolynomial < C :: ScalarField > , FeldmanCommitment < C > ) {
@@ -61,23 +86,23 @@ impl<C: CurveGroup> FeldmanVss<C> {
61
86
poly. coeffs [ 0 ] = secret;
62
87
63
88
// prepare commitment, u = (g^a_0, g^a_1, ..., g^a_t-1)
64
- let commitment = C :: generator ( ) . batch_mul ( & poly. coeffs ) ;
89
+ let commitment = pp . commit ( & poly. coeffs ) ;
65
90
66
- ( poly, commitment. into ( ) )
91
+ ( poly, commitment)
67
92
}
68
93
69
94
/// given a secret-embedded polynomial, compute the Shamir secret shares
70
95
/// node i \in {0,.. ,n-1} get f(i+1)
71
96
pub ( crate ) fn compute_shares (
72
- pp : & FeldmanVssPublicParam ,
97
+ pp : & FeldmanVssPublicParam < C > ,
73
98
poly : & DensePolynomial < C :: ScalarField > ,
74
99
) -> impl Iterator < Item = C :: ScalarField > {
75
100
( 0 ..pp. n . get ( ) ) . map ( |node_idx| poly. evaluate ( & ( ( node_idx + 1 ) as u64 ) . into ( ) ) )
76
101
}
77
102
78
103
/// same as [`Self::compute_shares()`], but output an iterator of bytes
79
104
pub ( crate ) fn compute_serialized_shares (
80
- pp : & FeldmanVssPublicParam ,
105
+ pp : & FeldmanVssPublicParam < C > ,
81
106
poly : & DensePolynomial < C :: ScalarField > ,
82
107
) -> impl Iterator < Item = Vec < u8 > > {
83
108
Self :: compute_shares ( pp, poly)
@@ -87,7 +112,7 @@ impl<C: CurveGroup> FeldmanVss<C> {
87
112
/// given the Feldman commitment (\vec{u} in paper), compute the `i`-th node's public share,
88
113
/// which is g^alpha_i where alpha_i is `i`-th secret share.
89
114
pub ( crate ) fn derive_public_share (
90
- pp : & FeldmanVssPublicParam ,
115
+ pp : & FeldmanVssPublicParam < C > ,
91
116
node_idx : usize ,
92
117
commitment : & [ C :: Affine ] ,
93
118
) -> Result < C , VssError > {
@@ -127,7 +152,7 @@ impl<C: CurveGroup> FeldmanVss<C> {
127
152
}
128
153
129
154
impl < C : CurveGroup > VerifiableSecretSharing for FeldmanVss < C > {
130
- type PublicParam = FeldmanVssPublicParam ;
155
+ type PublicParam = FeldmanVssPublicParam < C > ;
131
156
type Secret = C :: ScalarField ;
132
157
type SecretShare = C :: ScalarField ;
133
158
type Commitment = FeldmanCommitment < C > ;
@@ -203,6 +228,12 @@ pub struct FeldmanCommitment<C: CurveGroup> {
203
228
}
204
229
205
230
impl < C : CurveGroup > FeldmanCommitment < C > {
231
+ /// If you already have value in affine form, use `.into()`
232
+ pub fn new ( v : Vec < C > ) -> Self {
233
+ let comm = C :: normalize_batch ( & v) ;
234
+ Self { comm }
235
+ }
236
+
206
237
pub fn to_bytes ( & self ) -> Vec < u8 > {
207
238
bincode:: serde:: encode_to_vec ( self , bincode:: config:: standard ( ) )
208
239
. expect ( "serializing feldman commitment" )
@@ -248,7 +279,7 @@ impl<C: CurveGroup> Add<&FeldmanCommitment<C>> for &FeldmanCommitment<C> {
248
279
249
280
impl < C : CurveGroup > KeyResharing < Self > for FeldmanVss < C > {
250
281
fn reshare < R : Rng > (
251
- new_pp : & FeldmanVssPublicParam ,
282
+ new_pp : & FeldmanVssPublicParam < C > ,
252
283
old_share : & C :: ScalarField ,
253
284
rng : & mut R ,
254
285
) -> ( Vec < C :: ScalarField > , FeldmanCommitment < C > ) {
@@ -258,8 +289,8 @@ impl<C: CurveGroup> KeyResharing<Self> for FeldmanVss<C> {
258
289
}
259
290
260
291
fn verify_reshare (
261
- old_pp : & FeldmanVssPublicParam ,
262
- new_pp : & FeldmanVssPublicParam ,
292
+ old_pp : & FeldmanVssPublicParam < C > ,
293
+ new_pp : & FeldmanVssPublicParam < C > ,
263
294
send_node_idx : usize ,
264
295
recv_node_idx : usize ,
265
296
old_commitment : & FeldmanCommitment < C > ,
@@ -279,8 +310,8 @@ impl<C: CurveGroup> KeyResharing<Self> for FeldmanVss<C> {
279
310
}
280
311
281
312
fn combine (
282
- old_pp : & FeldmanVssPublicParam ,
283
- new_pp : & FeldmanVssPublicParam ,
313
+ old_pp : & FeldmanVssPublicParam < C > ,
314
+ new_pp : & FeldmanVssPublicParam < C > ,
284
315
recv_node_idx : usize ,
285
316
reshares : impl ExactSizeIterator < Item = ( usize , C :: ScalarField , FeldmanCommitment < C > ) > + Clone ,
286
317
) -> Result < ( C :: ScalarField , FeldmanCommitment < C > ) , VssError > {
0 commit comments