首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在模块链中借用ctx

如何在模块链中借用ctx
EN

Stack Overflow用户
提问于 2022-04-22 05:58:03
回答 1查看 64关注 0票数 0

我有一个入口点,其中ctx由父级传递:

代码语言:javascript
复制
pub mod instructions;

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

    pub fn flip(ctx: Context<Play>, data: FlipArgs) -> Result<()> {
        instructions::play::play(ctx, data)
    }
}

然后,instructions/play.rs有以下内容:

代码语言:javascript
复制
pub fn play(ctx: Context<Play>, data: FlipArgs) -> Result<()> {
    ctx.accounts.game.flip(ctx, data) // <== cannot move out of `ctx` because it is borrowed
}

#[derive(Accounts)]
pub struct Play<'info> {
    #[account(mut)]
    pub game: Account<'info, Game>,
    pub player: Signer<'info>,
}

ctx最终被传递给game.rs

代码语言:javascript
复制
impl Game {
    pub fn flip(&mut self, ctx: Context<Play>, data: FlipArgs) -> Result<()> {
        self.charge_fee(ctx);

        match data.heads_or_tails {
            true => self.play_heads(ctx), // <== use of moved value: `ctx`
            false => self.play_tails(ctx),
        }
    }

    fn charge_fee(&self, ctx: Context<Play>) -> Result<()> {
        let player = &ctx.accounts.player;

        // ...

        Ok(())
    }
}

如何从ctx中正确借用lib.rs > play.rs > game.rs

EN

回答 1

Stack Overflow用户

发布于 2022-04-22 08:13:56

正如在评论中所说的,你不是在借用ctx,你只是在移动它。请参阅相关文件以了解差异,并与示例一起说明这一点。

如果你仔细阅读,你就会明白为什么你只需要改变你的函数的签名:

代码语言:javascript
复制
// in instructions/play.rs
pub fn play(ctx: &Context<Play>, data: FlipArgs) -> Result<()> { // <-- takes a `&Context<Play>`
  ctx.accounts.game.flip(ctx, data) // and passes the borrow
}

// game.rs
impl Game {
  pub fn flip(&mut self, ctx: &Context<Play>, data: FlipArgs) -> Result<()> { // <-- takes a &Context<Play>
    self.charge_fee(ctx); // <-- here you pass the borrow
                          // also, unused `Result`, which is _bad_
    if data.heads_or_tails { // an `if` statement is a `match` over a `bool`
      self.play_heads(ctx) // <-- here you pass the borrow too, which is fine, because `&T: Copy`
    } else {
      self.play_tails(ctx) // <-- same as above
    }
  }
  fn charge_fee(&self, ctx: &Context<Play>) -> Result<()> { // <-- takes a `&Context<Play>`
    let player = &ctx.accounts.player;
    // ...
    Ok(())
  }
}

但是,尽管有此修补程序,出于多种动机,您还是需要在理解了“借”之后重构代码:

  1. 考虑到问题的上下文,不可能知道play是向Context<Play>借款,还是向拥有的值借款,因为两者都可以工作(在第二种情况下,您必须将借款传递给方法调用,即ctx.accounts.game.flip(&ctx, data) )。
  2. 您似乎一直将data作为一个拥有的值传递,就像您对ctx所做的一样,但是由于这是ctx的一个错误,它可能也适用于data (以及您的代码的许多其他部分)。
  3. 我不确定当前版本是否会编译需要flip&mut self,也就是说,它需要在play函数中向ctx.accounts.game进行可变的借用。但是,这也需要ctx的可变借用(除非是它不会,但这有点太高级了:在调用期间先了解借款,再学习内部可变性),这将使任何要作为参数传递的借款无效。

作为建议,我建议您在设计复杂应用程序的体系结构之前,先了解Rust的核心概念(通过阅读锈书可以有效地完成),因为Rust有一些非常特殊的模式,即使使用其他编程语言也是如此。否则,当您仍然不完全理解Rust中的借用和所有权时,您将继续与编译器斗争,试图修改您所想到的代码,以适应一些有用的东西。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71964033

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档