revm_precompile/bls12_381/
g2_mul.rs
1use super::{
2 g2::{encode_g2_point, extract_g2_input, G2_INPUT_ITEM_LENGTH},
3 utils::{extract_scalar_input, NBITS},
4};
5use crate::{u64_to_address, PrecompileWithAddress};
6use blst::{blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_mult, blst_p2_to_affine};
7use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult};
8
9pub const PRECOMPILE: PrecompileWithAddress =
11 PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g2_mul));
12pub const ADDRESS: u64 = 0x0f;
14pub(super) const BASE_GAS_FEE: u64 = 45000;
16
17pub(super) const INPUT_LENGTH: usize = 288;
19
20pub(super) fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult {
27 if BASE_GAS_FEE > gas_limit {
28 return Err(PrecompileError::OutOfGas.into());
29 }
30 if input.len() != INPUT_LENGTH {
31 return Err(PrecompileError::Other(format!(
32 "G2MUL input should be {INPUT_LENGTH} bytes, was {}",
33 input.len()
34 ))
35 .into());
36 }
37
38 let p0_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], true)?;
42 let mut p0 = blst_p2::default();
43 unsafe { blst_p2_from_affine(&mut p0, p0_aff) };
45
46 let input_scalar0 = extract_scalar_input(&input[G2_INPUT_ITEM_LENGTH..])?;
47
48 let mut p = blst_p2::default();
49 unsafe { blst_p2_mult(&mut p, &p0, input_scalar0.b.as_ptr(), NBITS) };
51 let mut p_aff = blst_p2_affine::default();
52 unsafe { blst_p2_to_affine(&mut p_aff, &p) };
54
55 let out = encode_g2_point(&p_aff);
56 Ok(PrecompileOutput::new(BASE_GAS_FEE, out))
57}