aurora_engine_precompiles/bls12_381/
g1_add.rs

1use crate::prelude::types::{make_address, Address, EthGas};
2use crate::prelude::Borrowed;
3use crate::{EvmPrecompileResult, Precompile, PrecompileOutput, Vec};
4use aurora_engine_sdk::bls12_381;
5use aurora_evm::{Context, ExitError};
6
7/// Base gas fee for BLS12-381 `g1_add` operation.
8const BASE_GAS_FEE: u64 = 375;
9
10/// Input length of `g1_add` operation.
11const INPUT_LENGTH: usize = 256;
12
13/// BLS12-381 G1 Add
14pub struct BlsG1Add;
15
16impl BlsG1Add {
17    pub const ADDRESS: Address = make_address(0, 0xB);
18
19    fn execute(input: &[u8]) -> Result<Vec<u8>, ExitError> {
20        bls12_381::g1_add(input).map_err(|e| ExitError::Other(Borrowed(e.as_ref())))
21    }
22}
23
24impl Precompile for BlsG1Add {
25    fn required_gas(_input: &[u8]) -> Result<EthGas, ExitError>
26    where
27        Self: Sized,
28    {
29        Ok(EthGas::new(BASE_GAS_FEE))
30    }
31
32    /// G1 addition call expects `256` bytes as an input that is interpreted as byte
33    /// concatenation of two G1 points (`128` bytes each).
34    /// Output is an encoding of addition operation result - single G1 point (`128`
35    /// bytes).
36    /// See also: <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition>
37    fn run(
38        &self,
39        input: &[u8],
40        target_gas: Option<EthGas>,
41        _context: &Context,
42        _is_static: bool,
43    ) -> EvmPrecompileResult {
44        if input.len() != INPUT_LENGTH {
45            return Err(ExitError::Other(Borrowed("ERR_BLS_G1ADD_INPUT_LEN")));
46        }
47
48        let cost = Self::required_gas(input)?;
49        if let Some(target_gas) = target_gas {
50            if cost > target_gas {
51                return Err(ExitError::OutOfGas);
52            }
53        }
54
55        let output = Self::execute(input)?;
56        Ok(PrecompileOutput::without_logs(cost, output))
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use aurora_engine_types::H160;
64
65    #[test]
66    fn bls12_381_g1_add() {
67        let precompile = BlsG1Add;
68        let ctx = Context {
69            address: H160::zero(),
70            caller: H160::zero(),
71            apparent_value: 0.into(),
72        };
73        let input = hex::decode("\
74               00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb\
75			   0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed2\
76			   000000000000000000000000000000000441e7f7f96198e4c23bd5eb16f1a7f045dbc8c53219ab2bcea91d3a027e2dfe659feac64905f8b9add7e4bfc91bec2b\
77			   0000000000000000000000000000000005fc51bb1b40c87cd4292d4b66f8ca5ce4ef9abd2b69d4464b4879064203bda7c9fc3f896a3844ebc713f7bb20951d95")
78            .expect("hex decoding failed");
79
80        let res = precompile
81            .run(&input, None, &ctx, false)
82            .expect("precompile run should not fail");
83        let expected = hex::decode("\
84                0000000000000000000000000000000016b8ab56b45a9294466809b8e858c1ad15ad0d52cfcb62f8f5753dc94cee1de6efaaebce10701e3ec2ecaa9551024ea\
85                600000000000000000000000000000000124571eec37c0b1361023188d66ec17c1ec230d31b515e0e81e599ec19e40c8a7c8cdea9735bc3d8b4e37ca7e5dd71f6")
86            .expect("hex decoding failed");
87
88        assert_eq!(res.output, expected);
89    }
90}