I am creating simple contract for storing ipfs hashes (see in attachment). When trying to call instruction 1 (AddIpfsHash) from python via solana-py and solders I get following error:
"Transaction simulation failed: Error processing Instruction 0: Failed to serialize or deserialize account data: Unknown"
I have tried multiple things, but i am not quite sure how to go on (i am not Rust developer, this is just for my Master Thesis :D) . If you could provide any help I would be very greatful ! If you'd like to see the code from python I will be happy to share and check it with you.
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
pubkey::Pubkey,
program_error::ProgramError,
rent::Rent,
sysvar::Sysvar,
msg
};
// Define the instruction types this program can handle
pub enum Instruction {
InitializeAccount,
AddIpfsHash { hash: String },
}
// Struct to represent the IPFS record
#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct IpfsRecord {
pub ipfs_hashes: Vec<String>,
}
// Deserialize instruction data into the Instruction enum
impl Instruction {
pub fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
let (&instruction_type, rest) = input.split_first().ok_or(ProgramError::InvalidInstructionData)?;
Ok(match instruction_type {
0 => Self::InitializeAccount,
1 => {
let hash = String::from_utf8(rest.to_vec()).map_err(|_| ProgramError::InvalidInstructionData)?;
Self::AddIpfsHash { hash }
},
_ => return Err(ProgramError::InvalidInstructionData),
})
}
}
// Entry point of the program
entrypoint!(process_instruction);
// Program entry function
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!("Account does not have the correct program id");
return Err(ProgramError::IncorrectProgramId);
}
let instruction = Instruction::unpack(instruction_data)?;
match instruction {
Instruction::InitializeAccount => {
let rent_exemption = Rent::get()?.minimum_balance(account.data_len());
if **account.lamports.borrow() < rent_exemption {
return Err(ProgramError::InsufficientFunds);
}
let ipfs_record = IpfsRecord { ipfs_hashes: Vec::new() };
ipfs_record.serialize(&mut &mut account.data.borrow_mut()[..])?;
},
Instruction::AddIpfsHash { hash } => {
let mut ipfs_record = IpfsRecord::try_from_slice(&account.data.borrow())?;
ipfs_record.ipfs_hashes.push(hash);
msg!("Zde");
ipfs_record.serialize(&mut &mut account.data.borrow_mut()[..])?;
},
}
Ok(())
}