use crate::extend::Hashable;
use rand::{thread_rng, RngCore};
use tiny_ec::{
curve::{Affine, ECMultContext, ECMultGenContext, Field, Jacobian, Scalar},
PublicKey,
};
use tiny_keccak::{Hasher, Keccak};
pub const FIELD_SIZE: Scalar = Scalar([
0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
]);
pub const GROUP_ORDER: Scalar = Scalar([
0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
]);
pub fn hash_keccak256(data: &[u8]) -> [u8; 32] {
let mut output = [0u8; 32];
let mut hasher = Keccak::v256();
hasher.update(data);
hasher.finalize(&mut output);
output
}
pub fn projective_sub(a: &Affine, b: &Affine) -> Affine {
let mut x = b.y * a.x + a.y * b.x.neg(1);
let mut y = a.y * b.y;
x.normalize();
y.normalize();
Affine::new(x, y)
}
pub fn projective_mul(a: &Affine, b: &Affine) -> Affine {
let mut x = a.x * b.x;
let mut y = a.y * b.y;
x.normalize();
y.normalize();
Affine::new(x, y)
}
pub fn projective_ec_add(a: &Affine, b: &Affine) -> Jacobian {
let mut r = Jacobian::default();
let mut l = Affine::default();
let (z1, z2) = (Field::from_int(1), Field::from_int(1));
l.set_xy(&(b.y + a.y.neg(1)), &(b.x + a.x.neg(1)));
let s1 = projective_mul(&l, &l);
let s1 = projective_sub(&s1, &Affine::compose(&a.x, &z1));
let s1 = projective_sub(&s1, &Affine::compose(&b.x, &z2));
let s2 = projective_sub(&Affine::compose(&a.x, &z1), &s1);
let s2 = projective_mul(&s2, &l);
let s2 = projective_sub(&s2, &Affine::compose(&a.y, &z1));
if s1.y != s2.y {
r.x = s1.x * s2.y;
r.y = s2.x * s1.y;
r.z = s1.y * s2.y;
} else {
r.x = s1.x;
r.y = s2.x;
r.z = s1.y;
}
r.x.normalize();
r.y.normalize();
r.z.normalize();
r
}
pub fn ecmult(context: &ECMultContext, a: &Affine, na: &Scalar) -> Affine {
let mut rj = Jacobian::default();
context.ecmult(&mut rj, &Jacobian::from_ge(a), na, &Scalar::from_int(0));
Affine::from(&rj)
}
pub fn ecmult_gen(context: &ECMultGenContext, ng: &Scalar) -> Affine {
let mut rj = Jacobian::default();
context.ecmult_gen(&mut rj, ng);
Affine::from(&rj)
}
pub fn calculate_witness_address(witness: &Affine) -> [u8; 20] {
let mut result = [0u8; 20];
result.copy_from_slice(&witness.keccak256()[12..32]);
result
}
pub fn get_address(pub_key: &PublicKey) -> [u8; 20] {
let mut affine_pub: Affine = (*pub_key).into();
affine_pub.x.normalize();
affine_pub.y.normalize();
calculate_witness_address(&affine_pub)
}
pub fn random_bytes(buf: &mut [u8]) {
let mut rng = thread_rng();
rng.fill_bytes(buf);
}