1
1
//! Gadgets for elliptic curve operations.
2
2
3
- use std:: fmt;
3
+ use std:: fmt:: Debug ;
4
4
5
5
use halo2:: {
6
6
arithmetic:: CurveAffine ,
@@ -9,31 +9,50 @@ use halo2::{
9
9
} ;
10
10
11
11
/// Trait allowing circuit's fixed points to be enumerated.
12
- pub trait FixedPoints < C : CurveAffine > : Clone + fmt :: Debug { }
12
+ pub trait FixedPoints < C : CurveAffine > : Clone + Debug { }
13
13
14
14
/// The set of circuit instructions required to use the ECC gadgets.
15
15
pub trait EccInstructions < C : CurveAffine > : Chip < C :: Base > {
16
+ /// Variable representing an element of the elliptic curve's base field, that
17
+ /// is used as a scalar in variable-base scalar mul.
18
+ ///
19
+ /// It is not true in general that a scalar field element fits in a curve's
20
+ /// base field, and in particular it is untrue for the Pallas curve, whose
21
+ /// scalar field `Fq` is larger than its base field `Fp`.
22
+ ///
23
+ /// However, the only use of variable-base scalar mul in the Orchard protocol
24
+ /// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed
25
+ /// to be in the base field of the curve. (See non-normative notes in
26
+ /// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.)
27
+ type ScalarVar : Clone + Debug ;
16
28
/// Variable representing a full-width element of the elliptic curve's scalar field, to be used for fixed-base scalar mul.
17
- type ScalarFixed : Clone + fmt :: Debug ;
29
+ type ScalarFixed : Clone + Debug ;
18
30
/// Variable representing a signed short element of the elliptic curve's scalar field, to be used for fixed-base scalar mul.
19
- type ScalarFixedShort : Clone + fmt :: Debug ;
31
+ type ScalarFixedShort : Clone + Debug ;
20
32
/// Variable representing an elliptic curve point.
21
- type Point : Clone + fmt :: Debug ;
33
+ type Point : Clone + Debug ;
22
34
/// Variable representing the x-coordinate of an elliptic curve point.
23
- type X : Clone + fmt :: Debug ;
35
+ type X : Clone + Debug ;
24
36
/// Variable representing the set of fixed bases in the circuit.
25
37
type FixedPoints : FixedPoints < C > ;
26
38
/// Variable representing a fixed elliptic curve point (constant in the circuit).
27
- type FixedPoint : Clone + fmt :: Debug ;
39
+ type FixedPoint : Clone + Debug ;
28
40
29
- /// Witnesses the given full-width scalar as a private input to the circuit for fixed-based scalar mul.
41
+ /// Witnesses the given base field element as a private input to the circuit for variable-base scalar mul.
42
+ fn witness_scalar_var (
43
+ & self ,
44
+ layouter : & mut impl Layouter < C :: Base > ,
45
+ value : Option < C :: Base > ,
46
+ ) -> Result < Self :: ScalarVar , Error > ;
47
+
48
+ /// Witnesses the given full-width scalar as a private input to the circuit for fixed-base scalar mul.
30
49
fn witness_scalar_fixed (
31
50
& self ,
32
51
layouter : & mut impl Layouter < C :: Base > ,
33
52
value : Option < C :: Scalar > ,
34
53
) -> Result < Self :: ScalarFixed , Error > ;
35
54
36
- /// Witnesses the given signed short scalar as a private input to the circuit for fixed-based scalar mul.
55
+ /// Witnesses the given signed short scalar as a private input to the circuit for fixed-base scalar mul.
37
56
fn witness_scalar_fixed_short (
38
57
& self ,
39
58
layouter : & mut impl Layouter < C :: Base > ,
@@ -50,19 +69,21 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
50
69
/// Extracts the x-coordinate of a point.
51
70
fn extract_p ( point : & Self :: Point ) -> & Self :: X ;
52
71
53
- /// Gets a fixed point into the circuit.
72
+ /// Returns a fixed point that had been previously loaded into the circuit.
73
+ /// The pre-loaded cells are used to set up equality constraints in other
74
+ /// parts of the circuit where the fixed base is used.
54
75
fn get_fixed ( & self , fixed_points : Self :: FixedPoints ) -> Result < Self :: FixedPoint , Error > ;
55
76
56
- /// Performs point addition, returning `a + b`.
57
- fn add (
77
+ /// Performs incomplete point addition, returning `a + b`.
78
+ fn add_incomplete (
58
79
& self ,
59
80
layouter : & mut impl Layouter < C :: Base > ,
60
81
a : & Self :: Point ,
61
82
b : & Self :: Point ,
62
83
) -> Result < Self :: Point , Error > ;
63
84
64
85
/// Performs complete point addition, returning `a + b`.
65
- fn add_complete (
86
+ fn add (
66
87
& self ,
67
88
layouter : & mut impl Layouter < C :: Base > ,
68
89
a : & Self :: Point ,
@@ -73,7 +94,7 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
73
94
fn mul (
74
95
& self ,
75
96
layouter : & mut impl Layouter < C :: Base > ,
76
- scalar : C :: Scalar ,
97
+ scalar : & Self :: ScalarVar ,
77
98
base : & Self :: Point ,
78
99
) -> Result < Self :: Point , Error > ;
79
100
@@ -94,70 +115,77 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
94
115
) -> Result < Self :: Point , Error > ;
95
116
}
96
117
118
+ /// An element of the given elliptic curve's base field, that is used as a scalar
119
+ /// in variable-base scalar mul.
120
+ ///
121
+ /// It is not true in general that a scalar field element fits in a curve's
122
+ /// base field, and in particular it is untrue for the Pallas curve, whose
123
+ /// scalar field `Fq` is larger than its base field `Fp`.
124
+ ///
125
+ /// However, the only use of variable-base scalar mul in the Orchard protocol
126
+ /// is in deriving diversified addresses `[ivk] g_d`, and `ivk` is guaranteed
127
+ /// to be in the base field of the curve. (See non-normative notes in
128
+ /// https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents.)
129
+ #[ derive( Debug ) ]
130
+ pub struct ScalarVar < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
131
+ chip : EccChip ,
132
+ inner : EccChip :: ScalarVar ,
133
+ }
134
+
97
135
/// A full-width element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
98
136
#[ derive( Debug ) ]
99
- pub struct ScalarFixed < C : CurveAffine , EccChip : EccInstructions < C > + Clone > {
137
+ pub struct ScalarFixed < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
100
138
chip : EccChip ,
101
139
inner : EccChip :: ScalarFixed ,
102
140
}
103
141
104
- impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone > ScalarFixed < C , EccChip > {
142
+ impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > ScalarFixed < C , EccChip > {
105
143
/// Constructs a new ScalarFixed with the given value.
106
144
pub fn new (
107
145
chip : EccChip ,
108
146
mut layouter : impl Layouter < C :: Base > ,
109
147
value : Option < C :: Scalar > ,
110
148
) -> Result < Self , Error > {
111
149
chip. witness_scalar_fixed ( & mut layouter, value)
112
- . map ( |inner| ScalarFixed {
113
- chip : chip. clone ( ) ,
114
- inner,
115
- } )
150
+ . map ( |inner| ScalarFixed { chip, inner } )
116
151
}
117
152
}
118
153
119
154
/// A signed short element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
120
155
#[ derive( Debug ) ]
121
- pub struct ScalarFixedShort < C : CurveAffine , EccChip : EccInstructions < C > + Clone > {
156
+ pub struct ScalarFixedShort < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
122
157
chip : EccChip ,
123
158
inner : EccChip :: ScalarFixedShort ,
124
159
}
125
160
126
- impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone > ScalarFixedShort < C , EccChip > {
161
+ impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > ScalarFixedShort < C , EccChip > {
127
162
/// Constructs a new ScalarFixedShort with the given value.
128
163
pub fn new (
129
164
chip : EccChip ,
130
165
mut layouter : impl Layouter < C :: Base > ,
131
166
value : Option < C :: Scalar > ,
132
167
) -> Result < Self , Error > {
133
168
chip. witness_scalar_fixed_short ( & mut layouter, value)
134
- . map ( |inner| ScalarFixedShort {
135
- chip : chip. clone ( ) ,
136
- inner,
137
- } )
169
+ . map ( |inner| ScalarFixedShort { chip, inner } )
138
170
}
139
171
}
140
172
141
173
/// An elliptic curve point over the given curve.
142
174
#[ derive( Debug ) ]
143
- pub struct Point < C : CurveAffine , EccChip : EccInstructions < C > + Clone > {
175
+ pub struct Point < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
144
176
chip : EccChip ,
145
177
inner : EccChip :: Point ,
146
178
}
147
179
148
- impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone > Point < C , EccChip > {
180
+ impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > Point < C , EccChip > {
149
181
/// Constructs a new point with the given value.
150
182
pub fn new (
151
- & self ,
183
+ chip : EccChip ,
152
184
mut layouter : impl Layouter < C :: Base > ,
153
185
value : Option < C > ,
154
186
) -> Result < Self , Error > {
155
- self . chip
156
- . witness_point ( & mut layouter, value)
157
- . map ( |inner| Point {
158
- chip : self . chip . clone ( ) ,
159
- inner,
160
- } )
187
+ let point = chip. witness_point ( & mut layouter, value) ;
188
+ point. map ( |inner| Point { chip, inner } )
161
189
}
162
190
163
191
/// Extracts the x-coordinate of a point.
@@ -172,6 +200,7 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
172
200
173
201
/// Returns `self + other`.
174
202
pub fn add ( & self , mut layouter : impl Layouter < C :: Base > , other : & Self ) -> Result < Self , Error > {
203
+ assert_eq ! ( format!( "{:?}" , self . chip) , format!( "{:?}" , other. chip) ) ;
175
204
self . chip
176
205
. add ( & mut layouter, & self . inner , & other. inner )
177
206
. map ( |inner| Point {
@@ -181,9 +210,14 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
181
210
}
182
211
183
212
/// Returns `[by] self`.
184
- pub fn mul ( & self , mut layouter : impl Layouter < C :: Base > , by : C :: Scalar ) -> Result < Self , Error > {
213
+ pub fn mul (
214
+ & self ,
215
+ mut layouter : impl Layouter < C :: Base > ,
216
+ by : & ScalarVar < C , EccChip > ,
217
+ ) -> Result < Self , Error > {
218
+ assert_eq ! ( format!( "{:?}" , self . chip) , format!( "{:?}" , by. chip) ) ;
185
219
self . chip
186
- . mul ( & mut layouter, by , & self . inner )
220
+ . mul ( & mut layouter, & by . inner , & self . inner )
187
221
. map ( |inner| Point {
188
222
chip : self . chip . clone ( ) ,
189
223
inner,
@@ -193,12 +227,12 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
193
227
194
228
/// The x-coordinate of an elliptic curve point over the given curve.
195
229
#[ derive( Debug ) ]
196
- pub struct X < C : CurveAffine , EccChip : EccInstructions < C > + Clone > {
230
+ pub struct X < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
197
231
chip : EccChip ,
198
232
inner : EccChip :: X ,
199
233
}
200
234
201
- impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone > X < C , EccChip > {
235
+ impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > X < C , EccChip > {
202
236
/// Wraps the given x-coordinate (obtained directly from an instruction) in a gadget.
203
237
pub fn from_inner ( chip : EccChip , inner : EccChip :: X ) -> Self {
204
238
X { chip, inner }
@@ -208,18 +242,16 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> X<C, EccChip> {
208
242
/// A constant elliptic curve point over the given curve, for which scalar multiplication
209
243
/// is more efficient.
210
244
#[ derive( Clone , Debug ) ]
211
- pub struct FixedPoint < C : CurveAffine , EccChip : EccInstructions < C > + Clone > {
245
+ pub struct FixedPoint < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > {
212
246
chip : EccChip ,
213
247
inner : EccChip :: FixedPoint ,
214
248
}
215
249
216
- impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone > FixedPoint < C , EccChip > {
250
+ impl < C : CurveAffine , EccChip : EccInstructions < C > + Clone + Debug > FixedPoint < C , EccChip > {
217
251
/// Gets a reference to the specified fixed point in the circuit.
218
252
pub fn get ( chip : EccChip , point : EccChip :: FixedPoints ) -> Result < Self , Error > {
219
- chip. get_fixed ( point) . map ( |inner| FixedPoint {
220
- chip : chip. clone ( ) ,
221
- inner,
222
- } )
253
+ chip. get_fixed ( point)
254
+ . map ( |inner| FixedPoint { chip, inner } )
223
255
}
224
256
225
257
/// Returns `[by] self`.
@@ -228,6 +260,7 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> FixedPoint<C, EccChip>
228
260
mut layouter : impl Layouter < C :: Base > ,
229
261
by : & ScalarFixed < C , EccChip > ,
230
262
) -> Result < Point < C , EccChip > , Error > {
263
+ assert_eq ! ( format!( "{:?}" , self . chip) , format!( "{:?}" , by. chip) ) ;
231
264
self . chip
232
265
. mul_fixed ( & mut layouter, & by. inner , & self . inner )
233
266
. map ( |inner| Point {
0 commit comments