revm_precompile/bls12_381/
pairing.rs1use super::utils::{remove_g1_padding, remove_g2_padding};
3use super::PairingPair;
4use crate::bls12_381_const::{
5 PADDED_G1_LENGTH, PADDED_G2_LENGTH, PAIRING_ADDRESS, PAIRING_INPUT_LENGTH,
6 PAIRING_MULTIPLIER_BASE, PAIRING_OFFSET_BASE,
7};
8use crate::{
9 crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult,
10};
11use primitives::B256;
12use std::vec::Vec;
13
14pub const PRECOMPILE: Precompile =
16 Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, pairing);
17
18pub fn pairing(input: &[u8], gas_limit: u64) -> PrecompileResult {
31 let input_len = input.len();
32 if input_len == 0 || !input_len.is_multiple_of(PAIRING_INPUT_LENGTH) {
33 return Err(PrecompileError::Bls12381PairingInputLength);
34 }
35
36 let k = input_len / PAIRING_INPUT_LENGTH;
37 let required_gas: u64 = PAIRING_MULTIPLIER_BASE * k as u64 + PAIRING_OFFSET_BASE;
38 if required_gas > gas_limit {
39 return Err(PrecompileError::OutOfGas);
40 }
41
42 let mut pairs: Vec<PairingPair> = Vec::with_capacity(k);
44 for i in 0..k {
45 let encoded_g1_element =
46 &input[i * PAIRING_INPUT_LENGTH..i * PAIRING_INPUT_LENGTH + PADDED_G1_LENGTH];
47 let encoded_g2_element = &input[i * PAIRING_INPUT_LENGTH + PADDED_G1_LENGTH
48 ..i * PAIRING_INPUT_LENGTH + PADDED_G1_LENGTH + PADDED_G2_LENGTH];
49
50 let [a_x, a_y] = remove_g1_padding(encoded_g1_element)?;
51 let [b_x_0, b_x_1, b_y_0, b_y_1] = remove_g2_padding(encoded_g2_element)?;
52
53 pairs.push(((*a_x, *a_y), (*b_x_0, *b_x_1, *b_y_0, *b_y_1)));
54 }
55
56 let result = crypto().bls12_381_pairing_check(&pairs)?;
57 let result = if result { 1 } else { 0 };
58
59 Ok(PrecompileOutput::new(
60 required_gas,
61 B256::with_last_byte(result).into(),
62 ))
63}