Open vicyyn opened 3 years ago
Switching my provider URL from "https://anchor.projectserum.com" to my local JSON RPC URL (http://127.0.0.1:8899 by default I think) fixed this issue for me.
Having the same issue as @vicyyn on localnet. Here is the full repo example of the error.
This is the program code:
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod test_recent_bh {
use super::*;
pub fn initialize(_ctx: Context<Initialize>) -> ProgramResult {
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
pub recent_blockhashes: Sysvar<'info, RecentBlockhashes>,
}
Here is how I'm testing it:
import * as anchor from "@project-serum/anchor";
import { SYSVAR_RECENT_BLOCKHASHES_PUBKEY } from "@solana/web3.js";
describe("test-recent-bh", () => {
// Configure the client to use the local cluster.
const provider = anchor.Provider.env();
anchor.setProvider(provider);
const idl = JSON.parse(require("fs").readFileSync("./target/idl/test_recent_bh.json"));
const programId = new anchor.web3.PublicKey("3vcGd5N1KYq3Gv9xPq9VNKqZPGFBRsS8SMGRgAWa98ph");
const program = new anchor.Program(idl, programId);
it("Is initialized!", async () => {
const tx = await program.rpc.initialize({
accounts: { recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY },
signers: [],
});
console.log(tx);
});
});
The relevant part of the anchor test
output error:
logs: [
'Program 3vcGd5N1KYq3Gv9xPq9VNKqZPGFBRsS8SMGRgAWa98ph invoke [1]',
'Program 3vcGd5N1KYq3Gv9xPq9VNKqZPGFBRsS8SMGRgAWa98ph consumed 200000 of 200000 compute units',
'Program failed to complete: exceeded maximum number of instructions allowed (200000) at instruction #3714',
'Program 3vcGd5N1KYq3Gv9xPq9VNKqZPGFBRsS8SMGRgAWa98ph failed: Program failed to complete'
]
}
1) Is initialized!
0 passing (91ms)
1 failing
1) test-recent-bh
Is initialized!:
Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Program failed to complete
at Connection.sendEncodedTransaction (node_modules/@solana/web3.js/src/connection.ts:3668:13)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at Connection.sendRawTransaction (node_modules/@solana/web3.js/src/connection.ts:3628:20)
at sendAndConfirmRawTransaction (node_modules/@solana/web3.js/src/util/send-and-confirm-raw-transaction.ts:27:21)
at Provider.send (node_modules/@project-serum/anchor/src/provider.ts:114:18)
at Object.rpc [as initialize] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:19:23)
at Context.<anonymous> (tests/test-recent-bh.ts:14:16)
I tried adjusting the MAX_ENTRIES
and fn size_of() -> usize
values in recent_blockhashes.rs
to be slightly smaller to see if that'd help it but that did basically nothing and I'm out of ideas lol
@RohanKapurDEV I tried out the reproduction (with an update to the programId
in the js tests) and didn't experience the issue. Not sure what'd cause this. Might be worth trying fresh.
Parsing the enter RecentBlockhashes
cannot be done on-chain, it is a vec of 150 Entry
, each entry is 32 bytes hashes + fee calculator struct.
https://github.com/solana-labs/solana/blob/2515f6a04f92fbab38fff8f40cfdd9d4165b9722/sdk/program/src/sysvar/recent_blockhashes.rs#L15
At least not just like that, the best option seems to deserialize a single specific entry in the vec.
It might not happen on localhost as the test running against genesys might not have a filled RecentBlockhashes vec yet.
Parsing the enter
RecentBlockhashes
cannot be done on-chain, it is a vec of 150Entry
, each entry is 32 bytes hashes + fee calculator struct. https://github.com/solana-labs/solana/blob/2515f6a04f92fbab38fff8f40cfdd9d4165b9722/sdk/program/src/sysvar/recent_blockhashes.rs#L15At least not just like that, the best option seems to deserialize a single specific entry in the vec.
It might not happen on localhost as the test running against genesys might not have a filled RecentBlockhashes vec yet.
@Arrowana how does one go about deserializing a single specific entry?
I'm experiencing the same issue on localhost. Using a bare-metal Solana API doesn't have the same issue, so it leads me to believe that it's Anchor-related. Code snippet below works:
/// Instruction processor
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
// Create in iterator to safety reference accounts in the slice
let account_info_iter = &mut accounts.iter();
let blockhashes_sysvar_info = next_account_info(account_info_iter)?;
let blockhashes_via_account = RecentBlockhashes::from_account_info(blockhashes_sysvar_info)?;
Ok(())
}
Parsing the enter
RecentBlockhashes
cannot be done on-chain, it is a vec of 150Entry
, each entry is 32 bytes hashes + fee calculator struct. https://github.com/solana-labs/solana/blob/2515f6a04f92fbab38fff8f40cfdd9d4165b9722/sdk/program/src/sysvar/recent_blockhashes.rs#L15 At least not just like that, the best option seems to deserialize a single specific entry in the vec. It might not happen on localhost as the test running against genesys might not have a filled RecentBlockhashes vec yet.@Arrowana how does one go about deserializing a single specific entry?
I'm experiencing the same issue on localhost. Using a bare-metal Solana API doesn't have the same issue, so it leads me to believe that it's Anchor-related. Code snippet below works:
/// Instruction processor pub fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], ) -> ProgramResult { // Create in iterator to safety reference accounts in the slice let account_info_iter = &mut accounts.iter(); let blockhashes_sysvar_info = next_account_info(account_info_iter)?; let blockhashes_via_account = RecentBlockhashes::from_account_info(blockhashes_sysvar_info)?; Ok(()) }
"It might not happen on localhost as the test running against genesys might not have a filled RecentBlockhashes vec yet."
Maybe let it fill then execute your test.
Also RecentBlockhashes is deprecated, use SlotHashes instead.
An example in metaplex where the first hash is read by doing a manual deserialization. https://github.com/metaplex-foundation/metaplex-program-library/blob/master/candy-machine/program/src/lib.rs#L270-L271
@Arrowana thanks for the code snipped, it worked really well!
If you own the Metaplex code, I think there might be an issue with its current form:
let data = recent_slothashes.data.borrow();
let most_recent = array_ref![data, 4, 8];
let index = u64::from_le_bytes(*most_recent);
let most_recent = array_ref![data, 8, 8];
let most_recent = array_ref![data, 8 + 8, 8];
pub type SlotHash = (Slot, Hash);
#[repr(C)]
#[derive(Serialize, Deserialize, PartialEq, Debug, Default)]
pub struct SlotHashes(Vec<SlotHash>);
'Program BE5g9sKeejZf85vmpU1N16whEgAXsp9jjEFmmN8ZMHMd invoke [1]', 'Program BE5g9sKeejZf85vmpU1N16whEgAXsp9jjEFmmN8ZMHMd consumed 200000 of 200000 compute units', 'Program failed to complete: exceeded maximum number of instructions allowed (200000) at instruction #10123', 'Program BE5g9sKeejZf85vmpU1N16whEgAXsp9jjEFmmN8ZMHMd failed: Program failed to complete'