Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host-optimized pairing cryptography with the Barreto-Naehrig curve #4852

Closed
wants to merge 7 commits into from

Conversation

mpapierski
Copy link
Collaborator

@mpapierski mpapierski commented Sep 9, 2024

This PR implements host-optimized pairing cryptography with the Barreto-Naehrig curve.

There are three new Wasm host functions:

  • casper_alt_bn128_add - Adds two points on the alt_bn128 elliptic curve.
  • casper_alt_bn128_mul - Multiply a point on the alt_bn128 elliptic curve by a scalar.
  • casper_alt_bn128_pairing - Performs a batched pairing check on the alt_bn128 elliptic curve.

Functionality

use casper_contract::{
    contract_api::{
        builtins::altbn128::{self, Error, Fq, Fr, Pair, G1},
        runtime,
    }
};

fn main() {
    // Addition
    let actual = altbn128::alt_bn128_add(
        &G1::from(ADD_X1_LE),
        &G1::from(ADD_Y1_LE),
        &G1::from(ADD_X2_LE),
        &G1::from(ADD_Y2_LE),
    );
    let expected = Ok((Fq::from(ADD_EXPECTED_X_LE), Fq::from(ADD_EXPECTED_Y_LE)));
    assert_eq!(actual, expected);
    // Multiply
    let x = G1::from(MUL_X_LE);
    let y = G1::from(MUL_Y_LE);
    let scalar = Fr::from(MUL_SCALAR_LE);

    assert_eq!(
        altbn128::alt_bn128_mul(&x, &y, &scalar),
        Ok((Fq::from(MUL_EXPECTED_X_LE), Fq::from(MUL_EXPECTED_Y_LE)))
    );
    // Pairing
    let all_pairs = [
        Pair {
            ax: Fq::from(PAIRING_AX_1_LE),
            ay: Fq::from(PAIRING_AY_1_LE),
            bax: Fq::from(PAIRING_BAX_1_LE),
            bay: Fq::from(PAIRING_BAY_1_LE),
            bbx: Fq::from(PAIRING_BBX_1_LE),
            bby: Fq::from(PAIRING_BBY_1_LE),
        },
        Pair {
            ax: Fq::from(PAIRING_AX_2_LE),
            ay: Fq::from(PAIRING_AY_2_LE),
            bax: Fq::from(PAIRING_BAX_2_LE),
            bay: Fq::from(PAIRING_BAY_2_LE),
            bbx: Fq::from(PAIRING_BBX_2_LE),
            bby: Fq::from(PAIRING_BBY_2_LE),
        },
    ];

    assert_eq!(altbn128::alt_bn128_pairing(&all_pairs), Ok(true));
}

Prior art

This work results from extensive internal research and is a foundation for implementing various zero-knowledge proof verifiers on Casper Network i.e. risc0, sp1, and others. This is compatible with alt_bn128 EVM precompiles (ecAdd, ecMul, ecPairing). The code is also inspired by other Rust implementations of EVM precompiles including aurora-engine and rust-ethereum.

Costs

Comparison of using a bn crate compiled to Wasm vs using the same functionality through host functions.

Function Wasm cost Host-side cost
alt_bn128_add 0.332511920 CSPR 0.009487020 CSPR
alt_bn128_mul 4.041409480 CSPR 0.009452310 CSPR
alt_bn128_pairing 324.598394790 CSPR 0.007415470 CSPR

Based on these results functions each alt_bn128_* will have a base cost of 1_000_000 motes, with the addition that alt_bn128_pairing function will have a dynamic cost depending on the amount of curves being paired.

Closes #4858

Copy link
Contributor

@asladeofgreen asladeofgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks nice.

  • We should add Prior Work acknowledgement either in the PR comment or the source code itself.
  • There ought to be WASM test cases that invoke these host functions ... and emit costs.

@mpapierski mpapierski marked this pull request as ready for review September 11, 2024 15:24
Copy link
Collaborator

@fizyk20 fizyk20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a small nitpick.

/// A point on the alt_bn128 curve.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[repr(C, packed)]
pub struct G1([u8; 32]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the types are pub, should we give them some more descriptive names? (Also applies to Fr and Fq below.)

Copy link

@jonas089 jonas089 Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is standard for Elliptic Curve notation, renaming them would confuse those who already have experience with this kind of math.

I think documentation would be more appropriate to make this accessible to everyone.

@mpapierski
Copy link
Collaborator Author

Closing for now

@mpapierski mpapierski closed this Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants