use crate::{
syscalls::{syscall_arith256_mod, SyscallArith256ModParams},
zisklib::{eq, fcall_secp256k1_fp_inv, fcall_secp256k1_fp_sqrt, is_one, is_zero, lt},
};
use super::constants::{NQR, P, P_MINUS_ONE};
pub fn reduce_fp_secp256k1(
x: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 4] {
if lt(x, &P) {
return *x;
}
let mut params = SyscallArith256ModParams {
a: x,
b: &[1, 0, 0, 0],
c: &[0, 0, 0, 0],
module: &P,
d: &mut [0, 0, 0, 0],
};
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn add_fp_secp256k1(
x: &[u64; 4],
y: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 4] {
let mut params =
SyscallArith256ModParams { a: x, b: &[1, 0, 0, 0], c: y, module: &P, d: &mut [0, 0, 0, 0] };
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn neg_fp_secp256k1(x: &[u64; 4], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 4] {
let mut params = SyscallArith256ModParams {
a: x,
b: &P_MINUS_ONE,
c: &[0, 0, 0, 0],
module: &P,
d: &mut [0, 0, 0, 0],
};
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn sub_fp_secp256k1(
x: &[u64; 4],
y: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 4] {
let mut params =
SyscallArith256ModParams { a: y, b: &P_MINUS_ONE, c: x, module: &P, d: &mut [0, 0, 0, 0] };
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn mul_fp_secp256k1(
x: &[u64; 4],
y: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 4] {
let mut params =
SyscallArith256ModParams { a: x, b: y, c: &[0, 0, 0, 0], module: &P, d: &mut [0, 0, 0, 0] };
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn square_fp_secp256k1(
x: &[u64; 4],
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> [u64; 4] {
let mut params =
SyscallArith256ModParams { a: x, b: x, c: &[0, 0, 0, 0], module: &P, d: &mut [0, 0, 0, 0] };
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
*params.d
}
pub fn sqrt_fp_secp256k1(
x: &[u64; 4],
parity: u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> ([u64; 4], bool) {
let hint = fcall_secp256k1_fp_sqrt(
x,
parity,
#[cfg(feature = "hints")]
hints,
);
let is_qr = hint[0] == 1;
let sqrt: [u64; 4] = hint[1..5].try_into().unwrap();
assert!(lt(&sqrt, &P), "Square root is not canonical");
let mut params = SyscallArith256ModParams {
a: &sqrt,
b: &sqrt,
c: &[0, 0, 0, 0],
module: &P,
d: &mut [0, 0, 0, 0],
};
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
if is_qr {
assert!(eq(params.d, x), "Square root verification failed");
(sqrt, true)
} else {
let nqr = mul_fp_secp256k1(
x,
&NQR,
#[cfg(feature = "hints")]
hints,
);
assert!(eq(params.d, &nqr), "Square root verification failed");
(sqrt, false)
}
}
pub fn inv_fp_secp256k1(x: &[u64; 4], #[cfg(feature = "hints")] hints: &mut Vec<u64>) -> [u64; 4] {
if is_zero(x) {
return *x;
}
let inv = fcall_secp256k1_fp_inv(
x,
#[cfg(feature = "hints")]
hints,
);
assert!(lt(&inv, &P), "Inverse is not canonical");
let mut params = SyscallArith256ModParams {
a: x,
b: &inv,
c: &[0, 0, 0, 0],
module: &P,
d: &mut [0, 0, 0, 0],
};
syscall_arith256_mod(
&mut params,
#[cfg(feature = "hints")]
hints,
);
assert!(is_one(params.d), "Inverse verification failed");
inv
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_reduce_fp_secp256k1_c")]
pub unsafe extern "C" fn reduce_fp_secp256k1_c(
x_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = reduce_fp_secp256k1(
x,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_add_fp_secp256k1_c")]
pub unsafe extern "C" fn add_fp_secp256k1_c(
x_ptr: *const u64,
y_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let y = &*(y_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = add_fp_secp256k1(
x,
y,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_neg_fp_secp256k1_c")]
pub unsafe extern "C" fn neg_fp_secp256k1_c(
x_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = neg_fp_secp256k1(
x,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_sub_fp_secp256k1_c")]
pub unsafe extern "C" fn sub_fp_secp256k1_c(
x_ptr: *const u64,
y_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let y = &*(y_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = sub_fp_secp256k1(
x,
y,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_mul_fp_secp256k1_c")]
pub unsafe extern "C" fn mul_fp_secp256k1_c(
x_ptr: *const u64,
y_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let y = &*(y_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = mul_fp_secp256k1(
x,
y,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_square_fp_secp256k1_c")]
pub unsafe extern "C" fn square_fp_secp256k1_c(
x_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = square_fp_secp256k1(
x,
#[cfg(feature = "hints")]
hints,
);
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_sqrt_fp_secp256k1_c")]
pub unsafe extern "C" fn sqrt_fp_secp256k1_c(
x_ptr: *const u64,
parity: u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) -> u8 {
let x = &*(x_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
let (sqrt, is_qr) = sqrt_fp_secp256k1(
x,
parity,
#[cfg(feature = "hints")]
hints,
);
*result = sqrt;
is_qr as u8
}
#[cfg_attr(not(feature = "hints"), no_mangle)]
#[cfg_attr(feature = "hints", export_name = "hints_inv_fp_secp256k1_c")]
pub unsafe extern "C" fn inv_fp_secp256k1_c(
x_ptr: *const u64,
result_ptr: *mut u64,
#[cfg(feature = "hints")] hints: &mut Vec<u64>,
) {
let x = &*(x_ptr as *const [u64; 4]);
let result = &mut *(result_ptr as *mut [u64; 4]);
*result = inv_fp_secp256k1(
x,
#[cfg(feature = "hints")]
hints,
);
}