use anyhow::anyhow;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signature, Signer};
use std::str::FromStr;
pub struct VerifyMessageSignature<'a> {
pub signature: &'a str,
pub pubkey: &'a str,
pub message: &'a str,
}
impl<'a> VerifyMessageSignature<'a> {
pub fn verify_signature(verify: &Self) -> anyhow::Result<bool> {
let pubkey = Self::pubkey_from_string(verify.pubkey)?;
let signature = Self::signature_from_string(verify.signature)?;
Ok(signature.verify(pubkey.as_ref(), verify.message.as_bytes()))
}
pub fn signature_from_string(sig: &str) -> anyhow::Result<Signature> {
Ok(Signature::from_str(sig).map_err(|e| anyhow!("signature_from_string: {e}"))?)
}
pub fn pubkey_from_string(pubkey: &str) -> anyhow::Result<Pubkey> {
Ok(Pubkey::from_str(pubkey).map_err(|e| anyhow!("pubkey_from_string: {e}"))?)
}
}
pub struct SignMessage;
impl<'a> SignMessage {
pub fn sign_message(keypair: &'a Keypair, message: &str) -> anyhow::Result<String> {
let signature = keypair.sign_message(message.as_bytes());
Ok(signature.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
use solana_sdk::signature::{Keypair, Signer};
#[test]
fn verify_sig() {
let keypair = Keypair::new();
let message = "hello";
let signature = SignMessage::sign_message(&keypair, &message).unwrap();
let result = VerifyMessageSignature::verify_signature(&VerifyMessageSignature {
message,
pubkey: &keypair.pubkey().to_string(),
signature: &signature,
})
.unwrap();
assert!(result);
}
#[test]
fn fail_verify_sig() {
let keypair = Keypair::new();
let message = "hello";
let signature = SignMessage::sign_message(&keypair, &message).unwrap();
let keypair = Keypair::new();
let result = VerifyMessageSignature::verify_signature(&VerifyMessageSignature {
message,
pubkey: &keypair.pubkey().to_string(),
signature: &signature,
})
.unwrap();
assert!(!result);
}
}