use super::utils::{pad_g2_point, remove_fp_padding};
use crate::{
bls12_381_const::{
MAP_FP2_TO_G2_ADDRESS, MAP_FP2_TO_G2_BASE_GAS_FEE, PADDED_FP2_LENGTH, PADDED_FP_LENGTH,
},
crypto, eth_precompile_fn, EthPrecompileOutput, EthPrecompileResult, Precompile,
PrecompileHalt, PrecompileId,
};
eth_precompile_fn!(map_fp2_to_g2_precompile, map_fp2_to_g2);
pub const PRECOMPILE: Precompile = Precompile::new(
PrecompileId::Bls12MapFp2ToGp2,
MAP_FP2_TO_G2_ADDRESS,
map_fp2_to_g2_precompile,
);
pub fn map_fp2_to_g2(input: &[u8], gas_limit: u64) -> EthPrecompileResult {
if MAP_FP2_TO_G2_BASE_GAS_FEE > gas_limit {
return Err(PrecompileHalt::OutOfGas);
}
if input.len() != PADDED_FP2_LENGTH {
return Err(PrecompileHalt::Bls12381MapFp2ToG2InputLength);
}
let input_p0_x = remove_fp_padding(&input[..PADDED_FP_LENGTH])?;
let input_p0_y = remove_fp_padding(&input[PADDED_FP_LENGTH..PADDED_FP2_LENGTH])?;
let unpadded_result = crypto().bls12_381_fp2_to_g2((*input_p0_x, *input_p0_y))?;
let padded_result = pad_g2_point(&unpadded_result);
Ok(EthPrecompileOutput::new(
MAP_FP2_TO_G2_BASE_GAS_FEE,
padded_result.into(),
))
}