builtins_common/
bls12_381.rs

1// This file is part of Gear.
2
3// Copyright (C) 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
19mod high_level;
20mod low_level;
21
22pub use gbuiltin_bls381::{
23    Request, Response, ark_bls12_381, ark_ec, ark_ff, ark_scale, ark_serialize,
24};
25pub use high_level::*;
26pub use low_level::Bls12_381OpsLowLevel;
27
28use super::{BuiltinActorError, BuiltinContext};
29use alloc::{vec, vec::Vec};
30use gbuiltin_bls381::{
31    REQUEST_AGGREGATE_G1, REQUEST_FINAL_EXPONENTIATION, REQUEST_MAP_TO_G2AFFINE,
32    REQUEST_MULTI_MILLER_LOOP, REQUEST_MULTI_SCALAR_MULTIPLICATION_G1,
33    REQUEST_MULTI_SCALAR_MULTIPLICATION_G2, REQUEST_PROJECTIVE_MULTIPLICATION_G1,
34    REQUEST_PROJECTIVE_MULTIPLICATION_G2,
35};
36
37/// Executes BLS12-381 built-in functions.
38///
39/// Checks the first byte of the input to determine which BLS12-381 operation to perform,
40/// and then calls the corresponding function with the remaining input bytes.
41pub fn execute_bls12_381_builtins<Gas: BlsOpsGasCost, Ops: Bls12_381Ops>(
42    input: &[u8],
43    context: &mut BuiltinContext,
44) -> Result<Response, BuiltinActorError> {
45    match input.first().copied() {
46        Some(REQUEST_MULTI_MILLER_LOOP) => {
47            high_level::multi_miller_loop::<Gas, Ops>(&input[1..], context)
48        }
49        Some(REQUEST_FINAL_EXPONENTIATION) => {
50            high_level::final_exponentiation::<Gas, Ops>(&input[1..], context)
51        }
52        Some(REQUEST_MULTI_SCALAR_MULTIPLICATION_G1) => high_level::msm::<Gas>(
53            &input[1..],
54            context,
55            Gas::bls12_381_msm_g1,
56            |bases, scalars| Ops::msm_g1(bases, scalars).map(Response::MultiScalarMultiplicationG1),
57        ),
58        Some(REQUEST_MULTI_SCALAR_MULTIPLICATION_G2) => high_level::msm::<Gas>(
59            &input[1..],
60            context,
61            Gas::bls12_381_msm_g2,
62            |bases, scalars| Ops::msm_g2(bases, scalars).map(Response::MultiScalarMultiplicationG2),
63        ),
64        Some(REQUEST_PROJECTIVE_MULTIPLICATION_G1) => high_level::projective_multiplication::<Gas>(
65            &input[1..],
66            context,
67            Gas::bls12_381_mul_projective_g1,
68            |base, scalar| {
69                Ops::projective_mul_g1(base, scalar).map(Response::ProjectiveMultiplicationG1)
70            },
71        ),
72        Some(REQUEST_PROJECTIVE_MULTIPLICATION_G2) => high_level::projective_multiplication::<Gas>(
73            &input[1..],
74            context,
75            Gas::bls12_381_mul_projective_g2,
76            |base, scalar| {
77                Ops::projective_mul_g2(base, scalar).map(Response::ProjectiveMultiplicationG2)
78            },
79        ),
80        Some(REQUEST_AGGREGATE_G1) => high_level::aggregate_g1::<Gas, Ops>(&input[1..], context),
81        Some(REQUEST_MAP_TO_G2AFFINE) => {
82            high_level::map_to_g2affine::<Gas, Ops>(&input[1..], context)
83        }
84        _ => Err(BuiltinActorError::DecodingError),
85    }
86}
87
88/// BLS12-381 operations gas cost trait.
89///
90/// Depending on the environment (e.g., runtime or tests), different values for gas costs
91/// can be provided by implementing this trait accordingly.
92pub trait BlsOpsGasCost {
93    /// Returns gas cost for decoding bytes.
94    fn decode_bytes(len: u32) -> u64;
95    /// Returns gas cost for BLS12-381 multi Miller loop operation.
96    fn bls12_381_multi_miller_loop(count: u32) -> u64;
97    /// Returns gas cost for BLS12-381 final exponentiation operation.
98    fn bls12_381_final_exponentiation() -> u64;
99    /// Returns gas cost for BLS12-381 MSM G1 operation.
100    fn bls12_381_msm_g1(count: u32) -> u64;
101    /// Returns gas cost for BLS12-381 MSM G2 operation.
102    fn bls12_381_msm_g2(count: u32) -> u64;
103    /// Returns gas cost for BLS12-381 projective multiplication G1 operation.
104    fn bls12_381_mul_projective_g1(count: u32) -> u64;
105    /// Returns gas cost for BLS12-381 projective multiplication G2 operation.
106    fn bls12_381_mul_projective_g2(count: u32) -> u64;
107    /// Returns gas cost for BLS12-381 G1 aggregation operation.
108    fn bls12_381_aggregate_g1(count: u32) -> u64;
109    /// Returns gas cost for BLS12-381 map to G2Affine operation.
110    fn bls12_381_map_to_g2affine(len: u32) -> u64;
111}
112/// Bls12-381 operations trait.
113///
114/// The trait abstracts the actual implementation of BLS12-381 operations. Depending
115/// on the environment (e.g., runtime or tests), bls operations can be implemented
116/// as host calls from the runtime, or directly using the `ark`s crates.
117pub trait Bls12_381Ops {
118    /// Performs the multi Miller loop operation on pairs of G1 and G2 points.
119    fn multi_miller_loop(g1: Vec<u8>, g2: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
120    /// Performs the final exponentiation operation.
121    fn final_exponentiation(f: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
122    /// Performs the multi-scalar multiplication operation on G1 points.
123    fn msm_g1(bases: Vec<u8>, scalars: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
124    /// Performs the multi-scalar multiplication operation on G2 points.
125    fn msm_g2(bases: Vec<u8>, scalars: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
126    /// Performs the projective multiplication operation on G1 points.
127    fn projective_mul_g1(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
128    /// Performs the projective multiplication operation on G2 points.
129    fn projective_mul_g2(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
130    /// Performs the aggregation operation on G1 points.
131    fn aggregate_g1(points: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
132    /// Maps a message to a G2Affine point.
133    fn map_to_g2affine(message: Vec<u8>) -> Result<Vec<u8>, BuiltinActorError>;
134}