revm_precompile/bls12_381/
map_fp_to_g1.rs1use super::utils::{pad_g1_point, remove_fp_padding};
3use crate::{
4 bls12_381_const::{MAP_FP_TO_G1_ADDRESS, MAP_FP_TO_G1_BASE_GAS_FEE, PADDED_FP_LENGTH},
5 crypto, eth_precompile_fn, EthPrecompileOutput, EthPrecompileResult, Precompile,
6 PrecompileHalt, PrecompileId,
7};
8
9eth_precompile_fn!(map_fp_to_g1_precompile, map_fp_to_g1);
10
11pub const PRECOMPILE: Precompile = Precompile::new(
13 PrecompileId::Bls12MapFpToGp1,
14 MAP_FP_TO_G1_ADDRESS,
15 map_fp_to_g1_precompile,
16);
17
18pub fn map_fp_to_g1(input: &[u8], gas_limit: u64) -> EthPrecompileResult {
22 if MAP_FP_TO_G1_BASE_GAS_FEE > gas_limit {
23 return Err(PrecompileHalt::OutOfGas);
24 }
25
26 if input.len() != PADDED_FP_LENGTH {
27 return Err(PrecompileHalt::Bls12381MapFpToG1InputLength);
28 }
29
30 let input_p0 = remove_fp_padding(input)?;
31
32 let unpadded_result = crypto().bls12_381_fp_to_g1(input_p0)?;
33
34 let padded_result = pad_g1_point(&unpadded_result);
36
37 Ok(EthPrecompileOutput::new(
38 MAP_FP_TO_G1_BASE_GAS_FEE,
39 padded_result.into(),
40 ))
41}
42
43#[cfg(test)]
44mod test {
45 use super::*;
46 use primitives::{hex, Bytes};
47
48 #[test]
49 fn sanity_test() {
50 let input = Bytes::from(hex!("000000000000000000000000000000006900000000000000636f6e7472616374595a603f343061cd305a03f40239f5ffff31818185c136bc2595f2aa18e08f17"));
51 let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE_GAS_FEE);
52 assert_eq!(fail, Err(PrecompileHalt::NonCanonicalFp));
53 }
54}