revm_precompile/bls12_381/
g2_add.rs

1use super::crypto_backend::{encode_g2_point, p2_add_affine, read_g2_no_subgroup_check};
2use super::utils::remove_g2_padding;
3use crate::bls12_381_const::{
4    G2_ADD_ADDRESS, G2_ADD_BASE_GAS_FEE, G2_ADD_INPUT_LENGTH, PADDED_G2_LENGTH,
5};
6use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress};
7use primitives::Bytes;
8
9/// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2ADD precompile.
10pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_ADD_ADDRESS, g2_add);
11
12/// G2 addition call expects `512` bytes as an input that is interpreted as byte
13/// concatenation of two G2 points (`256` bytes each).
14///
15/// Output is an encoding of addition operation result - single G2 point (`256`
16/// bytes).
17/// See also <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-addition>
18pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
19    if G2_ADD_BASE_GAS_FEE > gas_limit {
20        return Err(PrecompileError::OutOfGas);
21    }
22
23    if input.len() != G2_ADD_INPUT_LENGTH {
24        return Err(PrecompileError::Other(format!(
25            "G2ADD input should be {G2_ADD_INPUT_LENGTH} bytes, was {}",
26            input.len()
27        )));
28    }
29
30    let [a_x_0, a_x_1, a_y_0, a_y_1] = remove_g2_padding(&input[..PADDED_G2_LENGTH])?;
31    let [b_x_0, b_x_1, b_y_0, b_y_1] = remove_g2_padding(&input[PADDED_G2_LENGTH..])?;
32
33    // NB: There is no subgroup check for the G2 addition precompile because the time to do the subgroup
34    // check would be more than the time it takes to to do the g1 addition.
35    //
36    // Users should be careful to note whether the points being added are indeed in the right subgroup.
37    let a_aff = &read_g2_no_subgroup_check(a_x_0, a_x_1, a_y_0, a_y_1)?;
38    let b_aff = &read_g2_no_subgroup_check(b_x_0, b_x_1, b_y_0, b_y_1)?;
39
40    // Use the safe wrapper for G2 point addition
41    let p_aff = p2_add_affine(a_aff, b_aff);
42
43    let out = encode_g2_point(&p_aff);
44    Ok(PrecompileOutput::new(G2_ADD_BASE_GAS_FEE, out.into()))
45}