Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
feat: basic crypto benches
  • Loading branch information
Rjected committed Mar 19, 2024
commit 6a4989ccdbea736fb6e9ca812a194ad86597cf5e
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion crates/precompile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ k256 = { version = "0.13.3", default-features = false, features = ["ecdsa"] }
secp256k1 = { version = "0.28.2", default-features = false, features = [
"alloc",
"recovery",
"rand",
"std",
"global-context",
], optional = true }

criterion = "0.5"
rand = "0.8"

[features]
default = ["std", "c-kzg", "secp256k1", "portable"]
Expand Down Expand Up @@ -65,3 +69,8 @@ portable = ["revm-primitives/portable", "c-kzg?/portable"]
# The problem that `secp256k1` has is it fails to build for `wasm` target on Windows and Mac as it is c lib.
# In Linux it passes. If you don't require to build wasm on win/mac, it is safe to use it and it is enabled by default.
secp256k1 = ["dep:secp256k1"]

[[bench]]
name = "bench"
path = "benches/bench.rs"
harness = false
129 changes: 129 additions & 0 deletions crates/precompile/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use revm_precompile::{
bn128::{
pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT},
run_pair,
}, kzg_point_evaluation::run, secp256k1::ec_recover_run, Bytes
};
use revm_primitives::{hex, keccak256, Env, U256, VERSIONED_HASH_VERSION_KZG};
use secp256k1::{Message, SecretKey, SECP256K1};
use sha2::{Digest, Sha256};

/// Benchmarks different implementations of the root calculation.
pub fn trie_root_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("Precompile benchmarks");
let group_name = |description: &str| format!("precompile bench | {description}");

let input = hex::decode(
"\
1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\
3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\
209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\
04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\
2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\
120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\
111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\
2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\
198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\
1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\
090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\
12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
)
.unwrap();

// let expected =
// hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
// .unwrap();

let res = run_pair(
&input,
ISTANBUL_PAIR_PER_POINT,
ISTANBUL_PAIR_BASE,
u64::MAX,
)
.unwrap()
.0;

println!("gas used by regular pairing call: {:?}", res);

// generate secp256k1 signature
let data = hex::decode("1337133713371337").unwrap();
let hash = keccak256(data);
let secret_key = SecretKey::new(&mut rand::thread_rng());

let message = Message::from_digest_slice(&hash[..]).unwrap();
let s = SECP256K1.sign_ecdsa_recoverable(&message, &secret_key);
let (rec_id, data) = s.serialize_compact();
let mut rec_id = rec_id.to_i32() as u8;
assert_eq!(rec_id, 0);
rec_id += 27;

let mut message_and_signature = [0u8; 128];
message_and_signature[0..32].copy_from_slice(&hash[..]);

let rec_id = U256::from(rec_id as u64);
message_and_signature[32..64].copy_from_slice(&rec_id.to_be_bytes::<32>());
message_and_signature[64..128].copy_from_slice(&data);

// // `v` must be a 32-byte big-endian integer equal to 27 or 28.
// if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) {
// return Ok((ECRECOVER_BASE, Bytes::new()));
// }
// let msg = <&B256>::try_from(&input[0..32]).unwrap();
// let recid = input[63] - 27;
// let sig = <&B512>::try_from(&input[64..128]).unwrap();

let message_and_signature = Bytes::from(message_and_signature);
let gas = ec_recover_run(&message_and_signature, u64::MAX).unwrap();
println!("gas used by ecrecover precompile: {:?}", gas);

// now check kzg
let commitment = hex!("8f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7").to_vec();
let mut versioned_hash = Sha256::digest(&commitment).to_vec();
versioned_hash[0] = VERSIONED_HASH_VERSION_KZG;
let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000").to_vec();
let y = hex!("1522a4a7f34e1ea350ae07c29c96c7e79655aa926122e95fe69fcbd932ca49e9").to_vec();
let proof = hex!("a62ad71d14c5719385c0686f1871430475bf3a00f0aa3f7b8dd99a9abc2160744faf0070725e00b60ad9a026a15b1a8c").to_vec();

let kzg_input = [versioned_hash, z, y, commitment, proof].concat().into();

let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");
let gas = 50000;
let env = Env::default();
let (actual_gas, actual_output) = run(&kzg_input, gas, &env).unwrap();
println!("gas used by kzg precompile: {:?}", actual_gas);

group.bench_function(group_name("ecrecover precompile"), |b| {
b.iter(|| {
ec_recover_run(&message_and_signature, u64::MAX).unwrap();
black_box(())
})
});

group.bench_function(group_name("ecpairing precompile"), |b| {
b.iter(|| {
run_pair(
&input,
ISTANBUL_PAIR_PER_POINT,
ISTANBUL_PAIR_BASE,
u64::MAX,
)
.unwrap();
black_box(())
})
});

group.bench_function(group_name("kzg precompile"), |b| {
b.iter(|| {
run(&kzg_input, gas, &env).unwrap();
black_box(())
})
});
}

criterion_group! {
name = benches;
config = Criterion::default();
targets = trie_root_benchmark
}
criterion_main!(benches);
49 changes: 46 additions & 3 deletions crates/precompile/src/bn128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ pub mod pair {

const ADDRESS: Address = crate::u64_to_address(8);

const ISTANBUL_PAIR_PER_POINT: u64 = 34_000;
const ISTANBUL_PAIR_BASE: u64 = 45_000;
pub const ISTANBUL_PAIR_PER_POINT: u64 = 34_000;
pub const ISTANBUL_PAIR_BASE: u64 = 45_000;
pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress(
ADDRESS,
Precompile::Standard(|input, gas_limit| {
Expand Down Expand Up @@ -170,7 +170,7 @@ fn run_mul(input: &[u8]) -> Result<Bytes, Error> {
Ok(out.into())
}

fn run_pair(
pub fn run_pair(
input: &[u8],
pair_per_point_cost: u64,
pair_base_cost: u64,
Expand Down Expand Up @@ -226,6 +226,49 @@ fn run_pair(
Ok((gas_used, bool_to_bytes32(success)))
}

#[cfg(test)]
mod tests {
use tests::pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT};

use super::*;
use crate::primitives::hex;

#[test]
fn test_alt_bn128_pair() {
let input = hex::decode(
"\
1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\
3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\
209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\
04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\
2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\
120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\
111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\
2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\
198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\
1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\
090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\
12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
)
.unwrap();

// let expected =
// hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
// .unwrap();

let res = run_pair(
&input,
ISTANBUL_PAIR_PER_POINT,
ISTANBUL_PAIR_BASE,
u64::MAX,
)
.unwrap()
.0;

println!("gas used: {:?}", res);
}
}

/*
#[cfg(test)]
mod tests {
Expand Down
2 changes: 1 addition & 1 deletion crates/precompile/src/kzg_point_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const RETURN_VALUE: &[u8; 64] = &hex!(
/// | versioned_hash | z | y | commitment | proof |
/// | 32 | 32 | 32 | 48 | 48 |
/// with z and y being padded 32 byte big endian values
fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult {
pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult {
if gas_limit < GAS_COST {
return Err(Error::OutOfGas);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/precompile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
extern crate alloc as std;

mod blake2;
mod bn128;
pub mod bn128;
mod hash;
mod identity;
#[cfg(feature = "c-kzg")]
Expand Down
2 changes: 1 addition & 1 deletion crates/precompile/src/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ mod secp256k1 {
}
}

fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult {
pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult {
const ECRECOVER_BASE: u64 = 3_000;

if ECRECOVER_BASE > gas_limit {
Expand Down