Solana Anchor Rust:如何将 public 密钥转换为 AccountInfo 类型
Solana Anchor Rust: How to convert a public key into an AccountInfo type
我知道我可以通过上下文结构为我的 Solana Rust 程序提供用户的令牌帐户,如 Anchor 教程 2 所示:https://project-serum.github.io/anchor/tutorials/tutorial-2.html#defining-a-program
#[derive(Accounts)]
pub struct Stake<'info> {
pub user_reward_token_account: CpiAccount<'info, TokenAccount>,
...
}
但是如果我希望用户先将该用户的令牌帐户保存在某个用户的存储帐户中,然后让我的 Solana 程序从该用户的存储帐户中获取这些令牌帐户怎么办?
let user_acct = &ctx.accounts.user_acct;
然后在尝试向用户的代币帐户铸造一些奖励代币时:
let cpi_accounts = MintTo {
mint: ctx.accounts.reward_mint.to_account_info(),
to: user_acct.reward_user,
authority: ctx.accounts.pg_signer.clone()
};
我在编译时遇到错误:需要结构 anchor_lang::prelude::AccountInfo
,找到结构 anchor_lang::prelude::Pubkey
但是 to_account_info() 方法在 anchor_lang::prelude::Pubkey
中找不到
我查看了 Pubkey 文档:https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.Pubkey.html
但它没有说明任何关于 AccountInfo 的信息...
然后我尝试在 https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.AccountInfo.html 的帮助下从 reward_user 地址创建一个 AccountInfo 结构:
let to_addr = AccountInfo {
key: &user_acct.reward_user,
is_signer: false,
is_writable: true,
lamports: Rc<RefCell<&'a mut u64>>,
data: Rc<RefCell<&'a mut [u8]>>,
owner: &user_pda.user_acct,
executable: false,
rent_epoch: u64,
};
但这真的很难,我不知道 lamports、数据、rent_epoch 值是什么...
那么如何将 public 密钥转换为 AccountInfo 类型?
您需要通过上下文传递帐户才能访问其数据。这种设计允许 Solana 通过在运行前知道需要哪些帐户和数据来更好地并行化事务。
因此,为了使 Sealevel 并行处理指令批次,您需要在程序使用的帐户列表中提供一个帐户,即使该帐户尚不存在。在创建帐户时,需要将一些 lamports 转移到该帐户才能免租。存放 lamports 需要修改此帐户的状态,因此需要将其标记为可写。
我遇到了与潜在但不太可能发生的并发问题有关的问题,其中 PDA 种子将包含不同帐户的状态,counter
之后 counter
会递增。这是 Solana 处理数组的方式,不受大小限制,可以索引或循环。我希望每次调用链上的 assemble 一个新帐户地址,而不是中继两个不读取 counter
状态的客户端,而是一个提交交易稍微慢一点并被拒绝的客户端。这是不可能的。
这实际上意味着客户端总是必须派生PDA并将其传递给程序,即使程序本身会再次执行相同的操作然后将交易提交给系统程序。
我知道我可以通过上下文结构为我的 Solana Rust 程序提供用户的令牌帐户,如 Anchor 教程 2 所示:https://project-serum.github.io/anchor/tutorials/tutorial-2.html#defining-a-program
#[derive(Accounts)]
pub struct Stake<'info> {
pub user_reward_token_account: CpiAccount<'info, TokenAccount>,
...
}
但是如果我希望用户先将该用户的令牌帐户保存在某个用户的存储帐户中,然后让我的 Solana 程序从该用户的存储帐户中获取这些令牌帐户怎么办?
let user_acct = &ctx.accounts.user_acct;
然后在尝试向用户的代币帐户铸造一些奖励代币时:
let cpi_accounts = MintTo {
mint: ctx.accounts.reward_mint.to_account_info(),
to: user_acct.reward_user,
authority: ctx.accounts.pg_signer.clone()
};
我在编译时遇到错误:需要结构 anchor_lang::prelude::AccountInfo
,找到结构 anchor_lang::prelude::Pubkey
但是 to_account_info() 方法在 anchor_lang::prelude::Pubkey
我查看了 Pubkey 文档:https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.Pubkey.html
但它没有说明任何关于 AccountInfo 的信息...
然后我尝试在 https://docs.rs/anchor-lang/0.13.2/anchor_lang/prelude/struct.AccountInfo.html 的帮助下从 reward_user 地址创建一个 AccountInfo 结构:
let to_addr = AccountInfo {
key: &user_acct.reward_user,
is_signer: false,
is_writable: true,
lamports: Rc<RefCell<&'a mut u64>>,
data: Rc<RefCell<&'a mut [u8]>>,
owner: &user_pda.user_acct,
executable: false,
rent_epoch: u64,
};
但这真的很难,我不知道 lamports、数据、rent_epoch 值是什么...
那么如何将 public 密钥转换为 AccountInfo 类型?
您需要通过上下文传递帐户才能访问其数据。这种设计允许 Solana 通过在运行前知道需要哪些帐户和数据来更好地并行化事务。
因此,为了使 Sealevel 并行处理指令批次,您需要在程序使用的帐户列表中提供一个帐户,即使该帐户尚不存在。在创建帐户时,需要将一些 lamports 转移到该帐户才能免租。存放 lamports 需要修改此帐户的状态,因此需要将其标记为可写。
我遇到了与潜在但不太可能发生的并发问题有关的问题,其中 PDA 种子将包含不同帐户的状态,counter
之后 counter
会递增。这是 Solana 处理数组的方式,不受大小限制,可以索引或循环。我希望每次调用链上的 assemble 一个新帐户地址,而不是中继两个不读取 counter
状态的客户端,而是一个提交交易稍微慢一点并被拒绝的客户端。这是不可能的。
这实际上意味着客户端总是必须派生PDA并将其传递给程序,即使程序本身会再次执行相同的操作然后将交易提交给系统程序。