eth-valkyoth-verify 0.21.0

no_std Ethereum verification boundaries.
Documentation
use eth_valkyoth_hash::TinyKeccak256;
use eth_valkyoth_primitives::B256;

use crate::{
    ETHEREUM_PUBLIC_KEY_BYTES, EthereumSignature, RecoverableSecp256k1, SIGNING_DIGEST_BYTES,
    VerifyError,
};

pub(crate) type RealKeccak = TinyKeccak256;

pub(crate) struct TestSecp256k1Backend;

impl RecoverableSecp256k1 for TestSecp256k1Backend {
    fn recover_uncompressed_public_key(
        &mut self,
        signing_digest: B256,
        signature: EthereumSignature,
    ) -> Result<[u8; ETHEREUM_PUBLIC_KEY_BYTES], VerifyError> {
        let secp256k1_signature =
            k256::ecdsa::Signature::from_scalars(signature.r(), signature.s())
                .map_err(|_| VerifyError::InvalidSignature)?;
        if secp256k1_signature.normalize_s().is_some() {
            return Err(VerifyError::InvalidSignature);
        }
        let recovery_id = k256::ecdsa::RecoveryId::try_from(signature.y_parity().get())
            .map_err(|_| VerifyError::InvalidSignature)?;
        let digest_bytes = <[u8; SIGNING_DIGEST_BYTES]>::from(signing_digest);
        let verifying_key = k256::ecdsa::VerifyingKey::recover_from_prehash(
            &digest_bytes,
            &secp256k1_signature,
            recovery_id,
        )
        .map_err(|_| VerifyError::InvalidSignature)?;
        let encoded = verifying_key.to_encoded_point(false);
        encoded
            .as_bytes()
            .get(1..)
            .and_then(|value| <[u8; ETHEREUM_PUBLIC_KEY_BYTES]>::try_from(value).ok())
            .ok_or(VerifyError::InvalidSignature)
    }
}