Skip to content

Commit

Permalink
[tests] port test cases for EVM precompiles to Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
Vindaar committed Jun 14, 2024
1 parent 4685e71 commit 981c376
Showing 1 changed file with 253 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
//! Constantine
//! Copyright (c) 2018-2019 Status Research & Development GmbH
//! Copyright (c) 2020-Present Mamy André-Ratsimbazafy
//! Licensed and distributed under either of
//! * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
//! * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
//! at your option. This file may not be copied, modified, or distributed except according to those terms.

use constantine_sys::ctt_evm_status;
use constantine_ethereum_evm_precompiles::*;

use ::core::mem::MaybeUninit;
use std::fs;
use std::path::{PathBuf};

use glob::glob;
use hex;
use hex::FromHex;
use serde::{Deserialize, Deserializer};
use serde_json;

// Rust does not support concatenating
// compile-time &str ¯\_(ツ)_/¯, so we need to use macros, C-style.

macro_rules! test_dir {
() => {
"../../tests/protocol_ethereum_evm_precompiles/"
};
}

const MODEXP_TESTS: &str = concat!(test_dir!(), "modexp.json");
const MODEXP_EIP2565_TESTS: &str = concat!(test_dir!(), "modexp_eip2565.json");

const BN256ADD_TESTS: &str = concat!(test_dir!(), "bn256Add.json");
const BN256SCALARMUL_TESTS: &str = concat!(test_dir!(), "bn256ScalarMul.json");
const BN256PAIRING_TESTS: &str = concat!(test_dir!(), "bn256Pairing.json");

const ADD_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/add_G1_bls.json");
const FAIL_ADD_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-add_G1_bls.json");
const ADD_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/add_G2_bls.json");
const FAIL_ADD_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-add_G2_bls.json");

const MUL_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/mul_G1_bls.json");
const FAIL_MUL_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-mul_G1_bls.json");
const MUL_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/mul_G2_bls.json");
const FAIL_MUL_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-mul_G2_bls.json");

const MULTIEXP_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/multiexp_G1_bls.json");
const FAIL_MULTIEXP_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-multiexp_G1_bls.json");
const MULTIEXP_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/multiexp_G2_bls.json");
const FAIL_MULTIEXP_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-multiexp_G2_bls.json");

const PAIRING_CHECK_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/pairing_check_bls.json");
const FAIL_PAIRING_CHECK_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-pairing_check_bls.json");

const MAP_FP_TO_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/map_fp_to_G1_bls.json");
const FAIL_MAP_FP_TO_G1_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-map_fp_to_G1_bls.json");
const MAP_FP2_TO_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/map_fp2_to_G2_bls.json");
const FAIL_MAP_FP2_TO_G2_BLS_TESTS: &str = concat!(test_dir!(), "eip-2537/fail-map_fp2_to_G2_bls.json");


type HexString = String;

#[derive(Deserialize, Debug)]
struct PrecompileTest {
Input: HexString,
#[serde(default)]
Expected: HexString,
#[serde(default)]
ExpectedError: String,
Name: String,
#[serde(default)]
Gas: i64,
#[serde(default)]
NoBenchmark: bool,
}

type TestFunction = fn(&mut [u8], &[u8]) -> Result<bool, ctt_evm_status>;

fn from_hex(hex: HexString) -> Result<Vec<u8>, bool> {
// data does not always have `0x` prefix in JSON files!
// Check for the '0x' prefix
let href: &[u8] = hex.as_ref();
let href = if href.starts_with(b"0x") {
&href[2..]
} else {
href
};
// TODO: why cannot use `with_capacity`?
let mut result = vec![0u8; href.len() / 2];
match hex::decode_to_slice(href, result.as_mut_slice() as &mut [u8]) {
Ok(_) => Ok(result),
Err(_) => Err(false),
}
}


