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}