revm_precompile/secp256k1/
k256.rs

1//! k256 implementation of `ecrecover`. More about it in [`crate::secp256k1`].
2use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey};
3use primitives::{alloy_primitives::B512, keccak256, B256};
4
5/// Recover the public key from a signature and a message.
6///
7/// This function is using the `k256` crate.
8pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result<B256, Error> {
9    // parse signature
10    let mut sig = Signature::from_slice(sig.as_slice())?;
11
12    // normalize signature and flip recovery id if needed.
13    if let Some(sig_normalized) = sig.normalize_s() {
14        sig = sig_normalized;
15        recid ^= 1;
16    }
17    let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid");
18
19    // recover key
20    let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?;
21    // hash it
22    let mut hash = keccak256(
23        &recovered_key
24            .to_encoded_point(/* compress = */ false)
25            .as_bytes()[1..],
26    );
27
28    // truncate to 20 bytes
29    hash[..12].fill(0);
30    Ok(hash)
31}