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
136 lines (122 loc) · 3.88 KB
/
offchain_checker.rs
File metadata and controls
136 lines (122 loc) · 3.88 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
129
130
131
132
133
134
135
136
#![allow(non_snake_case)]
use crate::groth16::constants::{COFACTOR_CUBIC, H, K, LAMBDA, MM, R, S, T, W};
use ark_ff::{Field, One};
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);
let exp = 3_u32.pow(s) * &t;
// 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 as i32) {
let delta = (s as i32) - i - 1;
let d = if delta < 0 {
r.pow((&exp / 3_u32.pow((-delta) as u32)).to_u64_digits())
} else {
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();
log_assert_ne!(r_inv, BigUint::one());
let f2 = f1.pow(r_inv.to_u64_digits());
log_assert_ne!(f2, ark_bn254::Fq12::ONE);
// m'-th root of f, say f3
let mm_inv = MM.modinv(&(&*R * &*H)).unwrap();
log_assert_ne!(mm_inv, BigUint::one());
let f3 = f2.pow(mm_inv.to_u64_digits());
log_assert_eq!(f3.pow(&*COFACTOR_CUBIC.to_u64_digits()), ark_bn254::Fq12::ONE);
log_assert_ne!(f3, ark_bn254::Fq12::ONE);
// d-th (cubic) root, say c
let c = tonelli_shanks_cubic(f3, w, S, T.clone(), K.clone());
log_assert_ne!(c, ark_bn254::Fq12::ONE);
log_assert_eq!(c.pow(LAMBDA.to_u64_digits()), f * wi);
(c, wi)
}