Skip to content

Commit 70b72fa

Browse files
author
Ubuntu
committed
remove ambiguity
1 parent 470e24c commit 70b72fa

9 files changed

Lines changed: 109 additions & 117 deletions

File tree

‎bitvm/src/bn254/ell_coeffs.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl G2Prepared {
3636
t: &mut ark_bn254::G2Affine,
3737
three_div_two: &ark_bn254::Fq,
3838
) -> EllCoeff {
39+
assert_ne!(*t, ark_bn254::G2Affine::zero());
3940
// for affine coordinates
4041
// slope: alpha = 3 * x^2 / 2 * y
4142
// intercept: bias = y - alpha * x
@@ -55,6 +56,7 @@ impl G2Prepared {
5556
}
5657

5758
fn affine_add_in_place(t: &mut ark_bn254::G2Affine, q: &ark_bn254::G2Affine) -> EllCoeff {
59+
assert_ne!(*t, ark_bn254::G2Affine::zero());
5860
// alpha = (t.y - q.y) / (t.x - q.x)
5961
// bias = t.y - alpha * t.x
6062
let alpha = (t.y - q.y) / (t.x - q.x);

‎bitvm/src/bn254/g1.rs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ impl G1Affine {
6363
q: ark_bn254::G1Affine,
6464
c3: ark_bn254::Fq,
6565
) -> (Script, Vec<Hint>) {
66+
//assert_ne!(t, ark_bn254::G1Affine::zero());
67+
//assert_ne!(q, ark_bn254::G1Affine::zero());
6668
let mut hints = Vec::new();
6769

6870
let (hinted_script1, hint1) = Self::hinted_check_line_through_point(q.x, c3);
@@ -103,6 +105,7 @@ impl G1Affine {
103105
t: ark_bn254::G1Affine,
104106
c3: ark_bn254::Fq,
105107
) -> (Script, Vec<Hint>) {
108+
assert_ne!(t, ark_bn254::G1Affine::zero());
106109
let mut hints = vec![];
107110

108111
let (hinted_script1, hint1) = Fq::hinted_mul(1, t.y + t.y, 0, c3);
@@ -497,7 +500,7 @@ pub fn hinted_from_eval_points(px: ark_bn254::Fq, py: ark_bn254::Fq) -> (Script,
497500
let mut hints = Vec::new();
498501

499502
let p = ark_bn254::G1Affine::new_unchecked(px, py);
500-
if p.is_zero() {
503+
if p.is_zero() || py == ark_bn254::Fq::ZERO {
501504
return (G1Affine::push_zero(), hints, true);
502505
}
503506
let valid_point = p.is_on_curve();

‎bitvm/src/bn254/g2.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ pub fn hinted_check_tangent_line(
589589
c3: ark_bn254::Fq2,
590590
c4: ark_bn254::Fq2,
591591
) -> (Script, Vec<Hint>) {
592+
assert_ne!(t, ark_bn254::G2Affine::zero());
592593
let mut hints = Vec::new();
593594

594595
// let (hinted_script1, hint1) = Fq2::hinted_mul_by_constant(t.y.double(), &c3);
@@ -757,6 +758,8 @@ pub fn hinted_check_chord_line(
757758
c3: ark_bn254::Fq2,
758759
c4: ark_bn254::Fq2,
759760
) -> (Script, Vec<Hint>) {
761+
assert_ne!(t, ark_bn254::G2Affine::zero());
762+
assert_ne!(q, ark_bn254::G2Affine::zero());
760763
let mut hints = Vec::new();
761764

762765
let (script1, hint1) = hinted_check_line_through_point(q.x, c3, c4);

‎bitvm/src/bn254/pairing.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ impl Pairing {
3636
q4: ark_bn254::G2Affine,
3737
) -> (Script, Vec<Hint>) {
3838
assert_eq!(constants.len(), 4);
39+
use ark_ec::AffineRepr;
40+
assert_ne!(q4, ark_bn254::G2Affine::zero());
3941
let num_line_groups = constants.len();
4042
let num_constant = 3;
4143

‎bitvm/src/chunk/elements.rs‎

Lines changed: 63 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,25 @@ pub enum DataType {
3535
U256Data(ark_ff::BigInt<4>),
3636
}
3737

38-
/// Represent coordinates by evaluation form (-x/y, 1/y), see more: https://github.com/BitVM/BitVM/issues/213
39-
#[derive(Debug, Clone, Copy)]
38+
/// Represent evaluation form (-x/y, 1/y) for G1Affine points, see more: https://github.com/BitVM/BitVM/issues/213
39+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4040
pub struct FqPair {
41-
x: ark_bn254::Fq, // -x/y
42-
y: ark_bn254::Fq, // 1/y
43-
pub zero: bool, // true if y is zero
41+
x: ark_bn254::Fq,
42+
y: ark_bn254::Fq,
4443
}
4544

4645
impl FqPair {
46+
pub const ZERO: Self = Self {
47+
x: ark_bn254::Fq::ZERO,
48+
y: ark_bn254::Fq::ZERO,
49+
};
50+
4751
pub fn new(x: ark_bn254::Fq, y: ark_bn254::Fq) -> Self {
48-
Self {
49-
x,
50-
y,
51-
zero: y == ark_bn254::Fq::ZERO,
52+
if x == ark_bn254::Fq::ZERO || y == ark_bn254::Fq::ZERO {
53+
assert_eq!(x, ark_bn254::Fq::ZERO);
54+
assert_eq!(y, ark_bn254::Fq::ZERO);
5255
}
56+
Self { x, y }
5357
}
5458

5559
pub fn x(&self) -> ark_bn254::Fq {
@@ -61,81 +65,55 @@ impl FqPair {
6165
}
6266

6367
/// Recover the evaluation form to original form.
64-
pub fn recover(&self) -> Self {
65-
if self.zero {
66-
if self.x == ark_bn254::Fq::ZERO {
67-
return Self::new(ark_bn254::Fq::ZERO, ark_bn254::Fq::ZERO);
68-
}
69-
return Self::new(self.x, self.y);
68+
pub fn recover(&self) -> ark_bn254::G1Affine {
69+
if self.y == ark_bn254::Fq::ZERO {
70+
return ark_bn254::G1Affine::zero();
7071
}
71-
7272
let (nx, ny) = (self.x, self.y);
73-
let y = ny.inverse().expect("ny should be non-zero to recover");
73+
let y = ny
74+
.inverse()
75+
.expect("ny must be nonzero for evaluation form");
7476
let x = -nx * y; // equivalent to -nx / ny⁻¹
75-
76-
Self::new(x, y)
77+
// Use new_unchecked to get compitiable with generate_segments_using_mock_vk_and_mock_proof.
78+
ark_bn254::G1Affine::new_unchecked(x, y)
7779
}
7880

7981
pub fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
8082
let p = ark_bn254::G1Affine::rand(rng);
8183
Self::new(p.x, p.y)
8284
}
85+
86+
pub fn is_zero(&self) -> bool {
87+
*self == Self::ZERO
88+
}
8389
}
8490

8591
impl From<ark_bn254::G1Affine> for FqPair {
8692
fn from(p: ark_bn254::G1Affine) -> Self {
8793
if p.y == ark_bn254::Fq::ZERO {
88-
return Self {
89-
x: p.x,
90-
y: p.y,
91-
zero: true,
92-
};
94+
return Self { x: p.x, y: p.y };
9395
}
9496
let (x, y) = (p.x, p.y);
9597
let ny = y.inverse().expect("y must be nonzero for evaluation form");
9698
let nx = -(x * ny);
97-
Self {
98-
x: nx,
99-
y: ny,
100-
zero: false,
101-
}
99+
Self { x: nx, y: ny }
102100
}
103101
}
104102

105-
//impl From<FqPair> for ark_bn254::G1Affine {
106-
// fn from(pi: FqPair) -> Self {
107-
// if pi.zero {
108-
// if pi.x == ark_bn254::Fq::ZERO {
109-
// return ark_bn254::G1Affine::zero();
110-
// }
111-
// return ark_bn254::G1Affine::new_unchecked(pi.x, pi.y);
112-
// }
113-
//
114-
// let (nx, ny) = (pi.x, pi.y);
115-
// let y = ny
116-
// .inverse()
117-
// .expect("ny must be nonzero for evaluation form");
118-
// let x = -nx * y; // equivalent to -nx / ny⁻¹
119-
//
120-
// ark_bn254::G1Affine::new_unchecked(x, y)
121-
// }
122-
//}
123-
124103
/// Non-G2 Group on E'
125104
#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)]
126105
pub struct TwistPoint {
127106
x: ark_bn254::Fq2,
128107
y: ark_bn254::Fq2,
129-
pub zero: bool,
130108
}
131109

132110
impl TwistPoint {
111+
pub const ZERO: Self = Self {
112+
x: ark_bn254::Fq2::ZERO,
113+
y: ark_bn254::Fq2::ZERO,
114+
};
133115
pub fn new(x: ark_bn254::Fq2, y: ark_bn254::Fq2) -> Self {
134-
Self {
135-
x,
136-
y,
137-
zero: x == ark_bn254::Fq2::ZERO && y == ark_bn254::Fq2::ZERO,
138-
}
116+
Self { x, y }
139117
}
140118

141119
pub fn x(&self) -> ark_bn254::Fq2 {
@@ -146,25 +124,38 @@ impl TwistPoint {
146124
self.y
147125
}
148126

149-
pub fn is_zero(&self) -> bool {
150-
self.zero
151-
}
152-
153127
pub fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
154-
let p = ark_bn254::G2Affine::rand(rng);
155-
Self::new(p.x, p.y)
128+
loop {
129+
let x = ark_bn254::Fq2::rand(rng);
130+
let rhs = x * x * x + G2Config::COEFF_B;
131+
if let Some(y) = rhs.sqrt() {
132+
// This (x, y) satisfies the twist curve equation but is *not* subgroup-checked.
133+
let p = ark_bn254::G2Affine::new_unchecked(x, y);
134+
assert!(p.is_on_curve(), "curve equation must hold");
135+
return TwistPoint::new(x, y);
136+
}
137+
}
156138
}
157139

158140
/// y^2 = x^3 + b' (b' from E')
159141
pub fn is_on_curve(&self) -> bool {
142+
if self.is_zero() {
143+
return true;
144+
}
145+
let x2 = self.x.square();
160146
let y2 = self.y.square();
161-
let x3b = self.x.square() * self.x + <G2Config as SWCurveConfig>::COEFF_B;
147+
let x3b = x2 * self.x + <G2Config as SWCurveConfig>::COEFF_B;
162148
y2 == x3b
163149
}
164150

151+
// check if a zero point
152+
pub fn is_zero(&self) -> bool {
153+
*self == Self::ZERO
154+
}
155+
165156
/// Negation
166157
pub fn neg(&self) -> Self {
167-
if self.zero {
158+
if self.is_zero() {
168159
*self
169160
} else {
170161
Self::new(self.x, -self.y)
@@ -173,7 +164,7 @@ impl TwistPoint {
173164

174165
/// Point doubling: (x3, y3) = 2 * (x1, y1)
175166
pub fn double(&self) -> Self {
176-
if self.zero {
167+
if self.is_zero() {
177168
return *self;
178169
}
179170

@@ -187,7 +178,6 @@ impl TwistPoint {
187178
return Self {
188179
x: ark_bn254::Fq2::zero(),
189180
y: ark_bn254::Fq2::zero(),
190-
zero: true,
191181
};
192182
}
193183

@@ -200,10 +190,10 @@ impl TwistPoint {
200190

201191
/// Point addition on E': P3 = P1 + P2
202192
pub fn add(&self, other: &Self) -> Self {
203-
if self.zero {
193+
if self.is_zero() {
204194
return *other;
205195
}
206-
if other.zero {
196+
if other.is_zero() {
207197
return *self;
208198
}
209199

@@ -217,7 +207,6 @@ impl TwistPoint {
217207
return Self {
218208
x: ark_bn254::Fq2::zero(),
219209
y: ark_bn254::Fq2::zero(),
220-
zero: true,
221210
};
222211
} else {
223212
return self.double();
@@ -234,11 +223,7 @@ impl TwistPoint {
234223

235224
impl From<ark_bn254::G2Affine> for TwistPoint {
236225
fn from(p: ark_bn254::G2Affine) -> Self {
237-
Self {
238-
x: p.x,
239-
y: p.y,
240-
zero: p.is_zero(),
241-
}
226+
Self { x: p.x, y: p.y }
242227
}
243228
}
244229

@@ -419,7 +404,7 @@ impl DataType {
419404
DataType::U256Data(f) => CompressedStateObject::U256(f),
420405
DataType::G1Data(r) => {
421406
let r = r.recover();
422-
let hash = extern_hash_fps(vec![r.x(), r.y()]);
407+
let hash = extern_hash_fps(vec![r.x, r.y]);
423408
CompressedStateObject::Hash(hash)
424409
}
425410
}
@@ -502,7 +487,7 @@ fn as_hints_scalarelemtype_u256data(elem: ark_ff::BigInt<4>) -> Vec<Hint> {
502487

503488
fn as_hints_g1type_g1data(r: &FqPair) -> Vec<Hint> {
504489
let r = r.recover();
505-
let hints = vec![Hint::Fq(r.x()), Hint::Fq(r.y())];
490+
let hints = vec![Hint::Fq(r.x), Hint::Fq(r.y)];
506491
hints
507492
}
508493

@@ -636,21 +621,16 @@ mod test {
636621

637622
#[test]
638623
fn test_fq_pair() {
639-
let zero = ark_bn254::G1Affine::new_unchecked(ark_bn254::Fq::ZERO, ark_bn254::Fq::ZERO);
624+
let zero = ark_bn254::G1Affine::zero();
640625
let fp_zero = FqPair::from(zero);
641-
assert!(fp_zero.zero);
642-
assert_eq!(
643-
zero,
644-
ark_bn254::G1Affine::new_unchecked(fp_zero.x(), fp_zero.y())
645-
);
626+
assert_eq!(zero, fp_zero.recover());
646627

647628
let mut rng = thread_rng();
648629
(0..100).into_iter().for_each(|_| {
649630
let random = ark_bn254::G1Affine::rand(&mut rng);
650631
let fp_rand = FqPair::from(random);
651-
assert!(!fp_rand.zero);
652632
let lifted = fp_rand.recover();
653-
assert_eq!(random, ark_bn254::G1Affine::new(lifted.x(), lifted.y()));
633+
assert_eq!(random, lifted);
654634
});
655635
}
656636

@@ -691,7 +671,7 @@ mod test {
691671
// P + (-P) = 0
692672
let neg = p.neg();
693673
let s3 = p.add(&neg);
694-
assert!(s3.zero, "P + (-P) should be zero point");
674+
assert!(s3.is_zero(), "P + (-P) should be zero point");
695675
}
696676

697677
#[test]

‎bitvm/src/chunk/g16_runner_utils.rs‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ pub(crate) fn wrap_chunk_point_ops_and_multiply_line_evals_step_1(
225225
let p3: FqPair = in_p3.result.0.try_into().unwrap();
226226
let p2: FqPair = in_p2.result.0.try_into().unwrap();
227227

228-
let p4 = p4.recover();
229-
let p3 = p3.recover();
230-
let p2 = p2.recover();
228+
let p4 = ark_bn254::G1Affine::new_unchecked(p4.x(), p4.y()).into();
229+
let p3 = ark_bn254::G1Affine::new_unchecked(p3.x(), p3.y()).into();
230+
let p2 = ark_bn254::G1Affine::new_unchecked(p2.x(), p2.y()).into();
231231

232232
let mut q4: Option<TwistPoint> = None;
233233

@@ -368,13 +368,16 @@ pub(crate) fn wrap_hint_hash_p(
368368
let input_segment_info = vec![(in_t.id, ElementType::G1)];
369369

370370
let t: FqPair = in_t.result.0.try_into().unwrap();
371-
let (mut p3, mut is_valid_input, mut scr, mut op_hints) =
372-
(ark_bn254::G1Affine::identity(), true, script! {}, vec![]);
371+
let (mut p3, mut is_valid_input, mut scr, mut op_hints) = (
372+
ark_bn254::G1Affine::identity().into(),
373+
true,
374+
script! {},
375+
vec![],
376+
);
373377
if !skip {
374378
// the value has been converted to FqPair in chunk_msm, we recover it to G1 coordinate.
375379
let t = t.recover();
376-
let tq = ark_bn254::G1Affine::new_unchecked(t.x(), t.y());
377-
(p3, is_valid_input, scr, op_hints) = chunk_hash_p(tq, pub_vky0);
380+
(p3, is_valid_input, scr, op_hints) = chunk_hash_p(t, pub_vky0);
378381
// op_hints.extend_from_slice(&DataType::G1Data(t).get_hash_preimage_as_hints());
379382
}
380383
Segment {

0 commit comments

Comments
 (0)