Skip to content

Commit 4baf3e1

Browse files
Address review comments
Co-authored-by: Jack Grigg <jack@electriccoin.co>
1 parent 4bf6202 commit 4baf3e1

File tree

1 file changed

+78
-45
lines changed

1 file changed

+78
-45
lines changed

src/circuit/gadget/ecc.rs

+78-45
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Gadgets for elliptic curve operations.
22
3-
use std::fmt;
3+
use std::fmt::Debug;
44

55
use halo2::{
66
arithmetic::CurveAffine,
@@ -9,31 +9,50 @@ use halo2::{
99
};
1010

1111
/// 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 {}
1313

1414
/// The set of circuit instructions required to use the ECC gadgets.
1515
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;
1628
/// 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;
1830
/// 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;
2032
/// Variable representing an elliptic curve point.
21-
type Point: Clone + fmt::Debug;
33+
type Point: Clone + Debug;
2234
/// Variable representing the x-coordinate of an elliptic curve point.
23-
type X: Clone + fmt::Debug;
35+
type X: Clone + Debug;
2436
/// Variable representing the set of fixed bases in the circuit.
2537
type FixedPoints: FixedPoints<C>;
2638
/// Variable representing a fixed elliptic curve point (constant in the circuit).
27-
type FixedPoint: Clone + fmt::Debug;
39+
type FixedPoint: Clone + Debug;
2840

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.
3049
fn witness_scalar_fixed(
3150
&self,
3251
layouter: &mut impl Layouter<C::Base>,
3352
value: Option<C::Scalar>,
3453
) -> Result<Self::ScalarFixed, Error>;
3554

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.
3756
fn witness_scalar_fixed_short(
3857
&self,
3958
layouter: &mut impl Layouter<C::Base>,
@@ -50,19 +69,21 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
5069
/// Extracts the x-coordinate of a point.
5170
fn extract_p(point: &Self::Point) -> &Self::X;
5271

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.
5475
fn get_fixed(&self, fixed_points: Self::FixedPoints) -> Result<Self::FixedPoint, Error>;
5576

56-
/// Performs point addition, returning `a + b`.
57-
fn add(
77+
/// Performs incomplete point addition, returning `a + b`.
78+
fn add_incomplete(
5879
&self,
5980
layouter: &mut impl Layouter<C::Base>,
6081
a: &Self::Point,
6182
b: &Self::Point,
6283
) -> Result<Self::Point, Error>;
6384

6485
/// Performs complete point addition, returning `a + b`.
65-
fn add_complete(
86+
fn add(
6687
&self,
6788
layouter: &mut impl Layouter<C::Base>,
6889
a: &Self::Point,
@@ -73,7 +94,7 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
7394
fn mul(
7495
&self,
7596
layouter: &mut impl Layouter<C::Base>,
76-
scalar: C::Scalar,
97+
scalar: &Self::ScalarVar,
7798
base: &Self::Point,
7899
) -> Result<Self::Point, Error>;
79100

@@ -94,70 +115,77 @@ pub trait EccInstructions<C: CurveAffine>: Chip<C::Base> {
94115
) -> Result<Self::Point, Error>;
95116
}
96117

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+
97135
/// A full-width element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
98136
#[derive(Debug)]
99-
pub struct ScalarFixed<C: CurveAffine, EccChip: EccInstructions<C> + Clone> {
137+
pub struct ScalarFixed<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> {
100138
chip: EccChip,
101139
inner: EccChip::ScalarFixed,
102140
}
103141

104-
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> ScalarFixed<C, EccChip> {
142+
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> ScalarFixed<C, EccChip> {
105143
/// Constructs a new ScalarFixed with the given value.
106144
pub fn new(
107145
chip: EccChip,
108146
mut layouter: impl Layouter<C::Base>,
109147
value: Option<C::Scalar>,
110148
) -> Result<Self, Error> {
111149
chip.witness_scalar_fixed(&mut layouter, value)
112-
.map(|inner| ScalarFixed {
113-
chip: chip.clone(),
114-
inner,
115-
})
150+
.map(|inner| ScalarFixed { chip, inner })
116151
}
117152
}
118153

119154
/// A signed short element of the given elliptic curve's scalar field, to be used for fixed-base scalar mul.
120155
#[derive(Debug)]
121-
pub struct ScalarFixedShort<C: CurveAffine, EccChip: EccInstructions<C> + Clone> {
156+
pub struct ScalarFixedShort<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> {
122157
chip: EccChip,
123158
inner: EccChip::ScalarFixedShort,
124159
}
125160

126-
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> ScalarFixedShort<C, EccChip> {
161+
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> ScalarFixedShort<C, EccChip> {
127162
/// Constructs a new ScalarFixedShort with the given value.
128163
pub fn new(
129164
chip: EccChip,
130165
mut layouter: impl Layouter<C::Base>,
131166
value: Option<C::Scalar>,
132167
) -> Result<Self, Error> {
133168
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 })
138170
}
139171
}
140172

141173
/// An elliptic curve point over the given curve.
142174
#[derive(Debug)]
143-
pub struct Point<C: CurveAffine, EccChip: EccInstructions<C> + Clone> {
175+
pub struct Point<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> {
144176
chip: EccChip,
145177
inner: EccChip::Point,
146178
}
147179

148-
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
180+
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> Point<C, EccChip> {
149181
/// Constructs a new point with the given value.
150182
pub fn new(
151-
&self,
183+
chip: EccChip,
152184
mut layouter: impl Layouter<C::Base>,
153185
value: Option<C>,
154186
) -> 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 })
161189
}
162190

163191
/// Extracts the x-coordinate of a point.
@@ -172,6 +200,7 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
172200

173201
/// Returns `self + other`.
174202
pub fn add(&self, mut layouter: impl Layouter<C::Base>, other: &Self) -> Result<Self, Error> {
203+
assert_eq!(format!("{:?}", self.chip), format!("{:?}", other.chip));
175204
self.chip
176205
.add(&mut layouter, &self.inner, &other.inner)
177206
.map(|inner| Point {
@@ -181,9 +210,14 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
181210
}
182211

183212
/// 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));
185219
self.chip
186-
.mul(&mut layouter, by, &self.inner)
220+
.mul(&mut layouter, &by.inner, &self.inner)
187221
.map(|inner| Point {
188222
chip: self.chip.clone(),
189223
inner,
@@ -193,12 +227,12 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> Point<C, EccChip> {
193227

194228
/// The x-coordinate of an elliptic curve point over the given curve.
195229
#[derive(Debug)]
196-
pub struct X<C: CurveAffine, EccChip: EccInstructions<C> + Clone> {
230+
pub struct X<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> {
197231
chip: EccChip,
198232
inner: EccChip::X,
199233
}
200234

201-
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> X<C, EccChip> {
235+
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> X<C, EccChip> {
202236
/// Wraps the given x-coordinate (obtained directly from an instruction) in a gadget.
203237
pub fn from_inner(chip: EccChip, inner: EccChip::X) -> Self {
204238
X { chip, inner }
@@ -208,18 +242,16 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> X<C, EccChip> {
208242
/// A constant elliptic curve point over the given curve, for which scalar multiplication
209243
/// is more efficient.
210244
#[derive(Clone, Debug)]
211-
pub struct FixedPoint<C: CurveAffine, EccChip: EccInstructions<C> + Clone> {
245+
pub struct FixedPoint<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> {
212246
chip: EccChip,
213247
inner: EccChip::FixedPoint,
214248
}
215249

216-
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> FixedPoint<C, EccChip> {
250+
impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug> FixedPoint<C, EccChip> {
217251
/// Gets a reference to the specified fixed point in the circuit.
218252
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 })
223255
}
224256

225257
/// Returns `[by] self`.
@@ -228,6 +260,7 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone> FixedPoint<C, EccChip>
228260
mut layouter: impl Layouter<C::Base>,
229261
by: &ScalarFixed<C, EccChip>,
230262
) -> Result<Point<C, EccChip>, Error> {
263+
assert_eq!(format!("{:?}", self.chip), format!("{:?}", by.chip));
231264
self.chip
232265
.mul_fixed(&mut layouter, &by.inner, &self.inner)
233266
.map(|inner| Point {

0 commit comments

Comments
 (0)