code/pallets/drand/src/bls12_381.rs

bls12_381.rs

47 lines · 1,581 bytes · 19a6485969RawGitHub
/*
 * Copyright 2024 by Ideal Labs, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use ark_ec::pairing::Pairing;
use ark_std::{Zero, ops::Neg};
use sp_crypto_ec_utils::bls12_381::{
    Bls12_381 as Bls12_381Opt, G1Affine as G1AffineOpt, G2Affine as G2AffineOpt,
};

/// An optimized way to verify Drand pulses from quicket
/// Instead of computing two pairings and comparing them, we instead compute a multi miller loop,
/// and then take the final exponentiation, saving a lot of computational cost.
///
/// This function is also inlined as a way to optimize performance.
///
/// * `signature`:
/// * `q`:
/// * `msg_on_curve`: The message signed by Drand, hashed to G1
/// * `p_pub`: The beacon public key
#[inline]
pub fn fast_pairing_opt(
    signature: G1AffineOpt,
    q: G2AffineOpt,
    r: G1AffineOpt,
    s: G2AffineOpt,
) -> bool {
    let looped = Bls12_381Opt::multi_miller_loop([signature.neg(), r], [q, s]);
    let exp = Bls12_381Opt::final_exponentiation(looped);

    match exp {
        Some(e) => e.is_zero(),
        None => false,
    }
}