Skip to content

Commit dbf4c4e

Browse files
authored
Update EIP-3026 and EIP-2539 (#1173)
* Update eip-3026 gas meter * Add mappint operation * Remove TODOs * Fix compile
1 parent e7140a2 commit dbf4c4e

2 files changed

Lines changed: 132 additions & 21 deletions

File tree

frame/evm/precompile/bls12377/src/lib.rs

Lines changed: 116 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@
1818
#![cfg_attr(not(feature = "std"), no_std)]
1919

2020
// Arkworks
21-
use ark_bls12_377::{Bls12_377, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
22-
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
21+
use ark_bls12_377::{
22+
g1::Config as G1Config, g2::Config as G2Config, Bls12_377, Fq, Fq2, Fr, G1Affine, G1Projective,
23+
G2Affine, G2Projective,
24+
};
25+
use ark_ec::{
26+
hashing::{curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurve, HashToCurveError},
27+
pairing::Pairing,
28+
AffineRepr, CurveGroup, VariableBaseMSM,
29+
};
2330
use ark_ff::{BigInteger384, PrimeField, Zero};
24-
use ark_std::ops::Mul;
31+
use ark_std::{ops::Mul, vec::Vec};
2532

2633
// Frontier
2734
use fp_evm::{
@@ -124,6 +131,32 @@ fn extract_fq(bytes: [u8; 64]) -> Result<Fq, PrecompileFailure> {
124131
}
125132
}
126133

134+
fn read_fq(input: &[u8], offset: usize) -> Result<Fq, PrecompileFailure> {
135+
let mut buf = [0u8; 64];
136+
read_input(input, &mut buf, offset);
137+
extract_fq(buf)
138+
}
139+
140+
fn read_fq2(input: &[u8], offset: usize) -> Result<Fq2, PrecompileFailure> {
141+
let mut x_buf = [0u8; 64];
142+
let mut y_buf = [0u8; 64];
143+
read_input(input, &mut x_buf, offset);
144+
read_input(input, &mut y_buf, offset + 64);
145+
let px = extract_fq(x_buf)?;
146+
let py = extract_fq(y_buf)?;
147+
Ok(Fq2::new(px, py))
148+
}
149+
150+
fn map_to_curve_g1(fq: Fq) -> Result<G1Affine, HashToCurveError> {
151+
let m2c = WBMap::<G1Config>::new()?;
152+
m2c.map_to_curve(fq)
153+
}
154+
155+
fn map_to_curve_g2(fq2: Fq2) -> Result<G2Affine, HashToCurveError> {
156+
let m2c = WBMap::<G2Config>::new()?;
157+
m2c.map_to_curve(fq2)
158+
}
159+
127160
/// Decode G1 given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
128161
fn decode_g1(input: &[u8], offset: usize) -> Result<G1Projective, PrecompileFailure> {
129162
let mut px_buf = [0u8; 64];
@@ -483,8 +516,8 @@ pub struct Bls12377Pairing;
483516

484517
impl Bls12377Pairing {
485518
/// https://eips.ethereum.org/EIPS/eip-2539#pairing-operation
486-
const BASE_GAS: u64 = 65000;
487-
const PER_PAIR_GAS: u64 = 55000;
519+
const BASE_GAS: u64 = 65_000;
520+
const PER_PAIR_GAS: u64 = 55_000;
488521
}
489522

490523
impl Precompile for Bls12377Pairing {
@@ -548,5 +581,83 @@ impl Precompile for Bls12377Pairing {
548581
}
549582
}
550583

584+
/// Bls12377MapG1 implements EIP-2539 MapG1 precompile.
585+
pub struct Bls12377MapG1;
586+
587+
impl Bls12377MapG1 {
588+
const GAS_COST: u64 = 5_500;
589+
}
590+
591+
impl Precompile for Bls12377MapG1 {
592+
/// Implements EIP-2539 Map_To_G1 precompile.
593+
/// > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field.
594+
/// > Output of this call is `128` bytes and is G1 point following respective encoding rules.
595+
fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
596+
handle.record_cost(Bls12377MapG1::GAS_COST)?;
597+
598+
let input = handle.input();
599+
if input.len() != 64 {
600+
return Err(PrecompileFailure::Error {
601+
exit_status: ExitError::Other("invalid input length".into()),
602+
});
603+
}
604+
605+
let fq = read_fq(input, 0)?;
606+
let g1 = match map_to_curve_g1(fq) {
607+
Ok(point) => point,
608+
Err(_) => {
609+
return Err(PrecompileFailure::Error {
610+
exit_status: ExitError::Other("map to curve failed".into()),
611+
})
612+
}
613+
};
614+
615+
let output = encode_g1(g1);
616+
Ok(PrecompileOutput {
617+
exit_status: ExitSucceed::Returned,
618+
output: output.to_vec(),
619+
})
620+
}
621+
}
622+
623+
/// Bls12377MapG2 implements EIP-2539 MapG2 precompile.
624+
pub struct Bls12377MapG2;
625+
626+
impl Bls12377MapG2 {
627+
const GAS_COST: u64 = 75_000;
628+
}
629+
630+
impl Precompile for Bls12377MapG2 {
631+
/// Implements EIP-2539 Map_FP2_TO_G2 precompile logic.
632+
/// > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field.
633+
/// > Output of this call is `256` bytes and is G2 point following respective encoding rules.
634+
fn execute(handle: &mut impl PrecompileHandle) -> PrecompileResult {
635+
handle.record_cost(Bls12377MapG2::GAS_COST)?;
636+
637+
let input = handle.input();
638+
if input.len() != 64 {
639+
return Err(PrecompileFailure::Error {
640+
exit_status: ExitError::Other("invalid input length".into()),
641+
});
642+
}
643+
644+
let fq2 = read_fq2(input, 0)?;
645+
let g2 = match map_to_curve_g2(fq2) {
646+
Ok(point) => point,
647+
Err(_) => {
648+
return Err(PrecompileFailure::Error {
649+
exit_status: ExitError::Other("map to curve failed".into()),
650+
})
651+
}
652+
};
653+
654+
let output = encode_g2(g2);
655+
Ok(PrecompileOutput {
656+
exit_status: ExitSucceed::Returned,
657+
output: output.to_vec(),
658+
})
659+
}
660+
}
661+
551662
#[cfg(test)]
552663
mod tests;

frame/evm/precompile/bw6761/src/lib.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use ark_bw6_761::{Fq, Fr, G1Affine, G1Projective, G2Affine, G2Projective, BW6_761};
2222
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
2323
use ark_ff::{BigInteger768, PrimeField, Zero};
24-
use ark_std::ops::Mul;
24+
use ark_std::{ops::Mul, vec::Vec};
2525

2626
// Frontier
2727
use fp_evm::{
@@ -30,8 +30,15 @@ use fp_evm::{
3030
};
3131

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

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

180187
impl Bw6761G1Add {
181-
// TODO::to be estimated
182-
const GAS_COST: u64 = 0;
188+
const GAS_COST: u64 = 180;
183189
}
184190

185191
impl Precompile for Bw6761G1Add {
@@ -216,8 +222,7 @@ impl Precompile for Bw6761G1Add {
216222
pub struct Bw6761G1Mul;
217223

218224
impl Bw6761G1Mul {
219-
// TODO::to be estimated
220-
const GAS_COST: u64 = 0;
225+
const GAS_COST: u64 = 64_000;
221226
}
222227

223228
impl Precompile for Bw6761G1Mul {
@@ -254,7 +259,6 @@ impl Precompile for Bw6761G1Mul {
254259
pub struct Bw6761G1MultiExp;
255260

256261
impl Bw6761G1MultiExp {
257-
// TODO::to be estimated
258262
const MULTIPLIER: u64 = 1_000;
259263

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

328332
impl Bw6761G2Add {
329-
// TODO::to be estimated
330-
const GAS_COST: u64 = 0;
333+
const GAS_COST: u64 = 180;
331334
}
332335

333336
impl Precompile for Bw6761G2Add {
@@ -364,8 +367,7 @@ impl Precompile for Bw6761G2Add {
364367
pub struct Bw6761G2Mul;
365368

366369
impl Bw6761G2Mul {
367-
// TODO::to be estimated
368-
const GAS_COST: u64 = 0;
370+
const GAS_COST: u64 = 64_000;
369371
}
370372

371373
impl Precompile for Bw6761G2Mul {
@@ -402,7 +404,6 @@ impl Precompile for Bw6761G2Mul {
402404
pub struct Bw6761G2MultiExp;
403405

404406
impl Bw6761G2MultiExp {
405-
// TODO::to be estimated
406407
const MULTIPLIER: u64 = 1_000;
407408

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

476477
impl Bw6761Pairing {
477-
// TODO::to be estimated
478-
const BASE_GAS: u64 = 0;
479-
const PER_PAIR_GAS: u64 = 0;
478+
const BASE_GAS: u64 = 120_000;
479+
const PER_PAIR_GAS: u64 = 320_000;
480480
}
481481

482482
impl Precompile for Bw6761Pairing {

0 commit comments

Comments
 (0)