fn t_generate(test_name: String, func: TestFunction) {
type TestVectors = Vec<PrecompileTest>;

let unparsed = fs::read_to_string(&test_name).unwrap();
let vectors: TestVectors = serde_json::from_str(&unparsed).expect(&format!(
"Formatting should be consistent for file \"{}\"",
&test_name
));

for vector in vectors {
println!("Running test case: {}", vector.Name);

let input = vector.Input;
let expected = vector.Expected;

let input_bytes = from_hex(input)
.expect("Test failed; input bytes could not be unmarshaled.");
let expected_bytes = from_hex(expected)
.expect("Test failed; input bytes could not be unmarshaled.");
let mut r = vec![0u8; expected_bytes.len()];
// Call the test function
let status = func(&mut r, &input_bytes);
match status {
Ok(v) => assert!(v),
Err(e) => {
// reset!
r = vec![0u8; expected_bytes.len()];
}
}
assert!(r == expected_bytes);
}
}

#[test]
fn t_modexp() {
let test_name = MODEXP_TESTS.to_string();
t_generate(test_name, evm_modexp);
}

#[test]
fn t_modexp_eip2565_tests() {
let test_name = MODEXP_EIP2565_TESTS.to_string();
t_generate(test_name, evm_modexp);
}

#[test]
fn t_bn256add_tests() {
let test_name = BN256ADD_TESTS.to_string();
t_generate(test_name, evm_bn254_g1add);
}
#[test]
fn t_bn256scalarmul_tests() {
let test_name = BN256SCALARMUL_TESTS.to_string();
t_generate(test_name, evm_bn254_g1mul);
}

#[test]
fn t_bn256pairing_tests() {
let test_name = BN256PAIRING_TESTS.to_string();
t_generate(test_name, evm_bn254_ec_pairing_check);
}

#[test]
fn t_add_g1_bls_tests() {
let test_name = ADD_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1add);
}
#[test]
fn t_fail_add_g1_bls_TESTS() {
let test_name = FAIL_ADD_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1add);
}
#[test]
fn t_add_g2_bls_tests() {
let test_name = ADD_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2add);
}
#[test]
fn t_fail_add_g2_bls_TESTS() {
let test_name = FAIL_ADD_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2add);
}

#[test]
fn t_mul_g1_bls_tests() {
let test_name = MUL_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1mul);
}
#[test]
fn t_fail_mul_g1_bls_TESTS() {
let test_name = FAIL_MUL_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1mul);
}
#[test]
fn t_mul_g2_bls_tests() {
let test_name = MUL_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2mul);
}
#[test]
fn t_fail_mul_g2_bls_TESTS() {
let test_name = FAIL_MUL_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2mul);
}

#[test]
fn t_multiexp_g1_bls_tests() {
let test_name = MULTIEXP_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1msm);
}
#[test]
fn t_fail_multiexp_g1_bls_TESTS() {
let test_name = FAIL_MULTIEXP_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g1msm);
}
#[test]
fn t_multiexp_g2_bls_tests() {
let test_name = MULTIEXP_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2msm);
}
#[test]
fn t_fail_multiexp_g2_bls_TESTS() {
let test_name = FAIL_MULTIEXP_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_g2msm);
}

#[test]
fn t_pairing_check_bls_tests() {
let test_name = PAIRING_CHECK_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_pairing_check);
}
#[test]
fn t_fail_pairing_check_bls_TESTS() {
let test_name = FAIL_PAIRING_CHECK_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_pairing_check);
}

#[test]
fn t_map_fp_to_g1_BLS_TESTS() {
let test_name = MAP_FP_TO_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_map_fp_to_g1);
}
#[test]
fn t_fail_map_fp_to_G1_BLS_TESTS() {
let test_name = FAIL_MAP_FP_TO_G1_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_map_fp_to_g1);
}
#[test]
fn t_map_fp2_to_G2_BLS_TESTS() {
let test_name = MAP_FP2_TO_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_map_fp2_to_g2);
}
#[test]
fn t_fail_map_fp2_TO_G2_BLS_TESTS() {
let test_name = FAIL_MAP_FP2_TO_G2_BLS_TESTS.to_string();
t_generate(test_name, evm_bls12381_map_fp2_to_g2);
}

0 comments on commit 981c376

Please sign in to comment.