revm_precompile/bls12_381/
g1_add.rs

1use super::crypto_backend::{encode_g1_point, p1_add_affine, read_g1_no_subgroup_check};
2use super::utils::remove_g1_padding;
3use crate::bls12_381_const::{
4    G1_ADD_ADDRESS, G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH, PADDED_G1_LENGTH,
5};
6use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress};
7use primitives::Bytes;
8
9/// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile.
10pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_ADD_ADDRESS, g1_add);
11
12/// G1 addition call expects `256` bytes as an input that is interpreted as byte
13/// concatenation of two G1 points (`128` bytes each).
14/// Output is an encoding of addition operation result - single G1 point (`128`
15/// bytes).
16/// See also: <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition>
17pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
18    if G1_ADD_BASE_GAS_FEE > gas_limit {
19        return Err(PrecompileError::OutOfGas);
20    }
21
22    if input.len() != G1_ADD_INPUT_LENGTH {
23        return Err(PrecompileError::Other(format!(
24            "G1ADD input should be {G1_ADD_INPUT_LENGTH} bytes, was {}",
25            input.len()
26        )));
27    }
28
29    let [a_x, a_y] = remove_g1_padding(&input[..PADDED_G1_LENGTH])?;
30    let [b_x, b_y] = remove_g1_padding(&input[PADDED_G1_LENGTH..])?;
31
32    // NB: There is no subgroup check for the G1 addition precompile because the time to do the subgroup
33    // check would be more than the time it takes to to do the g1 addition.
34    //
35    // Users should be careful to note whether the points being added are indeed in the right subgroup.
36    let a_aff = &read_g1_no_subgroup_check(a_x, a_y)?;
37    let b_aff = &read_g1_no_subgroup_check(b_x, b_y)?;
38    let p_aff = p1_add_affine(a_aff, b_aff);
39
40    let out = encode_g1_point(&p_aff);
41    Ok(PrecompileOutput::new(G1_ADD_BASE_GAS_FEE, out.into()))
42}