2

我一直在尝试将一些结构类型的数据写入 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 Serialize 发送交易的代码是 ->

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                
            }
        }

已处理发送和签署交易的代码。任何帮助将非常感激。

4

1 回答 1

0

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

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();

您正在调用unwrap()一个None值,这是有道理的,考虑到之前没有向此帐户写入任何内容。您需要处理DUMMY_TX_ID在您的向量中找不到的情况。

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

于 2021-08-27T22:57:23.590 回答