aurora_engine_precompiles/bls12_381/
g1_add.rs

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