0

I’m working on an anchor-lang project to validate secp256k1 ethereum signature. I used secp256k1_recover program docs as a reference for this code. The problem is that the public key I get from the recovery does not match the one that signed the signature. Is there a mistake in my code or did I misinterpret how the recovery operates? I appreciate your help!

use solana_program::secp256k1_recover::{secp256k1_recover};

declare_id!("3PxEqHbGAWZthkyuJvtTjjwYSQ3HRGJVyk8MbjnZP2mt");

#[program]
pub mod solana_treasury {
    use super::*;

    pub fn recover(ctx: Context<New>) -> Result<()> {
        let eth_pubkey = "026f0a0eac8db33cebd88516ccbfafc148cd97abfe217e456c4f47f0478b1b443d";

        // ethers.solidityPackedKeccak256(['string'],["some_message"])
        let message = "69ee7a3423fa9be01fa80a47dffc9c3135fdccaab0ca5d5c4fbc3459b66c271e";

        // Buffer.concat([sig.r, sig.s]).toString('hex'))
        let signature = "5bf05d6ede6316f675a3d0ad0896db0473aaa6084a1c373046fc5ea2a285edd81b0dfc8c5bb6bb0affff58fbc4c16f73b757414b0af05ab4bc139864903bb81b";
        
        // sig.v - 27
        let recovery_id = 0;

        let recovered_pubkey = secp256k1_recover(
            &message.as_bytes(),
            recovery_id,
            &signature.as_bytes(),
        )
        .map_err(|_| ProgramError::InvalidArgument)?;

        // 58a8a3bd63db626497e1b4c09fb3119257c2bd0c651084eac0c038ad49bec874e380efbb5f8232aceae2383b9a1bbc22e936121ebaf83ff880801232327380e3
        let recovered_pubkey_hex = hex::encode(recovered_pubkey.0);

        msg!("Generated Recovered PubKey: {}", recovered_pubkey_hex);

        if eth_pubkey == recovered_pubkey_hex {
            msg!("Public Key Match!");
        } else {
            msg!("Public Key Doesn't Match!");
        }
        // value from recovered_pubkey_hex:
        // 58a8a3bd63db626497e1b4c09fb3119257c2bd0c651084eac0c038ad49bec874e380efbb5f8232aceae2383b9a1bbc22e936121ebaf83ff880801232327380e3

        // eth_pubkey should equals to recovered_pubkey_hex ?

        Ok(())
    }
}

#[derive(Accounts)]
pub struct New {}

1 Answer 1

1

The instruction expects it'll receive raw bytes, and not a hex string, so you'll also need to decode the hex strings as bytes:

        let recovered_pubkey = secp256k1_recover(
            &hex::decode(&message).unwrap(),
            recovery_id,
            &hex::decode(&signature).unwrap(),
        )
        .map_err(|_| ProgramError::InvalidArgument)?;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.