ecrecover/
ecrecover.rs

1use clap::Parser;
2use eyre::Result;
3use k256::ecdsa::{SigningKey, VerifyingKey};
4use openvm_benchmarks_prove::util::BenchmarkCli;
5use openvm_sdk::config::{SdkVmBuilder, SdkVmConfig};
6use openvm_stark_backend::p3_field::FieldAlgebra;
7use openvm_stark_sdk::{bench::run_with_metric_collection, p3_baby_bear::BabyBear};
8use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
9use tiny_keccak::{Hasher, Keccak};
10
11fn make_input(signing_key: &SigningKey, msg: &[u8]) -> Vec<BabyBear> {
12    let mut hasher = Keccak::v256();
13    hasher.update(msg);
14    let mut prehash = [0u8; 32];
15    hasher.finalize(&mut prehash);
16    let (signature, recid) = signing_key.sign_prehash_recoverable(&prehash).unwrap();
17    // Input format: https://www.evm.codes/precompiled?fork=cancun#0x01
18    let mut input = prehash.to_vec();
19    let v = recid.to_byte() + 27u8;
20    input.extend_from_slice(&[0; 31]);
21    input.push(v);
22    input.extend_from_slice(signature.to_bytes().as_ref());
23
24    input.into_iter().map(BabyBear::from_canonical_u8).collect()
25}
26
27fn main() -> Result<()> {
28    let args = BenchmarkCli::parse();
29
30    let config =
31        SdkVmConfig::from_toml(include_str!("../../../guest/ecrecover/openvm.toml"))?.app_vm_config;
32    let elf = args.build_bench_program("ecrecover", &config, None)?;
33
34    run_with_metric_collection("OUTPUT_PATH", || -> Result<()> {
35        let mut rng = ChaCha8Rng::seed_from_u64(12345);
36        let signing_key: SigningKey = SigningKey::random(&mut rng);
37        let verifying_key = VerifyingKey::from(&signing_key);
38        let mut hasher = Keccak::v256();
39        let mut expected_address = [0u8; 32];
40        hasher.update(
41            &verifying_key
42                .to_encoded_point(/* compress = */ false)
43                .as_bytes()[1..],
44        );
45        hasher.finalize(&mut expected_address);
46        expected_address[..12].fill(0); // 20 bytes as the address.
47        let mut input_stream = vec![expected_address
48            .into_iter()
49            .map(BabyBear::from_canonical_u8)
50            .collect::<Vec<_>>()];
51
52        let msg = ["Elliptic", "Curve", "Digital", "Signature", "Algorithm"];
53        input_stream.extend(
54            msg.iter()
55                .map(|s| make_input(&signing_key, s.as_bytes()))
56                .collect::<Vec<_>>(),
57        );
58        args.bench_from_exe::<SdkVmBuilder, _>(
59            "ecrecover_program",
60            config,
61            elf,
62            input_stream.into(),
63        )
64    })
65}