是否有可能从客户端破坏 Solana 智能合约?

问题描述 投票:0回答:2

我正在按照本教程在本地网络上创建智能合约。一切正常,但是当我修改客户端智能合约时,最终处于“损坏”状态。我无法理解发生了什么。这是合同:

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... =================================================== ================== 恢复中间帐户的临时密钥对文件

solana-keygen recover
以及以下 12 个单词的种子短语: =================================================== ==================准确体现演员侧舌荷兰铺作物对病能力案例 =================================================== ================== 要恢复部署,请将恢复的密钥对作为 [PROGRAM_ADDRESS_SIGNER] 参数为
solana deploy
或作为 [BUFFER_SIGNER] 至
solana program deploy
solana write-buffer'. Or to recover the account's lamports, pass it as the [BUFFER_ACCOUNT_ADDRESS] argument to 
solana 程序关闭`。 =================================================== ================== 错误:账户分配失败:RPC响应错误-32002: 交易模拟失败:该账户不能用于支付 交易费用部署时出现问题:输出{状态: ExitStatus(ExitStatus(256)),标准输出:“”,标准错误:“”}。

我非常感谢您的提示。发生了什么?我是否设法破坏了客户的合同?

anchor smartcontracts solana
2个回答
2
投票

这都是预期的行为。错误:

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
,这样它就有资金,然后根据需要将其用作签名者。


0
投票

我尝试过,但它对我不起作用。这是我得到的回应 “错误:空投请求失败。达到速率限制时可能会发生这种情况。”

© www.soinside.com 2019 - 2024. All rights reserved.