// This file is part of Substrate. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! *BLS12-381* types and host functions. use crate::utils; use alloc::vec::Vec; use ark_bls12_381_ext::CurveHooks; use ark_ec::{pairing::Pairing, CurveConfig}; use sp_runtime_interface::runtime_interface; /// First pairing group definitions. pub mod g1 { pub use ark_bls12_381_ext::g1::{BETA, G1_GENERATOR_X, G1_GENERATOR_Y}; /// Group configuration. pub type Config = ark_bls12_381_ext::g1::Config; /// Short Weierstrass form point affine representation. pub type G1Affine = ark_bls12_381_ext::g1::G1Affine; /// Short Weierstrass form point projective representation. pub type G1Projective = ark_bls12_381_ext::g1::G1Projective; } /// Second pairing group definitions. pub mod g2 { pub use ark_bls12_381_ext::g2::{ G2_GENERATOR_X, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1, G2_GENERATOR_Y, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1, }; /// Group configuration. pub type Config = ark_bls12_381_ext::g2::Config; /// Short Weierstrass form point affine representation. pub type G2Affine = ark_bls12_381_ext::g2::G2Affine; /// Short Weierstrass form point projective representation. pub type G2Projective = ark_bls12_381_ext::g2::G2Projective; } pub use self::{ g1::{Config as G1Config, G1Affine, G1Projective}, g2::{Config as G2Config, G2Affine, G2Projective}, }; /// Curve hooks jumping into [`host_calls`] host functions. #[derive(Copy, Clone)] pub struct HostHooks; /// Configuration for *BLS12-381* curve. pub type Config = ark_bls12_381_ext::Config; /// *BLS12-381* definition. /// /// A generic *BLS12* model specialized with *BLS12-381* configuration. pub type Bls12_381 = ark_bls12_381_ext::Bls12_381; impl CurveHooks for HostHooks { fn bls12_381_multi_miller_loop( g1: impl Iterator::G1Prepared>, g2: impl Iterator::G2Prepared>, ) -> Result<::TargetField, ()> { let g1 = utils::encode(g1.collect::>()); let g2 = utils::encode(g2.collect::>()); let res = host_calls::bls12_381_multi_miller_loop(g1, g2).unwrap_or_default(); utils::decode(res) } fn bls12_381_final_exponentiation( target: ::TargetField, ) -> Result<::TargetField, ()> { let target = utils::encode(target); let res = host_calls::bls12_381_final_exponentiation(target).unwrap_or_default(); utils::decode(res) } fn bls12_381_msm_g1( bases: &[G1Affine], scalars: &[::ScalarField], ) -> Result { let bases = utils::encode(bases); let scalars = utils::encode(scalars); let res = host_calls::bls12_381_msm_g1(bases, scalars).unwrap_or_default(); utils::decode_proj_sw(res) } fn bls12_381_msm_g2( bases: &[G2Affine], scalars: &[::ScalarField], ) -> Result { let bases = utils::encode(bases); let scalars = utils::encode(scalars); let res = host_calls::bls12_381_msm_g2(bases, scalars).unwrap_or_default(); utils::decode_proj_sw(res) } fn bls12_381_mul_projective_g1( base: &G1Projective, scalar: &[u64], ) -> Result { let base = utils::encode_proj_sw(base); let scalar = utils::encode(scalar); let res = host_calls::bls12_381_mul_projective_g1(base, scalar).unwrap_or_default(); utils::decode_proj_sw(res) } fn bls12_381_mul_projective_g2( base: &G2Projective, scalar: &[u64], ) -> Result { let base = utils::encode_proj_sw(base); let scalar = utils::encode(scalar); let res = host_calls::bls12_381_mul_projective_g2(base, scalar).unwrap_or_default(); utils::decode_proj_sw(res) } } /// Interfaces for working with *Arkworks* *BLS12-381* elliptic curve related types /// from within the runtime. /// /// All types are (de-)serialized through the wrapper types from the `ark-scale` trait, /// with `ark_scale::{ArkScale, ArkScaleProjective}`. /// /// `ArkScale`'s `Usage` generic parameter is expected to be set to "not-validated" /// and "not-compressed". #[runtime_interface] pub trait HostCalls { /// Pairing multi Miller loop for *BLS12-381*. /// /// - Receives encoded: /// - `a`: `ArkScale>`. /// - `b`: `ArkScale>`. /// - Returns encoded: `ArkScale`. fn bls12_381_multi_miller_loop(a: Vec, b: Vec) -> Result, ()> { utils::multi_miller_loop::(a, b) } /// Pairing final exponentiation for *BLS12-381*. /// /// - Receives encoded: `ArkScale<`. /// - Returns encoded: `ArkScale<` fn bls12_381_final_exponentiation(f: Vec) -> Result, ()> { utils::final_exponentiation::(f) } /// Multi scalar multiplication on *G1* for *BLS12-381* /// /// - Receives encoded: /// - `bases`: `ArkScale>`. /// - `scalars`: `ArkScale>`. /// - Returns encoded: `ArkScaleProjective`. fn bls12_381_msm_g1(bases: Vec, scalars: Vec) -> Result, ()> { utils::msm_sw::(bases, scalars) } /// Multi scalar multiplication on *G2* for *BLS12-381* /// /// - Receives encoded: /// - `bases`: `ArkScale>`. /// - `scalars`: `ArkScale>`. /// - Returns encoded: `ArkScaleProjective`. fn bls12_381_msm_g2(bases: Vec, scalars: Vec) -> Result, ()> { utils::msm_sw::(bases, scalars) } /// Projective multiplication on *G1* for *BLS12-381*. /// /// - Receives encoded: /// - `base`: `ArkScaleProjective`. /// - `scalar`: `ArkScale>`. /// - Returns encoded: `ArkScaleProjective`. fn bls12_381_mul_projective_g1(base: Vec, scalar: Vec) -> Result, ()> { utils::mul_projective_sw::(base, scalar) } /// Projective multiplication on *G2* for *BLS12-381* /// /// - Receives encoded: /// - `base`: `ArkScaleProjective`. /// - `scalar`: `ArkScale>`. /// - Returns encoded: `ArkScaleProjective`. fn bls12_381_mul_projective_g2(base: Vec, scalar: Vec) -> Result, ()> { utils::mul_projective_sw::(base, scalar) } }