aurora_engine_precompiles/bls12_381/
pairing_check.rs1use crate::prelude::{Borrowed, Vec};
2use crate::{utils, EvmPrecompileResult, Precompile, PrecompileOutput};
3use aurora_engine_sdk::bls12_381::{self, PAIRING_INPUT_LENGTH};
4use aurora_engine_types::types::{make_address, Address, EthGas};
5use aurora_evm::{Context, ExitError};
6
7const PAIRING_MULTIPLIER_BASE: u64 = 32600;
9const PAIRING_OFFSET_BASE: u64 = 37700;
11
12pub struct BlsPairingCheck;
14
15impl BlsPairingCheck {
16 pub const ADDRESS: Address = make_address(0, 0xF);
17
18 fn execute(input: &[u8]) -> Result<Vec<u8>, ExitError> {
19 bls12_381::pairing_check(input).map_err(|e| ExitError::Other(Borrowed(e.as_ref())))
20 }
21}
22
23impl Precompile for BlsPairingCheck {
24 fn required_gas(input: &[u8]) -> Result<EthGas, ExitError>
25 where
26 Self: Sized,
27 {
28 let k = u64::try_from(input.len() / PAIRING_INPUT_LENGTH).map_err(utils::err_usize_conv)?;
29 Ok(EthGas::new(
30 PAIRING_MULTIPLIER_BASE * k + PAIRING_OFFSET_BASE,
31 ))
32 }
33
34 fn run(
47 &self,
48 input: &[u8],
49 target_gas: Option<EthGas>,
50 _context: &Context,
51 _is_static: bool,
52 ) -> EvmPrecompileResult {
53 let input_len = input.len();
54 if input_len == 0 || input_len % PAIRING_INPUT_LENGTH != 0 {
55 return Err(ExitError::Other(Borrowed("ERR_BLS_PAIRING_INVALID_LENGTH")));
56 }
57
58 let cost = Self::required_gas(input)?;
59 if let Some(target_gas) = target_gas {
60 if cost > target_gas {
61 return Err(ExitError::OutOfGas);
62 }
63 }
64
65 let output = Self::execute(input)?;
66 Ok(PrecompileOutput::without_logs(cost, output))
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use aurora_engine_types::H160;
74
75 #[test]
76 fn bls12_381_pairing() {
77 let precompile = BlsPairingCheck;
78 let ctx = Context {
79 address: H160::zero(),
80 caller: H160::zero(),
81 apparent_value: 0.into(),
82 };
83 let input = hex::decode("\
84 000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80\
85 000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d5\
86 00000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e\
87 000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834\
88 000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e\
89 0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e\
90 000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80\
91 00000000000000000000000000000000118cd94e36ab177de95f52f180fdbdc584b8d30436eb882980306fa0625f07a1f7ad3b4c38a921c53d14aa9a6ba5b8d6\
92 00000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e\
93 000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834\
94 000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e\
95 0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e")
96 .expect("hex decoding failed");
97
98 let res = precompile
99 .run(&input, None, &ctx, false)
100 .expect("precompile run should not fail");
101 let expected =
102 hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
103 .expect("hex decoding failed");
104
105 assert_eq!(res.output, expected);
106 }
107}