[英]Init Token Account error - "Error processing Instruction 0: custom program error: 0x0"
[英]My transaction fails when trying to Init VRF on Devnet using Anchor (0x0 Error)
我正在嘗試為 Solana 使用 VRF 來生成隨機數,我正在使用 CPI 來執行此操作。 在 Localhost 上運行測試時,它可以正常工作並生成數字。
但是,當我切換到 Devnet 時,它會因錯誤而失敗:
交易模擬失敗自定義錯誤 0x0
我正在使用 Orao-VRF: Github
我的 lib.rs 代碼:
use anchor_lang::prelude::*;
use orao_solana_vrf::network_state_account_address;
use orao_solana_vrf::program::OraoVrf;
use orao_solana_vrf::randomness_account_address;
use orao_solana_vrf::state::NetworkState;
use orao_solana_vrf::CONFIG_ACCOUNT_SEED;
use orao_solana_vrf::RANDOMNESS_ACCOUNT_SEED;
use std::mem::size_of;
declare_id!("6ag7tVY7RizWm4xZr7Vv3N4yGio5mqS6H9VFAUFvuMQt");
#[program]
pub mod cflip {
use orao_solana_vrf::cpi::accounts::Request;
use super::*;
pub fn spin_and_pull_the_trigger(
ctx: Context<SpinAndPullTheTrigger>,
force: [u8; 32],
) -> Result<()> {
// Zero seed is illegal in VRF
if force == [0_u8; 32] {
return Err(Error::YouMustSpinTheCylinder.into());
}
// Request randomness.
let cpi_program = ctx.accounts.vrf.to_account_info();
let cpi_accounts = Request {
payer: ctx.accounts.player.to_account_info(),
network_state: ctx.accounts.config.to_account_info(),
treasury: ctx.accounts.treasury.to_account_info(),
request: ctx.accounts.random.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
};
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
orao_solana_vrf::cpi::request(cpi_ctx, force)?;
fn get_random(randomness: &[u8; 64]) -> u8 {
// use only first 8 bytes for simplicyty
let value = &randomness[0..size_of::<u64>()];
return value[0];
}
Ok(())
}
}
#[derive(Accounts)]
#[instruction(force: [u8; 32])]
pub struct SpinAndPullTheTrigger<'info> {
#[account(mut)]
player: Signer<'info>,
/// CHECK:
#[account(
mut,
seeds = [RANDOMNESS_ACCOUNT_SEED.as_ref(), &force],
bump,
seeds::program = orao_solana_vrf::ID
)]
random: AccountInfo<'info>,
/// CHECK:
#[account(mut)]
treasury: AccountInfo<'info>,
#[account(
mut,
seeds = [CONFIG_ACCOUNT_SEED.as_ref()],
bump,
seeds::program = orao_solana_vrf::ID
)]
config: Account<'info, NetworkState>,
vrf: Program<'info, OraoVrf>,
system_program: Program<'info, System>,
}
#[error_code]
pub enum Error {
#[msg("The player is already dead")]
PlayerDead,
#[msg("Unable to serialize a randomness request")]
RandomnessRequestSerializationError,
#[msg("Player must spin the cylinder")]
YouMustSpinTheCylinder,
#[msg("The cylinder is still spinning")]
TheCylinderIsStillSpinning,
}
/// Helper that builds the instruction.
#[cfg(feature = "sdk")]
pub fn spin_and_pull_the_trigger<'a>(
cflip: &'a anchor_client::Program,
vrf: &anchor_client::Program,
) -> std::result::Result<anchor_client::RequestBuilder<'a>, anchor_client::ClientError> {
let seed = rand::random();
// vrf accounts
let network_state_address = network_state_account_address();
let request_address = randomness_account_address(&seed);
let vrf_config = vrf.account::<NetworkState>(network_state_address)?.config;
Ok(cflip
.request()
.accounts(crate::accounts::SpinAndPullTheTrigger {
player: cflip.payer(),
treasury: vrf_config.treasury,
random: request_address,
config: network_state_address,
vrf: orao_solana_vrf::id(),
system_program: anchor_client::solana_sdk::system_program::ID,
})
.args(crate::instruction::SpinAndPullTheTrigger { force: seed }))
}
我的 test.ts 代碼:
import assert from "assert";
import * as anchor from "@project-serum/anchor";
import { Program, BN, Spl } from "@project-serum/anchor";
import {
Keypair,
PublicKey,
SystemProgram,
LAMPORTS_PER_SOL,
SYSVAR_RENT_PUBKEY,
SYSVAR_INSTRUCTIONS_PUBKEY,
Ed25519Program,
} from "@solana/web3.js";
import { Orao, networkStateAccountAddress, randomnessAccountAddress } from "../js/dist";
import { Cflip } from "../target/types/cflip";
import nacl from "tweetnacl";
describe("cflip", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.Cflip as Program<Cflip>;
const vrf = new Orao(provider);
// This accounts are for test VRF.
const treasury = Keypair.generate();
const fulfillmentAuthority = Keypair.generate();
// Initial force for russian-roulette
let force = Keypair.generate().publicKey;
// This helper will play a single round of russian-roulette.
async function spinAndPullTheTrigger(force: Buffer) {
const random = randomnessAccountAddress(force);
await program.methods
.spinAndPullTheTrigger([...force])
.accounts({
player: provider.wallet.publicKey,
vrf: vrf.programId,
config: networkStateAccountAddress(),
treasury: treasury.publicKey,
random,
systemProgram: SystemProgram.programId,
})
.rpc();
}
// This helper will fulfill randomness for our test VRF.
async function emulateFulfill(seed: Buffer) {
let signature = nacl.sign.detached(seed, fulfillmentAuthority.secretKey);
await vrf.methods
.fulfill()
.accounts({
instructionAcc: SYSVAR_INSTRUCTIONS_PUBKEY,
networkState: networkStateAccountAddress(),
request: randomnessAccountAddress(seed),
})
.preInstructions([
Ed25519Program.createInstructionWithPublicKey({
publicKey: fulfillmentAuthority.publicKey.toBytes(),
message: seed,
signature,
}),
])
.rpc();
}
before(async () => {
await provider.connection.confirmTransaction(
await provider.connection.requestAirdrop(treasury.publicKey, 1 * LAMPORTS_PER_SOL),
"confirmed"
);
// Initialize test VRF
const fee = 1 * LAMPORTS_PER_SOL;
const fullfillmentAuthorities = [
fulfillmentAuthority.publicKey,
];
const configAuthority = Keypair.generate();
await vrf.methods
.initNetwork(
new BN(fee),
configAuthority.publicKey,
fullfillmentAuthorities,
null
)
.accounts({
networkState: networkStateAccountAddress(),
treasury: treasury.publicKey,
})
.rpc();
});
it("spin and pull the trigger", async () => {
await spinAndPullTheTrigger(force.toBuffer());
await emulateFulfill(force.toBuffer());
const randomness = await vrf.getRandomness(force.toBuffer());
console.log(randomness.randomness);
});
});
從我收集到的內容來看,這與測試文件中的 before 塊有關:
before(async () => {
await provider.connection.confirmTransaction(
await provider.connection.requestAirdrop(treasury.publicKey, 1 * LAMPORTS_PER_SOL),
"confirmed"
);
// Initialize test VRF
const fee = 1 * LAMPORTS_PER_SOL;
const fullfillmentAuthorities = [
fulfillmentAuthority.publicKey,
];
const configAuthority = Keypair.generate();
await vrf.methods
.initNetwork(
new BN(fee),
configAuthority.publicKey,
fullfillmentAuthorities,
null
)
.accounts({
networkState: networkStateAccountAddress(),
treasury: treasury.publicKey,
})
.rpc();
});
任何幫助將不勝感激。 謝謝你。
devnet 上的 VRF 程序已經用我們的配置初始化了,所以你不能初始化它。 emulateFulfill
function 將拋出UnauthorizedFulfillmentAuthority
異常,因為您的fulfillmentAuthority 密鑰未列入白名單。 試試這樣的,別忘了用自己的cflip程序ID改程序ID
import * as anchor from "@project-serum/anchor";
import { Program } from "@project-serum/anchor";
import {
Keypair,
PublicKey,
SystemProgram,
} from "@solana/web3.js";
import { Orao, networkStateAccountAddress, randomnessAccountAddress } from "@orao-network/solana-vrf";
import { Cflip, IDL } from "../target/types/cflip";
describe("cflip", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = new Program<Cflip>(IDL, new PublicKey("2XeJv53N1UzbupYNDH9PDakRWQFS4VX4bJDPm8P5T64J"), provider);
const vrf = new Orao(provider);
// Initial force for russian-roulette
let force = Keypair.generate().publicKey;
// This helper will play a single round of russian-roulette.
async function spinAndPullTheTrigger(force: Buffer) {
const random = randomnessAccountAddress(force);
const networkState = await vrf.getNetworkState()
const treasury = networkState.config.treasury
await program.methods
.spinAndPullTheTrigger([...force])
.accounts({
player: provider.wallet.publicKey,
vrf: vrf.programId,
config: networkStateAccountAddress(),
treasury,
random,
systemProgram: SystemProgram.programId,
})
.rpc();
}
it("spin and pull the trigger", async () => {
await spinAndPullTheTrigger(force.toBuffer());
// Await fulfilled randomness (default commitment is "finalized"):
const randomness = await vrf.waitFulfilled(force.toBuffer());
console.log("Your randomness is " + randomness.fulfilled());
});
});
你的 Anchor.toml 是什么? 另外我認為您使用的是 SDK 而不是 CPI,如果您發布更多代碼會更有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.