forked from BitVM/BitVM
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoffchain_checker.rs
More file actions
128 lines (114 loc) · 3.46 KB
/
Copy pathoffchain_checker.rs
File metadata and controls
128 lines (114 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#![allow(non_snake_case)]
use crate::groth16::constants::{COFACTOR_CUBIC, H, K, LAMBDA, MM_INV, R, S, T, W};
use ark_ff::Field;
use num_bigint::BigUint;
use num_traits::ToPrimitive;
#[macro_export]
macro_rules! log_assert_eq {
($left:expr, $right:expr) => {
if $left != $right {
// log error
println! {"fail assert"}
}
};
($left:expr, $right:expr, $message: expr) => {
if $left != $right {
// log error
println! {"fail assert: {}", $message}
}
};
($left:expr, $right:expr, $text: expr, $message: expr) => {
if $left != $right {
// log error
println! {$text, $message}
}
};
}
#[macro_export]
macro_rules! log_assert_ne {
($left:expr, $right:expr) => {
if $left == $right {
println! {"fail assert"}
}
};
($left:expr, $right:expr, $message: expr) => {
if $left == $right {
// log error
println! {"fail assert: {}", $message}
}
};
}
// refer table 3 of https://eprint.iacr.org/2009/457.pdf
// a: Fp12 which is cubic residue
// c: random Fp12 which is cubic non-residue
// s: satisfying p^12 - 1 = 3^s * t
// t: satisfying p^12 - 1 = 3^s * t
// k: k = (t + 1) // 3
fn tonelli_shanks_cubic(
a: ark_bn254::Fq12,
c: ark_bn254::Fq12,
s: u32,
t: BigUint,
k: BigUint,
) -> ark_bn254::Fq12 {
let mut r = a.pow(t.to_u64_digits());
let e = 3_u32.pow(s - 1);
// compute cubic root of (a^t)^-1, say h
let (mut h, cc, mut c) = (
ark_bn254::Fq12::ONE,
c.pow([e as u64]),
c.inverse().unwrap(),
);
for i in 1..s {
let delta = s - i - 1;
let d = r.pow([3_u32.pow(delta as u32).to_u64().unwrap()]);
if d == cc {
(h, r) = (h * c, r * c.pow([3_u64]));
} else if d == cc.pow([2_u64]) {
(h, r) = (h * c.pow([2_u64]), r * c.pow([3_u64]).pow([2_u64]));
}
c = c.pow([3_u64])
}
// recover cubic root of a
r = a.pow(k.to_u64_digits()) * h;
if t == 3_u32 * k + 1_u32 {
r = r.inverse().unwrap();
}
log_assert_eq!(r.pow([3_u64]), a);
r
}
// Finding C
// refer from Algorithm 5 of "On Proving Pairings"(https://eprint.iacr.org/2024/640.pdf)
pub fn compute_c_wi(f: ark_bn254::Fq12) -> (ark_bn254::Fq12, ark_bn254::Fq12) {
// make sure f is r-th residue
log_assert_eq!(f.pow(&*H.to_u64_digits()), ark_bn254::Fq12::ONE);
let w = *W;
// options for wi are 1, w, w^2
let mut wi = ark_bn254::Fq12::ONE;
if (f * wi).pow(&*COFACTOR_CUBIC.to_u64_digits()) != ark_bn254::Fq12::ONE {
wi *= w;
if (f * wi).pow(&*COFACTOR_CUBIC.to_u64_digits()) != ark_bn254::Fq12::ONE {
wi *= w;
log_assert_eq!(
(f * wi).pow(&*COFACTOR_CUBIC.to_u64_digits()),
ark_bn254::Fq12::ONE
);
}
}
log_assert_eq!(wi.pow(&*H.to_u64_digits()), ark_bn254::Fq12::ONE);
// f1 is scaled f
let f1 = f * wi;
// r-th root of f1, say f2
let r_inv = R.modinv(&H).unwrap();
let f2 = f1.pow(r_inv.to_u64_digits());
// m'-th root of f, say f3
let f3 = f2.pow(MM_INV.to_u64_digits());
log_assert_eq!(
f3.pow(&*COFACTOR_CUBIC.to_u64_digits()),
ark_bn254::Fq12::ONE
);
// d-th (cubic) root, say c
let c = tonelli_shanks_cubic(f3, w, S, T.clone(), K.clone());
log_assert_eq!(c.pow(LAMBDA.to_u64_digits()), f * wi);
(c, wi)
}