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

Update EIP-3026 and EIP-2539 #1173

Merged
merged 4 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 116 additions & 5 deletions frame/evm/precompile/bls12377/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@
#![cfg_attr(not(feature = "std"), no_std)]

// Arkworks
use ark_bls12_377::{Bls12_377, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
use ark_bls12_377::{
g1::Config as G1Config, g2::Config as G2Config, Bls12_377, Fq, Fq2, Fr, G1Affine, G1Projective,
G2Affine, G2Projective,
};
use ark_ec::{
hashing::{curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurve, HashToCurveError},
pairing::Pairing,
AffineRepr, CurveGroup, VariableBaseMSM,
};
use ark_ff::{BigInteger384, PrimeField, Zero};
use ark_std::ops::Mul;
use ark_std::{ops::Mul, vec::Vec};

// Frontier
use fp_evm::{
Expand Down Expand Up @@ -124,6 +131,32 @@ fn extract_fq(bytes: [u8; 64]) -> Result<Fq, PrecompileFailure> {
}
}

fn read_fq(input: &[u8], offset: usize) -> Result<Fq, PrecompileFailure> {
let mut buf = [0u8; 64];
read_input(input, &mut buf, offset);
extract_fq(buf)
}

fn read_fq2(input: &[u8], offset: usize) -> Result<Fq2, PrecompileFailure> {
let mut x_buf = [0u8; 64];
let mut y_buf = [0u8; 64];
read_input(input, &mut x_buf, offset);
read_input(input, &mut y_buf, offset + 64);
let px = extract_fq(x_buf)?;
let py = extract_fq(y_buf)?;
Ok(Fq2::new(px, py))
}

fn map_to_curve_g1(fq: Fq) -> Result<G1Affine, HashToCurveError> {
let m2c = WBMap::<G1Config>::new()?;
m2c.map_to_curve(fq)
}

fn map_to_curve_g2(fq2: Fq2) -> Result<G2Affine, HashToCurveError> {
let m2c = WBMap::<G2Config>::new()?;
m2c.map_to_curve(fq2)
}

/// Decode G1 given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
fn decode_g1(input: &[u8], offset: usize) -> Result<G1Projective, PrecompileFailure> {
let mut px_buf = [0u8; 64];
Expand Down Expand Up @@ -483,8 +516,8 @@ pub struct Bls12377Pairing;

impl Bls12377Pairing {
/// https://eips.ethereum.org/EIPS/eip-2539#pairing-operation
const BASE_GAS: u64 = 65000;
const PER_PAIR_GAS: u64 = 55000;
const BASE_GAS: u64 = 65_000;
const PER_PAIR_GAS: u64 = 55_000;
}

impl Precompile for Bls12377Pairing {
Expand Down Expand Up @@ -548,5 +581,83 @@ impl Precompile for Bls12377Pairing {
}
}

/// Bls12377MapG1 implements EIP-2539 MapG1 precompile.
pub struct Bls12377MapG1;

impl Bls12377MapG1 {
const GAS_COST: u64 = 5_500;
}

impl Precompile for Bls12377MapG1 {
/// Implements EIP-2539 Map_To_G1 precompile.
/// > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field.
/// > Output of this call is `128` bytes and is G1 point following respective encoding rules.
fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
handle.record_cost(Bls12377MapG1::GAS_COST)?;

let input = handle.input();
if input.len() != 64 {
return Err(PrecompileFailure::Error {
exit_status: ExitError::Other("invalid input length".into()),
});
}

let fq = read_fq(input, 0)?;
let g1 = match map_to_curve_g1(fq) {
Ok(point) => point,
Err(_) => {
return Err(PrecompileFailure::Error {
exit_status: ExitError::Other("map to curve failed".into()),
})
}
};

let output = encode_g1(g1);
Ok(PrecompileOutput {
exit_status: ExitSucceed::Returned,
output: output.to_vec(),
})
}
}

/// Bls12377MapG2 implements EIP-2539 MapG2 precompile.
pub struct Bls12377MapG2;

impl Bls12377MapG2 {
const GAS_COST: u64 = 75_000;
}

impl Precompile for Bls12377MapG2 {
/// Implements EIP-2539 Map_FP2_TO_G2 precompile logic.
/// > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field.
/// > Output of this call is `256` bytes and is G2 point following respective encoding rules.
fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
handle.record_cost(Bls12377MapG2::GAS_COST)?;

let input = handle.input();
if input.len() != 64 {
return Err(PrecompileFailure::Error {
exit_status: ExitError::Other("invalid input length".into()),
});
}

let fq2 = read_fq2(input, 0)?;
let g2 = match map_to_curve_g2(fq2) {
Ok(point) => point,
Err(_) => {
return Err(PrecompileFailure::Error {
exit_status: ExitError::Other("map to curve failed".into()),
})
}
};

let output = encode_g2(g2);
Ok(PrecompileOutput {
exit_status: ExitSucceed::Returned,
output: output.to_vec(),
})
}
}

