You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solana数据账户无法读取更新值问题求助

问题:Solana计数器交易成功但账户状态未更新

本地部署的Solana问候计数器程序,调用increment_greeting交易后区块浏览器显示成功,但无法读取到数据账户更新后的计数器值,余额转账、账户创建等操作均正常。

Solana合约代码(Rust)

use anchor_lang::prelude::*;

declare_id!("8VEC1cycS5ry9aM5CBRWtxfVQBfNtWANTXXrXXmk2TXw");

#[program]
pub mod hello_please {
    use super::*;
    pub fn create_greeting(ctx: Context<CreateGreeting>) -> Result<()> {
        let greeting_account = &mut ctx.accounts.greeting_account;
        greeting_account.counter = 0;
        Ok(())
    }

    pub fn increment_greeting(ctx: Context<IncrementGreeting>) -> Result<()> {
        let greeting_account = &mut ctx.accounts.greeting_account;
        greeting_account.counter += 1;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct CreateGreeting<'info> {
    #[account(init, payer = user, space = 8 + 8)]
    pub greeting_account: Account<'info, GreetingAccount>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct IncrementGreeting<'info> {
    #[account(mut)]
    pub greeting_account: Account<'info, GreetingAccount>,
}

#[account]
pub struct GreetingAccount {
    pub counter: u64,
}

IDL(JSON)

{  "address": "8VEC1cycS5ry9aM5CBRWtxfVQBfNtWANTXXrXXmk2TXw",  "metadata": {    "name": "hello_please",    "version": "0.1.0",    "spec": "0.1.0",    "description": "Created with Anchor"  },  "instructions": [    {      "name": "create_greeting",      "discriminator": [        230,        141,        114,        135,        35,        122,        88,        117      ],      "accounts": [        {          "name": "greeting_account",          "writable": true,          "signer": true        },        {          "name": "user",          "writable": true,          "signer": true        },        {          "name": "system_program",          "address": "11111111111111111111111111111111"        }      ],      "args": []    },    {      "name": "increment_greeting",      "discriminator": [        58,        180,        32,        32,        96,        80,        100,        213      ],      "accounts": [        {          "name": "greeting_account",          "writable": true        }      ],      "args": []    }  ],  "accounts": [    {      "name": "GreetingAccount",      "discriminator": [        190,        16,        56,        57,        246,        26,        112,        24      ]    }  ],  "types": [    {      "name": "GreetingAccount",      "type": {        "kind": "struct",        "fields": [          {            "name": "counter",            "type": "u64"          }        ]      }    }  ]}

TypeScript调用代码

import * as anchor from "@coral-xyz/anchor";
import * as borsh from "@coral-xyz/borsh";
import { AnchorProvider, Program, Wallet, Idl, web3} from "@coral-xyz/anchor";
import idl from "./idl/hello_please.json";

async function main() {

    const connection =  new web3.Connection("http://127.0.0.1:8899");
    
    const providerAccount = web3.Keypair.generate();

    console.log(`providerAccount.publicKey: ${providerAccount.publicKey}`);

    console.log(`providerAccount.secretKey: ${providerAccount.secretKey}`);

    const airdrop_txn = await connection.requestAirdrop(providerAccount.publicKey, 10e9);
    const latestBlockHash_1 = await connection.getLatestBlockhash();
    await connection.confirmTransaction({
        blockhash: latestBlockHash_1.blockhash,
        lastValidBlockHeight: latestBlockHash_1.lastValidBlockHeight,
        signature: airdrop_txn,
    });
    console.log("Got Latest BlockHash");
    const provider_balance = await connection.getBalance(providerAccount.publicKey);
    console.log(`provider_account_balance: ${provider_balance}`);

    const wallet = new Wallet(providerAccount);
    
    const provider = new AnchorProvider(connection, wallet, {
    });
    anchor.setProvider(provider);
    console.log("provider set");

    const program = new Program(idl as Idl, provider);
    console.log("program created");

    const greetingAccount = anchor.web3.Keypair.generate();

    console.log(greetingAccount.publicKey);

    console.log(`greetingAccount created. \r greetingAccount.publicKey: ${greetingAccount.publicKey}`);

    console.log(`Sending Funds to greetingAccount`);
    const send_funds_transaction = new web3.Transaction().add(
        web3.SystemProgram.transfer({
          fromPubkey: providerAccount.publicKey,
          toPubkey: greetingAccount.publicKey,
          lamports: 2e9,
        }),
    );

    const send_funds_signature = await web3.sendAndConfirmTransaction(
        connection,
        send_funds_transaction,
        [providerAccount],
    );
    console.log('send_funds_signature', send_funds_signature);

    const greeting_balanace = await connection.getBalance(greetingAccount.publicKey);
    console.log(`Balance of Greeting Account: ${greeting_balanace}`);

    console.log("Before Sending Transaction: CreateGreeting");
    const createGreeting_tx = await program.methods
        .createGreeting()
        .accounts({
            greetingAccount: greetingAccount.publicKey,
        })
        .signers([greetingAccount])
        .rpc();

    console.log("Create Greeting Transaction signature:", createGreeting_tx+"\n");

    await printCounterValue(connection, greetingAccount, createGreeting_tx);

    console.log("Before Sending Transaction: IncrementGreeting");
    const incrementGreeting_tx = await program.methods
        .incrementGreeting()
        .accounts({
            greetingAccount: greetingAccount.publicKey,
        })
        .signers([providerAccount])
        .rpc();

    console.log("Increment Greeting Transaction signature:", incrementGreeting_tx+"\n");

    const isValid = await isValidSignature(connection, incrementGreeting_tx);

    console.log("Transaction Finalized: "+isValid);

    await printLatestBlockhash(connection, incrementGreeting_tx);

    console.log("Transaction Finalized: "+isValid);

    await printCounterValue(connection, greetingAccount, incrementGreeting_tx);

    console.log("Transaction Finalized: "+isValid);

}
main();

interface GreetingAccount {
    counter: anchor.BN
}

const isValidSignature = async (connection: anchor.web3.Connection, sig: string) => {
    const status = await connection.getSignatureStatus(sig, {
      searchTransactionHistory: true,
    });
    return (
      status.value?.err === null &&
      status.value?.confirmationStatus === "finalized"
    );
};

async function printCounterValue(connection: anchor.web3.Connection, greetingAccount: anchor.web3.Keypair, txSignature: string){

    const latestBlockHash = await connection.getLatestBlockhash();

    await connection.confirmTransaction({
        blockhash: latestBlockHash.blockhash,
        lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
        signature: txSignature,
      }, 'finalized');
    console.log("Got Latest BlockHash");
    console.log("Transaction finalized. Retrieving updated account state...");

    const accountInfo = await connection.getAccountInfo(greetingAccount.publicKey);
    if (accountInfo === null) {
        throw new Error("Error: Account not found");
    }
    console.log("account info retrieved");

    const GreetingAccountSchema = borsh.struct<GreetingAccount>([borsh.u64("counter"),]);
    console.log("GreetingAccount Schema constructed");

    const {counter} = GreetingAccountSchema.decode(accountInfo?.data, "processed");
    console.log("GreetingAccount Struct/Type constructed");

    console.log("decoded counter: "+counter.toNumber()+"\n");
}

async function printLatestBlockhash(connection: anchor.web3.Connection, txSignature: string){
    const latestBlockHash = await connection.getLatestBlockhash();

    await connection.confirmTransaction({
        blockhash: latestBlockHash.blockhash,
        lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
        signature: txSignature,
      }, 'finalized');
    console.log("Got Latest BlockHash");
}

执行结果

providerAccount.publicKey: 3bq44nBYNvJhcwU7XED6hwUFWGWdis3j2boXgtgmNMMc
providerAccount.secretKey: 117,199,146,222,123,138,144,19,26,63,129,43,202,20,26,58,240,92,210,168,65,43,214,187,6,193,156,166,24,57,33,68,38,163,116,115,157,110,105,109,102,165,156,10,252,121,205,229,42,62,247,58,83,157,174,42,88,218,94,30,51,226,173,35
Got Latest BlockHash
provider_account_balance: 10000000000
provider set
program created
PublicKey [PublicKey(8fTkRGZMxXeccGZpX4a9JgUqPWzU1Q6FRr69JCtLVTEF)] {
  _bn: <BN: 71dc1fbbdced2bd2ef5bbe8a86de890fc9c6e17ec9e9a5ea1ff7693df3fd8158>
}
 greetingAccount.publicKey: 8fTkRGZMxXeccGZpX4a9JgUqPWzU1Q6FRr69JCtLVTEF
Sending Funds to greetingAccount
send_funds_signature BeQFTFsf19QNUQjhDUhcnSqpkB9okuz6xFs3HpeUXGvwZ7MsvHRFEri61K4vK4ZE15RH16bGSuQXqLpCM6q97Fc
Balance of Greeting Account: 2000000000
Before Sending Transaction: CreateGreeting
Create Greeting Transaction signature: 3Cku7jdoZVLaWrmy6URz7GgepVvtAwq6HA5W4M9HDbUqfJcPhwsjS5uUVRhB7Z84b3iqnj6Jr1mdCqR52wrTZHxD

Got Latest BlockHash
Transaction finalized. Retrieving updated account state...
account info retrieved
GreetingAccount Schema constructed
GreetingAccount Struct/Type constructed
decoded counter: 0

Before Sending Transaction: IncrementGreeting
Increment Greeting Transaction signature: 4yUhDhcmKCQxCgrkE6CAc9T8vStG6iENUiv1ivAPTGcmoXFcPgsnzoZe2zoRAWeABkay7cTVwgww9DknXeMALKUV

Transaction Finalized: true
Got Latest BlockHash
Transaction Finalized: true
Got Latest BlockHash
Transaction finalized. Retrieving updated account state...
account info retrieved
GreetingAccount Schema constructed
GreetingAccount Struct/Type constructed
decoded counter: 0

Transaction Finalized: true

问题原因与修复方案

核心问题

Anchor创建的账户会在数据开头添加8字节的账户 discriminator,用于标识账户类型。你在TypeScript中直接用Borsh解码完整的账户数据,相当于把discriminator当成了计数器的一部分,导致解码结果错误。

修复方式1:手动跳过8字节 discriminator

修改printCounterValue函数中的解码逻辑,跳过前8字节:

async function printCounterValue(connection: anchor.web3.Connection, greetingAccount: anchor.web3.Keypair, txSignature: string){
    // ... 保留原有确认交易、获取账户信息的代码 ...
    // 跳过前8字节的Anchor账户discriminator
    const {counter} = GreetingAccountSchema.decode(accountInfo.data.slice(8), "processed");
    // ... 保留原有打印逻辑 ...
}

修复方式2:用Anchor Program直接读取账户(推荐)

利用Anchor IDL的类型支持,直接通过Program实例读取账户,无需手动处理Borsh解码:

// 替换原printCounterValue函数
async function printCounterValue(program: Program, greetingAccountPubkey: anchor.web3.PublicKey){
    const greetingAccount = await program.account.greetingAccount.fetch(greetingAccountPubkey);
    console.log("decoded counter: "+greetingAccount.counter.toNumber()+"\n");
}

// 在main函数中调用时,传入program和账户公钥
// 创建账户后调用:
await printCounterValue(program, greetingAccount.publicKey);
// 增量交易后调用:
await printCounterValue(program, greetingAccount.publicKey);

额外优化

IncrementGreeting交易中不需要传入providerAccount作为签名者,因为greeting_account仅需要可写权限,不需要签名(只有初始化账户时需要签名),可以去掉多余的signers参数:

const incrementGreeting_tx = await program.methods
    .incrementGreeting()
    .accounts({
        greetingAccount: greetingAccount.publicKey,
    })
    .rpc();

内容的提问来源于stack exchange,提问作者Md Tauhidul Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:57:31