use crate::utils::{self, HostcallResult, FAIL_MSG};
use alloc::vec::Vec;
use ark_ec::{AffineRepr, CurveConfig, CurveGroup};
use ark_pallas_ext::CurveHooks;
use sp_runtime_interface::{
pass_by::{PassFatPointerAndRead, PassFatPointerAndWrite},
runtime_interface,
};
pub type PallasConfig = ark_pallas_ext::PallasConfig<HostHooks>;
pub type Affine = ark_pallas_ext::Affine<HostHooks>;
pub type Projective = ark_pallas_ext::Projective<HostHooks>;
pub type ScalarField = <PallasConfig as CurveConfig>::ScalarField;
#[derive(Copy, Clone)]
pub struct HostHooks;
impl CurveHooks for HostHooks {
fn msm(bases: &[Affine], scalars: &[ScalarField]) -> Projective {
let mut out = utils::buffer_for::<Affine>();
host_calls::pallas_msm(&utils::encode(bases), &utils::encode(scalars), &mut out)
.and_then(|_| utils::decode::<Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
fn mul_projective(base: &Projective, scalar: &[u64]) -> Projective {
let mut out = utils::buffer_for::<Affine>();
host_calls::pallas_mul(&utils::encode(base.into_affine()), &utils::encode(scalar), &mut out)
.and_then(|_| utils::decode::<Affine>(&out))
.expect(FAIL_MSG)
.into_group()
}
}
#[runtime_interface]
pub trait HostCalls {
fn pallas_msm(
bases: PassFatPointerAndRead<&[u8]>,
scalars: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::msm_sw::<ark_pallas::PallasConfig>(bases, scalars, out)
}
fn pallas_mul(
base: PassFatPointerAndRead<&[u8]>,
scalar: PassFatPointerAndRead<&[u8]>,
out: PassFatPointerAndWrite<&mut [u8]>,
) -> HostcallResult {
utils::mul_sw::<ark_pallas::PallasConfig>(base, scalar, out)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::testing::*;
#[test]
fn mul_works() {
mul_test::<Affine, ark_pallas::Affine>();
}
#[test]
fn msm_works() {
msm_test::<Affine, ark_pallas::Affine>();
}
}