gbuiltin_bls381/lib.rs
1// This file is part of Gear.
2
3// Copyright (C) 2024-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19#![cfg_attr(not(feature = "std"), no_std)]
20
21extern crate alloc;
22
23use alloc::vec::Vec;
24use parity_scale_codec::{Decode, Encode};
25use scale_info::TypeInfo;
26
27pub use ark_bls12_381;
28pub use ark_ec;
29pub use ark_ff;
30pub use ark_scale;
31pub use ark_serialize;
32
33/// Constant defines codec index of [`Request::MultiMillerLoop`].
34pub const REQUEST_MULTI_MILLER_LOOP: u8 = 0;
35/// Constant defines codec index of [`Request::FinalExponentiation`].
36pub const REQUEST_FINAL_EXPONENTIATION: u8 = 1;
37/// Constant defines codec index of [`Request::MultiScalarMultiplicationG1`].
38pub const REQUEST_MULTI_SCALAR_MULTIPLICATION_G1: u8 = 2;
39/// Constant defines codec index of [`Request::MultiScalarMultiplicationG2`].
40pub const REQUEST_MULTI_SCALAR_MULTIPLICATION_G2: u8 = 3;
41/// Constant defines codec index of [`Request::ProjectiveMultiplicationG1`].
42pub const REQUEST_PROJECTIVE_MULTIPLICATION_G1: u8 = 4;
43/// Constant defines codec index of [`Request::ProjectiveMultiplicationG2`].
44pub const REQUEST_PROJECTIVE_MULTIPLICATION_G2: u8 = 5;
45/// Constant defines codec index of [`Request::AggregateG1`].
46pub const REQUEST_AGGREGATE_G1: u8 = 6;
47/// Constant defines codec index of [`Request::MapToG2Affine`].
48pub const REQUEST_MAP_TO_G2AFFINE: u8 = 7;
49
50/// Type that should be used to create a message to the bls12_381 builtin actor.
51/// Use the following crates to construct a request:
52/// - `ark-scale`: <https://docs.rs/ark-scale/>;
53/// - `ark-bls12-381`: <https://docs.rs/ark-bls12-381/>.
54#[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
55pub enum Request {
56 /// Request to pairing multi Miller loop for *BLS12-381*.
57 ///
58 /// Encoded:
59 /// - `a`: [`ArkScale<Vec<G1Affine>>`](https://docs.rs/ark-scale/).
60 /// - `b`: [`ArkScale<Vec<G2Affine>>`](https://docs.rs/ark-scale/).
61 #[codec(index = 0)]
62 MultiMillerLoop { a: Vec<u8>, b: Vec<u8> },
63
64 /// Request to pairing final exponentiation for *BLS12-381*.
65 ///
66 /// Encoded: [`ArkScale<<Bls12_381::TargetField>`](https://docs.rs/ark-scale/).
67 #[codec(index = 1)]
68 FinalExponentiation { f: Vec<u8> },
69
70 /// Request to multi scalar multiplication on *G1* for *BLS12-381*
71 ///
72 /// Encoded:
73 /// - `bases`: [`ArkScale<Vec<G1Affine>>`](https://docs.rs/ark-scale/).
74 /// - `scalars`: [`ArkScale<Vec<G1Config::ScalarField>>`](https://docs.rs/ark-scale/).
75 #[codec(index = 2)]
76 MultiScalarMultiplicationG1 { bases: Vec<u8>, scalars: Vec<u8> },
77
78 /// Request to multi scalar multiplication on *G2* for *BLS12-381*
79 ///
80 /// Encoded:
81 /// - `bases`: [`ArkScale<Vec<G2Affine>>`](https://docs.rs/ark-scale/).
82 /// - `scalars`: [`ArkScale<Vec<G2Config::ScalarField>>`](https://docs.rs/ark-scale/).
83 #[codec(index = 3)]
84 MultiScalarMultiplicationG2 { bases: Vec<u8>, scalars: Vec<u8> },
85
86 /// Request to projective multiplication on *G1* for *BLS12-381*.
87 ///
88 /// Encoded:
89 /// - `base`: [`ArkScaleProjective<G1Projective>`](https://docs.rs/ark-scale/).
90 /// - `scalar`: [`ArkScale<Vec<u64>>`](https://docs.rs/ark-scale/).
91 #[codec(index = 4)]
92 ProjectiveMultiplicationG1 { base: Vec<u8>, scalar: Vec<u8> },
93
94 /// Request to projective multiplication on *G2* for *BLS12-381*.
95 ///
96 /// Encoded:
97 /// - `base`: [`ArkScaleProjective<G2Projective>`](https://docs.rs/ark-scale/).
98 /// - `scalar`: [`ArkScale<Vec<u64>>`](https://docs.rs/ark-scale/).
99 #[codec(index = 5)]
100 ProjectiveMultiplicationG2 { base: Vec<u8>, scalar: Vec<u8> },
101
102 /// Request to aggregate *G1* points for *BLS12-381*.
103 ///
104 /// Encoded: [`ArkScale<Vec<G1Projective>>`](https://docs.rs/ark-scale/).
105 #[codec(index = 6)]
106 AggregateG1 { points: Vec<u8> },
107
108 /// Request to map an arbitrary message to *G2Affine* point for *BLS12-381*.
109 ///
110 /// Raw message bytes to map.
111 #[codec(index = 7)]
112 MapToG2Affine { message: Vec<u8> },
113}
114
115/// The enumeration contains result to a request.
116#[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
117pub enum Response {
118 /// Result of the multi Miller loop, encoded: [`ArkScale<Bls12_381::TargetField>`](https://docs.rs/ark-scale/).
119 #[codec(index = 0)]
120 MultiMillerLoop(Vec<u8>),
121 /// Result of the final exponentiation, encoded: [`ArkScale<Bls12_381::TargetField>`](https://docs.rs/ark-scale/).
122 #[codec(index = 1)]
123 FinalExponentiation(Vec<u8>),
124 /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective<G1Projective>`](https://docs.rs/ark-scale/).
125 #[codec(index = 2)]
126 MultiScalarMultiplicationG1(Vec<u8>),
127 /// Result of the multi scalar multiplication, encoded: [`ArkScaleProjective<G2Projective>`](https://docs.rs/ark-scale/).
128 #[codec(index = 3)]
129 MultiScalarMultiplicationG2(Vec<u8>),
130 /// Result of the projective multiplication, encoded: [`ArkScaleProjective<G1Projective>`](https://docs.rs/ark-scale/).
131 #[codec(index = 4)]
132 ProjectiveMultiplicationG1(Vec<u8>),
133 /// Result of the projective multiplication, encoded: [`ArkScaleProjective<G2Projective>`](https://docs.rs/ark-scale/).
134 #[codec(index = 5)]
135 ProjectiveMultiplicationG2(Vec<u8>),
136 /// Result of the aggregation, encoded: [`ArkScale<G1Projective>`](https://docs.rs/ark-scale/).
137 #[codec(index = 6)]
138 AggregateG1(Vec<u8>),
139 /// Result of the mapping, encoded: [`ArkScale<G2Affine>`](https://docs.rs/ark-scale/).
140 #[codec(index = 7)]
141 MapToG2Affine(Vec<u8>),
142}
143
144#[cfg(test)]
145mod tests {
146 extern crate alloc;
147
148 use super::*;
149 use alloc::vec;
150
151 // The standard Decode implementation cannot be used for precise gas charging.
152 // The following test checks that scale codec indexes of variants are set correctly.
153 #[test]
154 fn codec_enum_indexes() {
155 for (index, (variant, request, response)) in [
156 (
157 REQUEST_MULTI_MILLER_LOOP,
158 Request::MultiMillerLoop {
159 a: vec![],
160 b: vec![],
161 },
162 Response::MultiMillerLoop(vec![]),
163 ),
164 (
165 REQUEST_FINAL_EXPONENTIATION,
166 Request::FinalExponentiation { f: vec![] },
167 Response::FinalExponentiation(vec![]),
168 ),
169 (
170 REQUEST_MULTI_SCALAR_MULTIPLICATION_G1,
171 Request::MultiScalarMultiplicationG1 {
172 bases: vec![],
173 scalars: vec![],
174 },
175 Response::MultiScalarMultiplicationG1(vec![]),
176 ),
177 (
178 REQUEST_MULTI_SCALAR_MULTIPLICATION_G2,
179 Request::MultiScalarMultiplicationG2 {
180 bases: vec![],
181 scalars: vec![],
182 },
183 Response::MultiScalarMultiplicationG2(vec![]),
184 ),
185 (
186 REQUEST_PROJECTIVE_MULTIPLICATION_G1,
187 Request::ProjectiveMultiplicationG1 {
188 base: vec![],
189 scalar: vec![],
190 },
191 Response::ProjectiveMultiplicationG1(vec![]),
192 ),
193 (
194 REQUEST_PROJECTIVE_MULTIPLICATION_G2,
195 Request::ProjectiveMultiplicationG2 {
196 base: vec![],
197 scalar: vec![],
198 },
199 Response::ProjectiveMultiplicationG2(vec![]),
200 ),
201 (
202 REQUEST_AGGREGATE_G1,
203 Request::AggregateG1 { points: vec![] },
204 Response::AggregateG1(vec![]),
205 ),
206 (
207 REQUEST_MAP_TO_G2AFFINE,
208 Request::MapToG2Affine { message: vec![] },
209 Response::MapToG2Affine(vec![]),
210 ),
211 ]
212 .into_iter()
213 .enumerate()
214 {
215 assert_eq!(index, variant.into());
216
217 let request = request.encode();
218 assert!(matches!(request.first().copied(), Some(v) if v == variant));
219
220 let response = response.encode();
221 assert!(matches!(response.first().copied(), Some(v) if v == variant));
222 }
223 }
224}