use super::utils::{self, HostcallResult, FAIL_MSG};
use crate::runtime_interface::{
pass_by::{PassFatPointerAndRead, PassFatPointerAndReadWrite, PassFatPointerAndWrite},
runtime_interface,
};
use alloc::vec::Vec;
use ark_bw6_761_ext::CurveHooks;
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
pub type Config = ark_bw6_761_ext::Config<HostHooks>;
pub type BW6_761 = ark_bw6_761_ext::BW6_761<HostHooks>;
pub type G1Config = ark_bw6_761_ext::g1::Config<HostHooks>;
pub type G1Affine = ark_bw6_761_ext::g1::G1Affine<HostHooks>;
pub type G1Projective = ark_bw6_761_ext::g1::G1Projective<HostHooks>;
pub type G2Config = ark_bw6_761_ext::g2::Config<HostHooks>;
pub type G2Affine = ark_bw6_761_ext::g2::G2Affine<HostHooks>;
pub type G2Projective = ark_bw6_761_ext::g2::G2Projective<HostHooks>;
pub type ScalarField = <BW6_761 as Pairing>::ScalarField;
pub type G1Prepared = <BW6_761 as Pairing>::G1Prepared;
pub type G2Prepared = <BW6_761 as Pairing>::G2Prepared;
pub type TargetField = <BW6_761 as Pairing>::TargetField;
#[derive(Copy, Clone)]
pub struct HostHooks;
impl CurveHooks for HostHooks {
fn multi_miller_loop(
g1: impl Iterator<Item = G1Prepared>,
g2: impl Iterator<Item = G2Prepared>,
) -> TargetField {
let mut out = utils::buffer_for::<TargetField>();
host_calls::bw6_761_multi_miller_loop(
&utils::encode_iter(g1),
&utils::encode_iter(g2),
&mut out,
)
.and_then(|_| utils::decode::<TargetField>(&out))
.expect(FAIL_MSG)
}
fn final_exponentiation(target: TargetField) -> TargetField {
let mut in_out = utils::encode(target);
host_calls::bw6_761_final_exponentiation(&mut in_out)
.and_then(|_| utils::decode::<TargetField>(&in_out))
.expect(FAIL_MSG)
}
fn msm_g1(bases: &[G1Affine], scalars: &[ScalarField]) -> G1Projective {
let mut out = utils::buffer_for::<G1Affine>();
host_calls::bw6_761_msm_g1(&utils::encode(bases), &utils::encode(scalars), &mut out)
.and_then(|_| utils::decode::<G1Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
fn msm_g2(bases: &[G2Affine], scalars: &[ScalarField]) -> G2Projective {
let mut out = utils::buffer_for::<G2Affine>();
host_calls::bw6_761_msm_g2(&utils::encode(bases), &utils::encode(scalars), &mut out)
.and_then(|_| utils::decode::<G2Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective {
let mut out = utils::buffer_for::<G1Affine>();
host_calls::bw6_761_mul_g1(
&utils::encode(base.into_affine()),
&utils::encode(scalar),
&mut out,
)
.and_then(|_| utils::decode::<G1Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective {
let mut out = utils::buffer_for::<G2Affine>();
host_calls::bw6_761_mul_g2(
&utils::encode(base.into_affine()),
&utils::encode(scalar),
&mut out,
)
.and_then(|_| utils::decode::<G2Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
}
#[runtime_interface]
pub trait HostCalls {
fn bw6_761_multi_miller_loop(
a: PassFatPointerAndRead<&[u8]>,
b: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::multi_miller_loop::<ark_bw6_761::BW6_761>(a, b, out)
}
fn bw6_761_final_exponentiation(
in_out: PassFatPointerAndReadWrite<&mut [u8]>,
) -> HostcallResult {
utils::final_exponentiation::<ark_bw6_761::BW6_761>(in_out)
}
fn bw6_761_msm_g1(
bases: PassFatPointerAndRead<&[u8]>,
scalars: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::msm_sw::<ark_bw6_761::g1::Config>(bases, scalars, out)
}
fn bw6_761_msm_g2(
bases: PassFatPointerAndRead<&[u8]>,
scalars: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::msm_sw::<ark_bw6_761::g2::Config>(bases, scalars, out)
}
fn bw6_761_mul_g1(
base: PassFatPointerAndRead<&[u8]>,
scalar: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::mul_sw::<ark_bw6_761::g1::Config>(base, scalar, out)
}
fn bw6_761_mul_g2(
base: PassFatPointerAndRead<&[u8]>,
scalar: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::mul_sw::<ark_bw6_761::g2::Config>(base, scalar, out)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::crypto_ec_utils::utils::testing::*;
#[test]
fn mul_g1_works() {
mul_test::<G1Affine, ark_bw6_761::G1Affine>();
}
#[test]
fn msm_g1_works() {
msm_test::<G1Affine, ark_bw6_761::G1Affine>();
}
#[test]
fn mul_g2_works() {
mul_test::<G2Affine, ark_bw6_761::G2Affine>();
}
#[test]
fn msm_g2_works() {
msm_test::<G2Affine, ark_bw6_761::G2Affine>();
}
#[test]
fn pairing_works() {
pairing_test::<BW6_761, ark_bw6_761::BW6_761>();
}
}