如何解决交易模拟失败:solana区块链交易期间的错误处理指令?



我一直在尝试写一些结构类型的数据到solana区块链,但一直被卡住在一个错误说->

Transaction simulation failed: Error processing Instruction 0: Program failed to complete 
Program 2qCpEJASM553foMRmd4MHRLxEFywKwvaUXRtypXJp4zv invoke [1]
Program consumption: 199505 units remaining
Program log: Instruction_data message object LoveRecord { groom: "a", created_on: "0" }
Program log: libstd rust_begin_panic
Program log: panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:67:98
Program 2qCpEJASM553foMRmd4MHRLxEFywKwvaUXRtypXJp4zv consumed 200000 of 200000 compute units
Program failed to complete: BPF program panicked
Program 2qCpEJASM553foMRmd4MHRLxEFywKwvaUXRtypXJp4zv failed: Program failed to complete

在Rust语言中solana程序入口点的代码为->

use borsh::{ BorshDeserialize, BorshSerialize };
use solana_program::{
account_info::{ next_account_info, AccountInfo },
entrypoint,
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
pubkey::Pubkey,
};
use std::io::ErrorKind::InvalidData;
#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct LoveRecord {
pub groom: String,
pub created_on: String
}
const DUMMY_TX_ID: &str = "a";
const DUMMY_CREATED_ON: &str = "0"; // milliseconds, 16 digits
pub fn get_init_love_record() -> LoveRecord {
LoveRecord{ groom: String::from(DUMMY_TX_ID), created_on: String::from(DUMMY_CREATED_ON) }
}
pub fn get_init_love_records() -> Vec<LoveRecord> {
let mut records = Vec::new();
for _ in 0..10 {
records.push(get_init_love_record());
}
return records;
}
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8]
) -> ProgramResult {
let accounts_iter = &mut accounts.iter();
let account = next_account_info(accounts_iter)?;
if account.owner != program_id {
msg!("Greeted account does not have the correct program id");
return Err(ProgramError::IncorrectProgramId);
}

let instruction_data_message = LoveRecord::try_from_slice(instruction_data).map_err(|err| {
msg!("Attempt to deserialize instruction data has failed. {:?}", err);
ProgramError::InvalidInstructionData
})?;
solana_program::msg!("pass");
msg!("pass");
msg!("Instruction_data message object {:?}", instruction_data_message);
let mut existing_data_messages = match <Vec<LoveRecord>>::try_from_slice(&account.data.borrow_mut()) {
Ok(data) => data,
Err(err) => {
if err.kind() == InvalidData {
msg!("InvalidData so initializing account data");
get_init_love_records()
} else {
msg!("Unknown error decoding account data {:?}", err)
}
}
};
let index = existing_data_messages.iter().position(|p| p.groom == String::from(DUMMY_TX_ID)).unwrap(); // find first dummy data entry
msg!("Found index {}", index);
existing_data_messages[index] = instruction_data_message; // set dummy data to new entry
let updated_data = existing_data_messages.try_to_vec().expect("Failed to encode data."); // set records object back to vector data
msg!("Final existing_data_messages[index] {:?}", existing_data_messages[index]);
// data algorithm for storing data into account and then archiving into Arweave
// 1. Each LoveRecord object will be prepopulated for txt field having 1 characters (length of a arweave tx).
// Each LoveRecordContainer will be prepopulated with 10 LoveRecord objects with dummy data.
// 2. Client will submit an arweave tx for each message; get back the tx id; and submit it to our program.
// 3. This tx id will be saved to the Solana program and be used for querying back to arweave to get actual data.
let data = &mut &mut account.data.borrow_mut();
msg!("Attempting save data.");
data[..updated_data.len()].copy_from_slice(&updated_data);    
let saved_data = <Vec<LoveRecord>>::try_from_slice(data)?;
msg!("LoveRecord has been saved to account data. {:?}", saved_data[index]);
msg!("End program.");
Ok(())
}

使用Borsch序列化发送事务的代码是->

static async sayHello(data) {
let config = DappLib.getConfig();
console.log(data);
let DUMMY_TX_ID = "a";
let DUMMY_CREATED_ON = "0";
class LoveRecord {
constructor(fields = undefined) {
this.groom = DUMMY_TX_ID;
this.created_on = DUMMY_CREATED_ON; // max milliseconds in dat
if (fields) {
this.groom = fields.groom;
this.created_on = fields.created_on;
}
}
}            


const LoveRecordSchema = new Map([[
LoveRecord,
{
kind: "struct",
fields: [
["groom", "string"],
["created_on", "string"],
],
},

]]);


const loveobj = new LoveRecord();
loveobj.groom = "a";
loveobj.created_on = "0";
const res = borsh.serialize(LoveRecordSchema,loveobj);

let result = await Blockchain.put({ config }, 'greeting', res);
console.log("Pass")
return {
type: DappLib.DAPP_RESULT_OBJECT,
label: 'Transaction Result',
result                
}
}

发送和签名事务的代码已被处理。如有任何帮助,我将不胜感激。

这是关于代码的一个非常具体的问题,但是错误消息可能是最好的查看位置:

Program log: panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:67:98

这似乎与下面这行相符:

let index = existing_data_messages.iter().position(|p| p.groom == String::from(DUMMY_TX_ID)).unwrap();

您在None值上调用unwrap(),这是有意义的,考虑到之前没有向该帐户写入任何内容。你需要处理的情况下,DUMMY_TX_ID没有发现在你的向量。

您可以在https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.position找到有关position()工作原理的更多信息