revm_precompile/
secp256k1.rs1#[cfg(feature = "secp256k1")]
2pub mod bitcoin_secp256k1;
3pub mod k256;
4#[cfg(feature = "libsecp256k1")]
5pub mod parity_libsecp256k1;
6
7use crate::{
8 utilities::right_pad, PrecompileError, PrecompileOutput, PrecompileResult,
9 PrecompileWithAddress,
10};
11use primitives::{alloy_primitives::B512, Bytes, B256};
12
13pub const ECRECOVER: PrecompileWithAddress =
14 PrecompileWithAddress(crate::u64_to_address(1), ec_recover_run);
15
16pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult {
17 const ECRECOVER_BASE: u64 = 3_000;
18
19 if ECRECOVER_BASE > gas_limit {
20 return Err(PrecompileError::OutOfGas);
21 }
22
23 let input = right_pad::<128>(input);
24
25 if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) {
27 return Ok(PrecompileOutput::new(ECRECOVER_BASE, Bytes::new()));
28 }
29
30 let msg = <&B256>::try_from(&input[0..32]).unwrap();
31 let recid = input[63] - 27;
32 let sig = <&B512>::try_from(&input[64..128]).unwrap();
33
34 let res = ecrecover(sig, recid, msg);
35
36 let out = res.map(|o| o.to_vec().into()).unwrap_or_default();
37 Ok(PrecompileOutput::new(ECRECOVER_BASE, out))
38}
39
40cfg_if::cfg_if! {
41 if #[cfg(feature = "secp256k1")] {
42 pub use bitcoin_secp256k1::ecrecover;
43 } else if #[cfg(feature = "libsecp256k1")] {
44 pub use parity_libsecp256k1::ecrecover;
45 } else {
46 pub use k256::ecrecover;
47 }
48}