如何在Solana/Rust中检测函数调用者(类似Solidity的msg.sender)
在Solana/Rust中检测函数调用者并限制特定钱包访问
作为从以太坊转Solana的开发者,你需要先明确两者核心模型的差异:以太坊通过msg.sender直接标识调用者,而Solana的交易由签名者账户授权,程序需通过交易中的签名者列表识别发起者。
1. 实现类似Solidity msg.sender的调用者检测
在Solana Rust程序中,交易的签名者会被包含在accounts参数里,通常第一个签名者账户就是发起交易的用户钱包(对应以太坊的msg.sender)。具体实现代码如下:
use solana_program::{ account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, program_error::ProgramError, }; entrypoint!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], ) -> ProgramResult { // 取出账户列表中的第一个签名者账户 let caller_account = &accounts[0]; // 必须验证该账户是交易签名者,防止未授权调用 if !caller_account.is_signer { return Err(ProgramError::MissingRequiredSignature); } // 获取调用者公钥,对应Solidity的msg.sender let caller_pubkey = caller_account.key; // 后续业务逻辑... Ok(()) }
2. 限制仅特定钱包调用函数
拿到调用者公钥后,只需将其与预设的允许钱包地址对比,不匹配则返回错误即可:
// 替换为你允许的钱包公钥 const ALLOWED_WALLET: &str = "FjGQx6zZbX7E8Y9WqR3T4Y6U7I8O0P1A2S3D4F5G6H7J8K9L"; fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], ) -> ProgramResult { let caller_account = &accounts[0]; if !caller_account.is_signer { return Err(ProgramError::MissingRequiredSignature); } let caller_pubkey = caller_account.key; // 解析允许的钱包公钥 let allowed_pubkey = Pubkey::from_str(ALLOWED_WALLET)?; // 对比公钥,限制访问 if caller_pubkey != &allowed_pubkey { // 可使用标准错误或自定义错误返回 return Err(ProgramError::InvalidAccountData); } // 仅允许的钱包可执行的业务逻辑 Ok(()) }
关键注意事项
- 账户顺序很重要:如果程序需要多个签名者,要确保调用者账户在预期的列表位置;
- 必须验证
is_signer:即使账户在列表中,也需确认它签署了交易,避免未授权调用; - 自定义错误优化:可以定义专属的程序错误类型,替代标准错误,让调用者更清晰知晓失败原因。
内容的提问来源于stack exchange,提问作者Muhammad Abdullah
相关产品推荐
相关产品推荐