#[cfg(test)]
mod tests;
32 changes: 16 additions & 16 deletions frame/evm/precompile/bw6761/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use ark_bw6_761::{Fq, Fr, G1Affine, G1Projective, G2Affine, G2Projective, BW6_761};
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
use ark_ff::{BigInteger768, PrimeField, Zero};
use ark_std::ops::Mul;
use ark_std::{ops::Mul, vec::Vec};

// Frontier
use fp_evm::{
Expand All @@ -30,8 +30,15 @@ use fp_evm::{
};

/// Gas discount table for BW6-761 G1 and G2 multi exponentiation operations.
// TODO::to be estimated
const BW6761_MULTIEXP_DISCOUNT_TABLE: [u16; 128] = [0u16; 128];
const BW6761_MULTIEXP_DISCOUNT_TABLE: [u16; 128] = [
1266, 733, 561, 474, 422, 387, 362, 344, 329, 318, 308, 300, 296, 289, 283, 279, 275, 272, 269,
266, 265, 260, 259, 256, 255, 254, 252, 251, 250, 249, 249, 220, 228, 225, 223, 219, 216, 214,
212, 209, 209, 205, 203, 202, 200, 198, 196, 199, 195, 192, 192, 191, 190, 187, 186, 185, 184,
184, 181, 181, 181, 180, 178, 179, 176, 177, 176, 175, 174, 173, 171, 171, 170, 170, 169, 168,
168, 167, 167, 166, 165, 167, 166, 166, 165, 165, 164, 164, 163, 163, 162, 162, 160, 163, 159,
162, 159, 160, 159, 159, 158, 158, 158, 158, 157, 157, 156, 155, 155, 156, 155, 155, 154, 155,
154, 153, 153, 153, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150,
];

/// Encode Fq as `96` bytes by performing Big-Endian encoding of the corresponding (unsigned) integer.
fn encode_fq(field: Fq) -> [u8; 96] {
Expand Down Expand Up @@ -178,8 +185,7 @@ fn decode_g2(input: &[u8], offset: usize) -> Result<G2Projective, PrecompileFail
pub struct Bw6761G1Add;

impl Bw6761G1Add {
// TODO::to be estimated
const GAS_COST: u64 = 0;
const GAS_COST: u64 = 180;
}

impl Precompile for Bw6761G1Add {
Expand Down Expand Up @@ -216,8 +222,7 @@ impl Precompile for Bw6761G1Add {
pub struct Bw6761G1Mul;

impl Bw6761G1Mul {
// TODO::to be estimated
const GAS_COST: u64 = 0;
const GAS_COST: u64 = 64_000;
}

impl Precompile for Bw6761G1Mul {
Expand Down Expand Up @@ -254,7 +259,6 @@ impl Precompile for Bw6761G1Mul {
pub struct Bw6761G1MultiExp;

impl Bw6761G1MultiExp {
// TODO::to be estimated
const MULTIPLIER: u64 = 1_000;

/// Returns the gas required to execute the pre-compiled contract.
Expand Down Expand Up @@ -326,8 +330,7 @@ impl Precompile for Bw6761G1MultiExp {
pub struct Bw6761G2Add;

impl Bw6761G2Add {
// TODO::to be estimated
const GAS_COST: u64 = 0;
const GAS_COST: u64 = 180;
}

impl Precompile for Bw6761G2Add {
Expand Down Expand Up @@ -364,8 +367,7 @@ impl Precompile for Bw6761G2Add {
pub struct Bw6761G2Mul;

impl Bw6761G2Mul {
// TODO::to be estimated
const GAS_COST: u64 = 0;
const GAS_COST: u64 = 64_000;
hujw77 marked this conversation as resolved.
Show resolved Hide resolved
}

impl Precompile for Bw6761G2Mul {
Expand Down Expand Up @@ -402,7 +404,6 @@ impl Precompile for Bw6761G2Mul {
pub struct Bw6761G2MultiExp;

impl Bw6761G2MultiExp {
// TODO::to be estimated
const MULTIPLIER: u64 = 1_000;

/// Returns the gas required to execute the pre-compiled contract.
Expand Down Expand Up @@ -474,9 +475,8 @@ impl Precompile for Bw6761G2MultiExp {
pub struct Bw6761Pairing;

impl Bw6761Pairing {
// TODO::to be estimated
const BASE_GAS: u64 = 0;
const PER_PAIR_GAS: u64 = 0;
const BASE_GAS: u64 = 120_000;
const PER_PAIR_GAS: u64 = 320_000;
}

impl Precompile for Bw6761Pairing {
Expand Down
Loading