referrerpolicy=no-referrer-when-downgrade

sp_crypto_ec_utils/
bls12_377.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! *BLS12-377* types and host functions.
19
20use crate::utils::{self, HostcallResult, FAIL_MSG};
21use alloc::vec::Vec;
22use ark_bls12_377_ext::CurveHooks;
23use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
24use sp_runtime_interface::{
25	pass_by::{PassFatPointerAndRead, PassFatPointerAndReadWrite, PassFatPointerAndWrite},
26	runtime_interface,
27};
28
29/// Configuration for *BLS12-377* curve.
30pub type Config = ark_bls12_377_ext::Config<HostHooks>;
31
32/// *BLS12-377* pairing friendly curve.
33pub type Bls12_377 = ark_bls12_377_ext::Bls12_377<HostHooks>;
34
35/// G1 group configuration.
36pub type G1Config = ark_bls12_377_ext::g1::Config<HostHooks>;
37/// An element in G1 (affine).
38pub type G1Affine = ark_bls12_377_ext::g1::G1Affine<HostHooks>;
39/// An element in G1 (projective).
40pub type G1Projective = ark_bls12_377_ext::g1::G1Projective<HostHooks>;
41
42/// G2 group configuration.
43pub type G2Config = ark_bls12_377_ext::g2::Config<HostHooks>;
44/// An element in G2 (affine).
45pub type G2Affine = ark_bls12_377_ext::g2::G2Affine<HostHooks>;
46/// An element in G2 (projective).
47pub type G2Projective = ark_bls12_377_ext::g2::G2Projective<HostHooks>;
48
49/// G1 and G2 scalar field (Fr).
50pub type ScalarField = <Bls12_377 as Pairing>::ScalarField;
51
52/// An element in G1 preprocessed for pairing.
53pub type G1Prepared = <Bls12_377 as Pairing>::G1Prepared;
54/// An element in G2 preprocessed for pairing.
55pub type G2Prepared = <Bls12_377 as Pairing>::G2Prepared;
56/// Pairing target field.
57pub type TargetField = <Bls12_377 as Pairing>::TargetField;
58
59/// Curve hooks jumping into [`host_calls`] host functions.
60#[derive(Copy, Clone)]
61pub struct HostHooks;
62
63impl CurveHooks for HostHooks {
64	fn multi_miller_loop(
65		g1: impl Iterator<Item = G1Prepared>,
66		g2: impl Iterator<Item = G2Prepared>,
67	) -> TargetField {
68		let mut out = utils::buffer_for::<TargetField>();
69		host_calls::bls12_377_multi_miller_loop(
70			&utils::encode_iter(g1),
71			&utils::encode_iter(g2),
72			&mut out,
73		)
74		.and_then(|_| utils::decode::<TargetField>(&out))
75		.expect(FAIL_MSG)
76	}
77
78	fn final_exponentiation(target: TargetField) -> TargetField {
79		let mut in_out = utils::encode(target);
80		host_calls::bls12_377_final_exponentiation(&mut in_out)
81			.and_then(|_| utils::decode::<TargetField>(&in_out))
82			.expect(FAIL_MSG)
83	}
84
85	fn msm_g1(bases: &[G1Affine], scalars: &[ScalarField]) -> G1Projective {
86		let mut out = utils::buffer_for::<G1Affine>();
87		host_calls::bls12_377_msm_g1(&utils::encode(bases), &utils::encode(scalars), &mut out)
88			.and_then(|_| utils::decode::<G1Affine>(&out))
89			.expect(FAIL_MSG)
90			.into_group()
91	}
92
93	fn msm_g2(bases: &[G2Affine], scalars: &[ScalarField]) -> G2Projective {
94		let mut out = utils::buffer_for::<G2Affine>();
95		host_calls::bls12_377_msm_g2(&utils::encode(bases), &utils::encode(scalars), &mut out)
96			.and_then(|_| utils::decode::<G2Affine>(&out))
97			.expect(FAIL_MSG)
98			.into_group()
99	}
100
101	fn mul_projective_g1(base: &G1Projective, scalar: &[u64]) -> G1Projective {
102		let mut out = utils::buffer_for::<G1Affine>();
103		host_calls::bls12_377_mul_g1(
104			&utils::encode(base.into_affine()),
105			&utils::encode(scalar),
106			&mut out,
107		)
108		.and_then(|_| utils::decode::<G1Affine>(&out))
109		.expect(FAIL_MSG)
110		.into_group()
111	}
112
113	fn mul_projective_g2(base: &G2Projective, scalar: &[u64]) -> G2Projective {
114		let mut out = utils::buffer_for::<G2Affine>();
115		host_calls::bls12_377_mul_g2(
116			&utils::encode(base.into_affine()),
117			&utils::encode(scalar),
118			&mut out,
119		)
120		.and_then(|_| utils::decode::<G2Affine>(&out))
121		.expect(FAIL_MSG)
122		.into_group()
123	}
124}
125
126/// Interfaces for working with *Arkworks* *BLS12-377* elliptic curve related types
127/// from within the runtime.
128///
129/// All types are (de-)serialized through the wrapper types from `ark-scale`.
130///
131/// `ArkScale`'s `Usage` generic parameter is expected to be set to "not-validated"
132/// and "not-compressed".
133#[runtime_interface]
134pub trait HostCalls {
135	/// Pairing multi Miller loop for *BLS12-377*.
136	///
137	/// Receives encoded:
138	/// - `a`: `Vec<G1Affine>`.
139	/// - `b`: `Vec<G2Affine>`.
140	/// Writes encoded `TargetField` to `out`.
141	fn bls12_377_multi_miller_loop(
142		a: PassFatPointerAndRead<&[u8]>,
143		b: PassFatPointerAndRead<&[u8]>,
144		out: PassFatPointerAndWrite<&mut [u8]>,
145	) -> HostcallResult {
146		utils::multi_miller_loop::<ark_bls12_377::Bls12_377>(a, b, out)
147	}
148
149	/// Pairing final exponentiation for *BLS12-377*.
150	///
151	/// Receives encoded: `TargetField`.
152	/// Writes encoded `TargetField` to `in_out`.
153	fn bls12_377_final_exponentiation(
154		in_out: PassFatPointerAndReadWrite<&mut [u8]>,
155	) -> HostcallResult {
156		utils::final_exponentiation::<ark_bls12_377::Bls12_377>(in_out)
157	}
158
159	/// Multi scalar multiplication on *G1* for *BLS12-377*.
160	///
161	/// Receives encoded:
162	/// - `bases`: `Vec<G1Affine>`.
163	/// - `scalars`: `Vec<ScalarField>`.
164	/// Writes encoded `G1Affine` to `out`.
165	fn bls12_377_msm_g1(
166		bases: PassFatPointerAndRead<&[u8]>,
167		scalars: PassFatPointerAndRead<&[u8]>,
168		out: PassFatPointerAndWrite<&mut [u8]>,
169	) -> HostcallResult {
170		utils::msm_sw::<ark_bls12_377::g1::Config>(bases, scalars, out)
171	}
172
173	/// Multi scalar multiplication on *G2* for *BLS12-377*.
174	///
175	/// Receives encoded:
176	/// - `bases`: `Vec<G2Affine>`.
177	/// - `scalars`: `Vec<ScalarField>`.
178	/// Writes encoded `G2Affine` to `out`.
179	fn bls12_377_msm_g2(
180		bases: PassFatPointerAndRead<&[u8]>,
181		scalars: PassFatPointerAndRead<&[u8]>,
182		out: PassFatPointerAndWrite<&mut [u8]>,
183	) -> HostcallResult {
184		utils::msm_sw::<ark_bls12_377::g2::Config>(bases, scalars, out)
185	}
186
187	/// Affine multiplication on *G1* for *BLS12-377*.
188	///
189	/// Receives encoded:
190	/// - `base`: `G1Affine`.
191	/// - `scalar`: `BigInteger`.
192	/// Writes encoded `G1Affine` to `out`.
193	fn bls12_377_mul_g1(
194		base: PassFatPointerAndRead<&[u8]>,
195		scalar: PassFatPointerAndRead<&[u8]>,
196		out: PassFatPointerAndWrite<&mut [u8]>,
197	) -> HostcallResult {
198		utils::mul_sw::<ark_bls12_377::g1::Config>(base, scalar, out)
199	}
200
201	/// Affine multiplication on *G2* for *BLS12-377*.
202	///
203	/// Receives encoded:
204	/// - `base`: `G2Affine`.
205	/// - `scalar`: `BigInteger`.
206	/// Writes encoded `G2Affine` to `out`.
207	fn bls12_377_mul_g2(
208		base: PassFatPointerAndRead<&[u8]>,
209		scalar: PassFatPointerAndRead<&[u8]>,
210		out: PassFatPointerAndWrite<&mut [u8]>,
211	) -> HostcallResult {
212		utils::mul_sw::<ark_bls12_377::g2::Config>(base, scalar, out)
213	}
214}
215
216#[cfg(test)]
217mod tests {
218	use super::*;
219	use crate::utils::testing::*;
220
221	#[test]
222	fn mul_g1_works() {
223		mul_test::<G1Affine, ark_bls12_377::G1Affine>();
224	}
225
226	#[test]
227	fn msm_g1_works() {
228		msm_test::<G1Affine, ark_bls12_377::G1Affine>();
229	}
230
231	#[test]
232	fn mul_g2_works() {
233		mul_test::<G2Affine, ark_bls12_377::G2Affine>();
234	}
235
236	#[test]
237	fn msm_g2_works() {
238		msm_test::<G2Affine, ark_bls12_377::G2Affine>();
239	}
240
241	#[test]
242	fn pairing_works() {
243		pairing_test::<Bls12_377, ark_bls12_377::Bls12_377>();
244	}
245}