Seems there is no direct ecrecover
equivalent and that using the Ed25519 signature verification program is the best route. And it seems the way to use that program is to include it as an instruction in the transaction that calls your smart contract (instead of making a cross-program invocation to it, which you can't do as of the time of writing this). And you must design your smart contract in such a way that it assumes that an instruction before it would have been the Ed25519 sig verification instruction. Here's some code I made based off the only public library I could find that does this (it's Anchor based):
let ix = instructions_sysvar_module::load_instruction_at_checked(
EXPECTED_IX_SYSVAR_INDEX,
&ctx.accounts.instructions_sysvar,
)?;
if !validate_ed25519_ix(&ix) {
return err!(ErrorCode::InstructionMissing);
}
let pub_key = Pubkey::new(&ix.data[EXPECTED_PUBLIC_KEY_RANGE]);
let order = &ix.data[112..];
return Ok((pub_key, order.to_vec()));
based on: https://github.com/UnCaged-Studios/solana-program-library/blob/main/programs/kaching-cash-register/src/settle_order_payment.rs#L30
EXPECTED_IX_SYSVAR_INDEX
would be the expected index of the Ed25519 verification instruction in your transaction.
validate_ed25519_ix(&ix)
makes sure that the instruction is actually a Ed25519 sig verify instruction (checking the instruction's program ID among other things)
The instruction's data will include the public key used to sign, the message signed, and the actual signature.
The way I understand this approach is that the fact that your smart contract's instruction is reached means the Ed25519 sig verify instruction succeeded. If the sig verify instruction fails because of an invalid signature that causes an error to be thrown, then your smart contract wouldn't be reached since the entire transaction would fail.
I first gleaned this is the approach to take from a comment on github
Apparently this program doesn't work for CPI for GPU reasons: Program
failed to complete: Program
Ed25519SigVerify111111111111111111111111111 not supported by inner
instructions
solana-labs/solana#19843
Apparently the correct approach is to verify the signature in a
separate instruction, then walk through the instructions in your
program code using Sysvar1nstructions1111111111111111111111111 to
confirm the signature value.
source: https://github.com/solana-developers/solana-cookbook/issues/211
So overall what does this all mean? It means that when you are creating a transaction that you'll send to the Solana network, whether you generate that transaction using JavaScript, Rust, Go, or Python code, you must include a Ed25519 sig verification instruction in your transaction at the index your smart contract (or program as they're called in Solana) expects.