From b6445b98792a028521f1561a355b70167d755901 Mon Sep 17 00:00:00 2001 From: Michael Danenberg <56533526+danenbm@users.noreply.github.com> Date: Sat, 17 Feb 2024 14:16:03 -0800 Subject: [PATCH] Move load and save to trait and check key --- programs/mpl-asset/src/processor/transfer.rs | 88 ++++++++++++++++++- programs/mpl-asset/src/state/asset.rs | 8 +- programs/mpl-asset/src/state/mod.rs | 4 +- programs/mpl-asset/src/state/plugin_header.rs | 24 ++--- programs/mpl-asset/src/utils.rs | 33 ++++++- 5 files changed, 132 insertions(+), 25 deletions(-) diff --git a/programs/mpl-asset/src/processor/transfer.rs b/programs/mpl-asset/src/processor/transfer.rs index 1a7edcf6..684a7132 100644 --- a/programs/mpl-asset/src/processor/transfer.rs +++ b/programs/mpl-asset/src/processor/transfer.rs @@ -2,13 +2,14 @@ use borsh::{BorshDeserialize, BorshSerialize}; use mpl_utils::assert_signer; use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, program::invoke, - program_memory::sol_memcpy, rent::Rent, system_instruction, system_program, sysvar::Sysvar, + program_memory::sol_memcpy, system_instruction, system_program, }; use crate::{ error::MplAssetError, - instruction::accounts::CreateAccounts, + instruction::accounts::TransferAccounts, state::{Asset, Compressible, DataState, HashedAsset, Key}, + utils::DataBlob, }; #[repr(C)] @@ -22,6 +23,89 @@ pub enum MigrationLevel { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] pub struct TransferArgs {} +// // danenbm working on +// #[account(0, writable, name="asset_address", desc = "The address of the asset")] +// #[account(1, optional, name="collection", desc = "The collection to which the asset belongs")] +// #[account(2, signer, name="authority", desc = "The owner or delegate of the asset")] +// #[account(3, optional, writable, signer, name="payer", desc = "The account paying for the storage fees")] +// #[account(4, name="new_owner", desc = "The new owner to which to transfer the asset")] +// #[account(5, optional, name="log_wrapper", desc = "The SPL Noop Program")] +// Transfer(TransferArgs), + pub(crate) fn transfer<'a>(accounts: &'a [AccountInfo<'a>], args: TransferArgs) -> ProgramResult { + // Accounts. + let ctx = TransferAccounts::context(accounts)?; + + // Guards. + assert_signer(ctx.accounts.authority)?; + + if let Some(payer) = ctx.accounts.payer { + assert_signer(payer)?; + } + + let asset = Asset::load(ctx.accounts.asset_address, 0)?; + + asset.owner = ctx.accounts.new_owner.key(); + + // if *ctx.accounts.system_program.key != system_program::id() { + // return Err(MplAssetError::InvalidSystemProgram.into()); + // } + + // let updated_asset = Asset { + // key: Key::Asset, + // update_authority: *ctx + // .accounts + // .update_authority + // .unwrap_or(ctx.accounts.payer) + // .key, + // owner: *ctx + // .accounts + // .owner + // .unwrap_or(ctx.accounts.update_authority.unwrap_or(ctx.accounts.payer)) + // .key, + // name: args.name, + // uri: args.uri, + // }; + + // let serialized_data = new_asset.try_to_vec()?; + + // let serialized_data = match args.data_state { + // DataState::AccountState => serialized_data, + // DataState::LedgerState => { + // invoke(&spl_noop::instruction(serialized_data.clone()), &[])?; + + // let hashed_asset = HashedAsset { + // key: Key::HashedAsset, + // hash: new_asset.hash()?, + // }; + + // hashed_asset.try_to_vec()? + // } + // }; + + //let lamports = rent.minimum_balance(serialized_data.len()); + + // CPI to the System Program. + // invoke( + // &system_instruction::create_account( + // ctx.accounts.payer.key, + // ctx.accounts.asset_address.key, + // lamports, + // serialized_data.len() as u64, + // &crate::id(), + // ), + // &[ + // ctx.accounts.payer.clone(), + // ctx.accounts.asset_address.clone(), + // ctx.accounts.system_program.clone(), + // ], + // )?; + + // sol_memcpy( + // &mut ctx.accounts.asset_address.try_borrow_mut_data()?, + // &serialized_data, + // serialized_data.len(), + // ); + Ok(()) } diff --git a/programs/mpl-asset/src/state/asset.rs b/programs/mpl-asset/src/state/asset.rs index ef9213ac..5424ec96 100644 --- a/programs/mpl-asset/src/state/asset.rs +++ b/programs/mpl-asset/src/state/asset.rs @@ -2,9 +2,9 @@ use borsh::{BorshDeserialize, BorshSerialize}; use shank::ShankAccount; use solana_program::{keccak, program_error::ProgramError, pubkey::Pubkey}; -use crate::utils::DataBlob; +use crate::{state::Key, utils::DataBlob}; -use super::{Compressible, Key}; +use super::Compressible; #[derive(Clone, BorshSerialize, BorshDeserialize, Debug, ShankAccount)] pub struct Asset { @@ -35,6 +35,10 @@ impl DataBlob for Asset { fn get_size(&self) -> usize { Asset::BASE_LENGTH + self.name.len() + self.uri.len() } + + fn key() -> Key { + Key::Asset + } } #[derive(Clone, BorshSerialize, BorshDeserialize, Debug, ShankAccount)] diff --git a/programs/mpl-asset/src/state/mod.rs b/programs/mpl-asset/src/state/mod.rs index 1b398b07..a0967b73 100644 --- a/programs/mpl-asset/src/state/mod.rs +++ b/programs/mpl-asset/src/state/mod.rs @@ -2,6 +2,7 @@ mod asset; pub use asset::*; mod plugin_header; +use num_derive::FromPrimitive; pub use plugin_header::*; use borsh::{BorshDeserialize, BorshSerialize}; @@ -44,11 +45,12 @@ pub trait Compressible { fn hash(&self) -> Result<[u8; 32], ProgramError>; } -#[derive(Clone, BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq)] +#[derive(Clone, BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, FromPrimitive)] pub enum Key { Uninitialized, Asset, HashedAsset, Collection, HashedCollection, + PluginHeader, } diff --git a/programs/mpl-asset/src/state/plugin_header.rs b/programs/mpl-asset/src/state/plugin_header.rs index 22596c1d..efe97dbb 100644 --- a/programs/mpl-asset/src/state/plugin_header.rs +++ b/programs/mpl-asset/src/state/plugin_header.rs @@ -4,8 +4,7 @@ use solana_program::entrypoint::ProgramResult; use solana_program::msg; use solana_program::program_error::ProgramError; -use crate::error::MplAssetError; -use crate::utils::DataBlob; +use crate::{error::MplAssetError, state::Key, utils::DataBlob}; #[repr(C)] #[derive(Clone, BorshSerialize, BorshDeserialize, Debug)] @@ -14,23 +13,6 @@ pub struct PluginHeader { pub plugin_map_offset: usize, // 8 } -impl PluginHeader { - pub fn load(account: &AccountInfo, offset: usize) -> Result { - let mut bytes: &[u8] = &(*account.data).borrow()[offset..]; - PluginHeader::deserialize(&mut bytes).map_err(|error| { - msg!("Error: {}", error); - MplAssetError::DeserializationError.into() - }) - } - - pub fn save(&self, account: &AccountInfo, offset: usize) -> ProgramResult { - borsh::to_writer(&mut account.data.borrow_mut()[offset..], self).map_err(|error| { - msg!("Error: {}", error); - MplAssetError::SerializationError.into() - }) - } -} - impl DataBlob for PluginHeader { fn get_initial_size() -> usize { 1 + 8 @@ -39,4 +21,8 @@ impl DataBlob for PluginHeader { fn get_size(&self) -> usize { 1 + 8 } + + fn key() -> Key { + Key::PluginHeader + } } diff --git a/programs/mpl-asset/src/utils.rs b/programs/mpl-asset/src/utils.rs index e829d81a..a6b57a30 100644 --- a/programs/mpl-asset/src/utils.rs +++ b/programs/mpl-asset/src/utils.rs @@ -1,4 +1,35 @@ -pub trait DataBlob { +use crate::{error::MplAssetError, state::Key}; +use borsh::{BorshDeserialize, BorshSerialize}; +use num_traits::FromPrimitive; +use solana_program::account_info::AccountInfo; +use solana_program::entrypoint::ProgramResult; +use solana_program::msg; +use solana_program::program_error::ProgramError; + +pub trait DataBlob: BorshSerialize + BorshDeserialize { fn get_initial_size() -> usize; fn get_size(&self) -> usize; + fn key() -> Key; + + fn load(account: &AccountInfo, offset: usize) -> Result { + let key = Key::from_u8((*account.data).borrow()[offset]) + .ok_or(MplAssetError::DeserializationError)?; + + if key != Self::key() { + return Err(MplAssetError::DeserializationError.into()); + } + + let mut bytes: &[u8] = &(*account.data).borrow()[offset..]; + Self::deserialize(&mut bytes).map_err(|error| { + msg!("Error: {}", error); + MplAssetError::DeserializationError.into() + }) + } + + fn save(&self, account: &AccountInfo, offset: usize) -> ProgramResult { + borsh::to_writer(&mut account.data.borrow_mut()[offset..], self).map_err(|error| { + msg!("Error: {}", error); + MplAssetError::SerializationError.into() + }) + } }