revm_precompile/bls12_381/
g1_add.rs
1use super::g1::{encode_g1_point, extract_g1_input, G1_INPUT_ITEM_LENGTH};
2use crate::{u64_to_address, PrecompileWithAddress};
3use blst::{
4 blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine,
5};
6use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult};
7
8pub const PRECOMPILE: PrecompileWithAddress =
10 PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g1_add));
11pub const ADDRESS: u64 = 0x0b;
13const BASE_GAS_FEE: u64 = 500;
15
16const INPUT_LENGTH: usize = 256;
18
19pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
25 if BASE_GAS_FEE > gas_limit {
26 return Err(PrecompileError::OutOfGas.into());
27 }
28
29 if input.len() != INPUT_LENGTH {
30 return Err(PrecompileError::Other(format!(
31 "G1ADD input should be {INPUT_LENGTH} bytes, was {}",
32 input.len()
33 ))
34 .into());
35 }
36
37 let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?;
41 let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?;
42
43 let mut b = blst_p1::default();
44 unsafe { blst_p1_from_affine(&mut b, b_aff) };
46
47 let mut p = blst_p1::default();
48 unsafe { blst_p1_add_or_double_affine(&mut p, &b, a_aff) };
50
51 let mut p_aff = blst_p1_affine::default();
52 unsafe { blst_p1_to_affine(&mut p_aff, &p) };
54
55 let out = encode_g1_point(&p_aff);
56 Ok(PrecompileOutput::new(BASE_GAS_FEE, out))
57}