use alloc::vec::Vec;
use ark_bls12_381::Bls12_381;
use ark_ec::{
CurveConfig, CurveGroup as _,
pairing::{MillerLoopOutput, Pairing},
short_weierstrass::{Affine as SWAffine, SWCurveConfig},
twisted_edwards::{Affine as TEAffine, Projective as TEProjective, TECurveConfig},
};
use ark_ed_on_bls12_381_bandersnatch::EdwardsConfig;
use ark_ff::Zero as _;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
pub(super) const ERROR_ENCODE: u32 = 1;
pub(super) const ERROR_DECODE: u32 = 2;
pub(super) const ERROR_LENGTH_MISMATCH: u32 = 3;
pub(super) const ERROR_DEGENERATE_POINT: u32 = 4;
pub(super) const ERROR_UNKNOWN: u32 = 255;
fn decode<T: CanonicalDeserialize>(bytes: &[u8]) -> Result<T, u32> {
T::deserialize_with_mode(bytes, Compress::No, Validate::No).map_err(|_| ERROR_DECODE)
}
fn encode<T: CanonicalSerialize>(value: &T, out_len: usize) -> Result<Vec<u8>, u32> {
if value.serialized_size(Compress::No) > out_len {
return Err(ERROR_ENCODE);
}
let mut out = Vec::with_capacity(value.serialized_size(Compress::No));
value
.serialize_with_mode(&mut out, Compress::No)
.map_err(|_| ERROR_ENCODE)?;
Ok(out)
}
fn te_into_affine_safe<T: TECurveConfig>(point: TEProjective<T>) -> Result<TEAffine<T>, u32> {
if point.z.is_zero() {
return Err(ERROR_DEGENERATE_POINT);
}
Ok(point.into_affine())
}
fn mul_sw<T: SWCurveConfig>(base: &[u8], scalar: &[u8], out_len: usize) -> Result<Vec<u8>, u32> {
let base = decode::<SWAffine<T>>(base)?;
let scalar = decode::<Vec<u64>>(scalar)?;
encode(&T::mul_affine(&base, &scalar).into_affine(), out_len)
}
fn msm_sw<T: SWCurveConfig>(bases: &[u8], scalars: &[u8], out_len: usize) -> Result<Vec<u8>, u32> {
let bases = decode::<Vec<SWAffine<T>>>(bases)?;
let scalars = decode::<Vec<T::ScalarField>>(scalars)?;
let result = T::msm(&bases, &scalars).map_err(|_| ERROR_LENGTH_MISMATCH)?;
encode(&result.into_affine(), out_len)
}
pub(super) fn ed_on_bls12_381_bandersnatch_mul(
base: &[u8],
scalar: &[u8],
out_len: usize,
) -> Result<Vec<u8>, u32> {
let base = decode::<TEAffine<EdwardsConfig>>(base)?;
let scalar = decode::<Vec<u64>>(scalar)?;
let result = <EdwardsConfig as TECurveConfig>::mul_affine(&base, &scalar);
encode(&te_into_affine_safe(result)?, out_len)
}
pub(super) fn ed_on_bls12_381_bandersnatch_msm(
bases: &[u8],
scalars: &[u8],
out_len: usize,
) -> Result<Vec<u8>, u32> {
let bases = decode::<Vec<TEAffine<EdwardsConfig>>>(bases)?;
let scalars = decode::<Vec<<EdwardsConfig as CurveConfig>::ScalarField>>(scalars)?;
let result = <EdwardsConfig as TECurveConfig>::msm(&bases, &scalars)
.map_err(|_| ERROR_LENGTH_MISMATCH)?;
encode(&te_into_affine_safe(result)?, out_len)
}
pub(super) fn bls12_381_mul_g1(base: &[u8], scalar: &[u8], out_len: usize) -> Result<Vec<u8>, u32> {
mul_sw::<ark_bls12_381::g1::Config>(base, scalar, out_len)
}
pub(super) fn bls12_381_mul_g2(base: &[u8], scalar: &[u8], out_len: usize) -> Result<Vec<u8>, u32> {
mul_sw::<ark_bls12_381::g2::Config>(base, scalar, out_len)
}
pub(super) fn bls12_381_msm_g1(
bases: &[u8],
scalars: &[u8],
out_len: usize,
) -> Result<Vec<u8>, u32> {
msm_sw::<ark_bls12_381::g1::Config>(bases, scalars, out_len)
}
pub(super) fn bls12_381_msm_g2(
bases: &[u8],
scalars: &[u8],
out_len: usize,
) -> Result<Vec<u8>, u32> {
msm_sw::<ark_bls12_381::g2::Config>(bases, scalars, out_len)
}
pub(super) fn bls12_381_multi_miller_loop(
g1: &[u8],
g2: &[u8],
out_len: usize,
) -> Result<Vec<u8>, u32> {
let g1 = decode::<Vec<ark_bls12_381::G1Affine>>(g1)?;
let g2 = decode::<Vec<ark_bls12_381::G2Affine>>(g2)?;
let result = Bls12_381::multi_miller_loop(g1, g2);
encode(&result.0, out_len)
}
pub(super) fn bls12_381_final_exponentiation(in_out: &[u8]) -> Result<Vec<u8>, u32> {
let target = decode::<ark_bls12_381::Fq12>(in_out)?;
let result = Bls12_381::final_exponentiation(MillerLoopOutput(target)).ok_or(ERROR_UNKNOWN)?;
encode(&result.0, in_out.len())
}