revm_precompile/bls12_381/
g1_add.rs

1use super::g1::{encode_g1_point, extract_g1_input};
2use crate::bls12_381_const::{
3    G1_ADD_ADDRESS, G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH, G1_INPUT_ITEM_LENGTH,
4};
5use crate::{u64_to_address, PrecompileWithAddress};
6use crate::{PrecompileError, PrecompileOutput, PrecompileResult};
7use blst::{
8    blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine,
9};
10use primitives::Bytes;
11
12/// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile.
13pub const PRECOMPILE: PrecompileWithAddress =
14    PrecompileWithAddress(u64_to_address(G1_ADD_ADDRESS), g1_add);
15
16/// G1 addition call expects `256` bytes as an input that is interpreted as byte
17/// concatenation of two G1 points (`128` bytes each).
18/// Output is an encoding of addition operation result - single G1 point (`128`
19/// bytes).
20/// See also: <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition>
21pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
22    if G1_ADD_BASE_GAS_FEE > gas_limit {
23        return Err(PrecompileError::OutOfGas);
24    }
25
26    if input.len() != G1_ADD_INPUT_LENGTH {
27        return Err(PrecompileError::Other(format!(
28            "G1ADD input should be {G1_ADD_INPUT_LENGTH} bytes, was {}",
29            input.len()
30        )));
31    }
32
33    // NB: There is no subgroup check for the G1 addition precompile.
34    //
35    // So we set the subgroup checks here to `false`
36    let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?;
37    let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?;
38
39    let mut b = blst_p1::default();
40    // SAFETY: `b` and `b_aff` are blst values.
41    unsafe { blst_p1_from_affine(&mut b, b_aff) };
42
43    let mut p = blst_p1::default();
44    // SAFETY: `p`, `b` and `a_aff` are blst values.
45    unsafe { blst_p1_add_or_double_affine(&mut p, &b, a_aff) };
46
47    let mut p_aff = blst_p1_affine::default();
48    // SAFETY: `p_aff` and `p`` are blst values.
49    unsafe { blst_p1_to_affine(&mut p_aff, &p) };
50
51    let out = encode_g1_point(&p_aff);
52    Ok(PrecompileOutput::new(G1_ADD_BASE_GAS_FEE, out))
53}