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