Solana 60 天课程

2025年02月27日更新 66 人订阅
原价: ¥ 28 限时优惠
专栏简介 开始 Solana - 安装与故障排除 Solana 和 Rust 中的算术与基本类型 Solana Anchor 程序 IDL Solana中的Require、Revert和自定义错误 Solana程序是可升级的,并且没有构造函数 Solidity开发者的Rust基础 Rust不寻常的语法 Rust 函数式过程宏 Rust 结构体与属性式和自定义派生宏 Rust 和 Solana 中的可见性与“继承” Solana时钟及其他“区块”变量 Solana 系统变量详解 Solana 日志、“事件”与交易历史 Tx.origin、msg.sender 和 onlyOwner 在 Solana 中:识别调用者 Solana 计算单元与交易费用介绍 在 Solana 和 Anchor 中初始化账户 Solana 计数器教程:在账户中读写数据 使用 Solana web3 js 和 Anchor 读取账户数据 在Solana中创建“映射”和“嵌套映射” Solana中的存储成本、最大存储容量和账户调整 在 Solana 中读取账户余额的 Anchor 方法:address(account).balance 功能修饰符(view、pure、payable)和回退函数在 Solana 中不存在的原因 在 Solana 上实现 SOL 转账及构建支付分配器 使用不同签名者修改账户 PDA(程序派生地址)与 Solana 中的密钥对账户 理解 Solana 中的账户所有权:从PDA中转移SOL Anchor 中的 Init if needed 与重初始化攻击 Solana 中的多重调用:批量交易与交易大小限制 Solana 中的所有者与权限 在Solana中删除和关闭账户与程序 在 Anchor 中:不同类型的账户 在链上读取另一个锚点程序账户数据 在 Anchor 中的跨程序调用(CPI)

Tx.origin、msg.sender 和 onlyOwner 在 Solana 中:识别调用者

  • RareSkills
  • 发布于 2024-02-23 20:22
  • 阅读 905

本文详细比较了Solidity和Solana智能合约中的msg.sendertx.origin概念,并提供了在Solana中如何实现类似功能的代码示例。文章还介绍了如何在Solana中处理多个签名者以及如何实现onlyOwner功能。

tx.origin msg.sender onlyOwner在Solana中

在Solidity中,msg.sender 是一个全局变量,表示调用或发起智能合约函数调用的地址。全局变量 tx.origin 是签署交易的钱包。

在Solana中,没有与 msg.sender 相当的概念。

tx.origin 有类似的概念,但你需要注意的是,Solana交易可以有多个签名者,因此我们可以将其视为具有“多个 tx.origins”。

要在Solana中获取 “tx.origin” 地址,你需要通过将签名者账户添加到函数上下文中并在调用函数时传递调用者的账户来进行设置。

让我们看看如何在Solana中访问交易签名者的地址的示例:

use anchor_lang::prelude::*;

declare_id!("Hf96fZsgq9R6Y1AHfyGbhi9EAmaQw2oks8NqakS6XVt1");

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

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let the_signer1: &mut Signer = &mut ctx.accounts.signer1;

        // 函数逻辑....

        msg!("签名者1: {:?}", *the_signer1.key);

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    pub signer1: Signer<'info>,
}

在上面的代码片段中,Signer<'info> 用于验证 Initialize<'info> 账户结构中的 signer1 账户已签署该交易。

initialize 函数中,signer1 账户从上下文中可变引用并被赋值给 the_signer1 变量。

然后最后,我们使用 msg! 宏记录 signer1 的公钥(地址),并传入 *the_signer1.key,这会解引用并访问通过 the_signer1 指向的实际值的 key 字段或方法。

接下来是为上述程序编写测试:

describe("Day14", () => {
  // 将客户端配置为使用本地集群。
  anchor.setProvider(anchor.AnchorProvider.env());

  const program = anchor.workspace.Day14 as Program<Day14>;

  it("由单个签名者签名", async () => {
    // 在这里添加你的测试。
    const tx = await program.methods.initialize().accounts({
      signer1: program.provider.publicKey
    }).rpc();

    console.log("签名者1: ", program.provider.publicKey.toBase58());
  });
});

在测试中,我们将我们的钱包账户作为签名者传递给 signer1 账户,然后调用初始化函数。之后,我们将钱包账户记录到控制台,以验证其与程序中的一致性。

练习: 你注意到了在运行测试后 shell_1(命令终端)和 shell_3(日志终端)中的输出有什么吗?

多个签名者

在Solana中,我们也可以有多个签名者签署一个交易,你可以把它看作是将一堆签名捆绑在一起并发送到一个交易中。一个用例是在一个交易中进行多签交易。

要做到这一点,我们只需在程序的账户结构中添加更多的 Signer 结构,然后确保在调用函数时传递必要的账户:

use anchor_lang::prelude::*;

declare_id!("Hf96fZsgq9R6Y1AHfyGbhi9EAmaQw2oks8NqakS6XVt1");

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

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let the_signer1: &mut Signer = &mut ctx.accounts.signer1;
        let the_signer2: &mut Signer = &mut ctx.accounts.signer2;

        msg!("签名者1: {:?}", *the_signer1.key);
        msg!("签名者2: {:?}", *the_signer2.key);

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    pub signer1: Signer<'info>,
    pub signer2: Signer<'info>,
}

上面的示例与单个签名者示例基本相同,有一个显著的区别。在这种情况下,我们向 Initialize 结构添加了另一个签名者账户(signer2),并在 initialize 函数中记录了两个签名者的公钥。

调用 initialize 函数与多个签名者是不同的,下面的测试显示如何调用多个签名者的函数:


describe("Day14", () => {
  // 将客户端配置为使用本地集群。
  anchor.setProvider(anchor.AnchorProvider.env());

  const program = anchor.workspace.Day14 as Program<Day14>;

  // 生成一个签名者来调用我们的函数
  let myKeypair = anchor.web3.Keypair.generate();

  it("由多个签名者签名", async () => {...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论