From 8eaff99234aca42955345e2775ef11e24e2c0339 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 19 Jul 2024 08:49:29 -0400 Subject: [PATCH] feat: use batch bn256 pair operation (#1643) * feat: use batch bn256 pair operation We are currently not taking advantage of the batch pair operation from the `bn` library for the pairing check precompile. This yields a ~27% speedup on the existing bench: ``` Crypto Precompile benchmarks/precompile bench | ecpairing precompile time: [2.2389 ms 2.2441 ms 2.2495 ms] change: [-27.689% -27.469% -27.227%] (p = 0.00 < 0.05) Performance has improved. ``` * use with_capacity * import vec --- crates/precompile/src/bn128.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index c9ce059d73..193cb48af8 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -4,6 +4,7 @@ use crate::{ }; use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; use revm_primitives::PrecompileOutput; +use std::vec::Vec; pub mod add { use super::*; @@ -179,7 +180,9 @@ pub fn run_pair( } else { let elements = input.len() / PAIR_ELEMENT_LEN; - let mut mul = Gt::one(); + let mut points = Vec::with_capacity(elements); + + // read points for idx in 0..elements { let read_fq_at = |n: usize| { debug_assert!(n < PAIR_ELEMENT_LEN / 32); @@ -200,6 +203,7 @@ pub fn run_pair( let b = { let ba = Fq2::new(bax, bay); let bb = Fq2::new(bbx, bby); + // TODO: check whether or not we need these zero checks if ba.is_zero() && bb.is_zero() { G2::zero() } else { @@ -207,9 +211,11 @@ pub fn run_pair( } }; - mul = mul * bn::pairing(a, b); + points.push((a, b)); } + let mul = bn::pairing_batch(&points); + mul == Gt::one() }; Ok(PrecompileOutput::new(gas_used, bool_to_bytes32(success)))