revm_precompile/bls12_381/
g2_add.rsuse super::g2::{encode_g2_point, extract_g2_input, G2_INPUT_ITEM_LENGTH};
use crate::{u64_to_address, PrecompileWithAddress};
use blst::{
blst_p2, blst_p2_add_or_double_affine, blst_p2_affine, blst_p2_from_affine, blst_p2_to_affine,
};
use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult};
pub const PRECOMPILE: PrecompileWithAddress =
PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g2_add));
pub const ADDRESS: u64 = 0x0e;
const BASE_GAS_FEE: u64 = 800;
const INPUT_LENGTH: usize = 512;
pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
if BASE_GAS_FEE > gas_limit {
return Err(PrecompileError::OutOfGas.into());
}
if input.len() != INPUT_LENGTH {
return Err(PrecompileError::Other(format!(
"G2ADD input should be {INPUT_LENGTH} bytes, was {}",
input.len()
))
.into());
}
let a_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], false)?;
let b_aff = &extract_g2_input(&input[G2_INPUT_ITEM_LENGTH..], false)?;
let mut b = blst_p2::default();
unsafe { blst_p2_from_affine(&mut b, b_aff) };
let mut p = blst_p2::default();
unsafe { blst_p2_add_or_double_affine(&mut p, &b, a_aff) };
let mut p_aff = blst_p2_affine::default();
unsafe { blst_p2_to_affine(&mut p_aff, &p) };
let out = encode_g2_point(&p_aff);
Ok(PrecompileOutput::new(BASE_GAS_FEE, out))
}