我正在按照本教程在本地网络上创建智能合约。一切正常,但是当我修改客户端智能合约时,最终处于“损坏”状态。我无法理解发生了什么。这是合同:
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
mod mysolanaapp {
use super::*;
pub fn create(ctx: Context<Create>) -> ProgramResult {
let base_account = &mut ctx.accounts.base_account;
base_account.count = 0;
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> ProgramResult {
let base_account = &mut ctx.accounts.base_account;
base_account.count += 1;
Ok(())
}
}
// Transaction instructions
#[derive(Accounts)]
pub struct Create<'info> {
#[account(init, payer = user, space = 16 + 16)]
pub base_account: Account<'info, BaseAccount>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program <'info, System>,
}
// Transaction instructions
#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut)]
pub base_account: Account<'info, BaseAccount>,
}
// An account that goes inside a transaction instruction
#[account]
pub struct BaseAccount {
pub count: u64,
}
工作的客户端代码是:
const anchor = require('@project-serum/anchor');
const { SystemProgram } = anchor.web3;
(async () => {
const provider = anchor.Provider.local();
anchor.setProvider(provider);
// The Account to create.
const myAccount = anchor.web3.Keypair.generate();
// Read the generated IDL.
const idl = JSON.parse(require('fs').readFileSync('./hello.json', 'utf8'));
// Address of the deployed program.
const programId = new anchor.web3.PublicKey('GrfgF4vWfVEDsLKHxiB5Q6yfYhziubLY9M8VVxyTEc6o');
// Generate the program client from IDL.
const program = new anchor.Program(idl, programId);
// Execute the RPC.
await program.rpc.create({
accounts: {
baseAccount: myAccount.publicKey,
user: provider.wallet.publicKey,
systemProgram: SystemProgram.programId,
},
signers: [myAccount],
});
/* Fetch the account and check the value of count */
let account = await program.account.baseAccount.fetch(myAccount.publicKey);
console.log('Count 0: ', account.count.toString())
await program.rpc.increment({
accounts: {
baseAccount: myAccount.publicKey,
},
});
account = await program.account.baseAccount.fetch(myAccount.publicKey);
console.log('Count 1: ', account.count.toString())
})();
但是此代码每次调用时都会生成新帐户。由于我想保持数据持久性,我尝试通过加载我用来部署合约的本地密钥对来替换帐户生成:
const secKey = JSON.parse(require('fs').readFileSync('/home/username/.config/solana/id.json', 'utf8'));
const arr = Uint8Array.from(secKey)
const myAccount = anchor.web3.Keypair.fromSecretKey(arr);
但是这会导致错误:
SendTransactionError: 发送交易失败: 交易模拟失败: 该账户不能用于支付交易费用
对我来说更奇怪的是,恢复更改没有帮助,而且客户端总是失败。令我惊讶的是,甚至不再可能再次部署合约,因为锚返回以下错误:
升级权限:/home/username/.config/solana/id.json 部署中 程序“mysolanaapp”...程序路径: /home/用户名/workspace/solana/mysolanaapp/target/deploy/mysolanaapp.so... =================================================== ================== 恢复中间帐户的临时密钥对文件
以及以下 12 个单词的种子短语: =================================================== ==================准确体现演员侧舌荷兰铺作物对病能力案例 =================================================== ================== 要恢复部署,请将恢复的密钥对作为 [PROGRAM_ADDRESS_SIGNER] 参数为
solana-keygen recover
或作为 [BUFFER_SIGNER] 至solana deploy
或solana program deploy
solana 程序关闭`。 =================================================== ================== 错误:账户分配失败:RPC响应错误-32002: 交易模拟失败:该账户不能用于支付 交易费用部署时出现问题:输出{状态: ExitStatus(ExitStatus(256)),标准输出:“”,标准错误:“”}。
solana write-buffer'. Or to recover the account's lamports, pass it as the [BUFFER_ACCOUNT_ADDRESS] argument to
我非常感谢您的提示。发生了什么?我是否设法破坏了客户的合同?
这都是预期的行为。错误:
SendTransactionError: 发送交易失败: 交易模拟失败: 该账户不能用于支付交易费用
提供所有最重要的信息。在 Solana 中,当您向网络发送交易时,系统程序拥有的某个帐户 (https://docs.solana.com/developing/runtime-facilities/programs#system-program) 必须对交易进行签名,以便扣除费用。当您使用程序在
create
上运行 myAccount
指令时,该帐户将被分配给您的程序,因此它不再属于系统程序所拥有,从而无法签署交易。有关帐户模型的更多信息,特别是有关所有权的信息,请访问 https://docs.solana.com/developing/programming-model/accounts#ownership-and-assignment-to-programs
综上所述,要解决您的问题,您需要使用不同的帐户签署交易。您可以先使用
solana-keygen new -o new_account.json
,然后使用 solana airdrop .1 new_account.json
,这样它就有资金,然后根据需要将其用作签名者。
我尝试过,但它对我不起作用。这是我得到的回应 “错误:空投请求失败。达到速率限制时可能会发生这种情况。”