Skip to content

Commit

Permalink
Combine plugin updating into util
Browse files Browse the repository at this point in the history
  • Loading branch information
danenbm committed May 8, 2024
1 parent ba777c9 commit 6791c66
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 234 deletions.
26 changes: 4 additions & 22 deletions programs/mpl-core/src/plugins/external_plugins.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
pubkey::Pubkey,
};
use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
use strum::EnumCount;

use crate::{
error::MplCoreError,
state::{AssetV1, SolanaAccount},
state::{AssetV1, PluginSolanaAccount, SolanaAccount},
};

use super::{
Expand Down Expand Up @@ -180,25 +177,10 @@ impl ExternalPlugin {
ExternalPlugin::DataStore(data_store) => data_store.validate_add_external_plugin(ctx),
}
}

/// Load and deserialize a plugin from an offset in the account.
pub fn load(account: &AccountInfo, offset: usize) -> Result<Self, ProgramError> {
let mut bytes: &[u8] = &(*account.data).borrow()[offset..];
Self::deserialize(&mut bytes).map_err(|error| {
msg!("Error: {}", error);
MplCoreError::DeserializationError.into()
})
}

/// Save and serialize a plugin to an offset in the account.
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);
MplCoreError::SerializationError.into()
})
}
}

impl PluginSolanaAccount for ExternalPlugin {}

impl From<&ExternalPluginInitInfo> for ExternalPlugin {
fn from(init_info: &ExternalPluginInitInfo) -> Self {
match init_info {
Expand Down
2 changes: 1 addition & 1 deletion programs/mpl-core/src/plugins/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::collections::BTreeMap;

use crate::{
error::MplCoreError,
state::{Authority, Key},
state::{Authority, Key, PluginSolanaAccount},
};

use super::{
Expand Down
27 changes: 3 additions & 24 deletions programs/mpl-core/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,9 @@ pub use utils::*;

use borsh::{BorshDeserialize, BorshSerialize};
use num_derive::ToPrimitive;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
};
use strum::EnumCount;

use crate::{
error::MplCoreError,
state::{Authority, Compressible, DataBlob},
};
use crate::state::{Authority, Compressible, DataBlob, PluginSolanaAccount};

/// Definition of the plugin variants, each containing a link to the plugin struct.
#[repr(C)]
Expand Down Expand Up @@ -86,25 +80,10 @@ impl Plugin {
pub fn manager(&self) -> Authority {
PluginType::from(self).manager()
}

/// Load and deserialize a plugin from an offset in the account.
pub fn load(account: &AccountInfo, offset: usize) -> Result<Self, ProgramError> {
let mut bytes: &[u8] = &(*account.data).borrow()[offset..];
Self::deserialize(&mut bytes).map_err(|error| {
msg!("Error: {}", error);
MplCoreError::DeserializationError.into()
})
}

/// Save and serialize a plugin to an offset in the account.
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);
MplCoreError::SerializationError.into()
})
}
}

impl PluginSolanaAccount for Plugin {}

impl Compressible for Plugin {}

/// List of first party plugin types.
Expand Down
2 changes: 1 addition & 1 deletion programs/mpl-core/src/plugins/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::collections::HashSet;
use crate::{
error::MplCoreError,
plugins::{ExternalCheckResult, HookableLifecycleEvent},
state::{AssetV1, Authority, CoreAsset, DataBlob, Key, SolanaAccount},
state::{AssetV1, Authority, CoreAsset, DataBlob, Key, PluginSolanaAccount, SolanaAccount},
utils::resize_or_reallocate_account,
};

Expand Down
84 changes: 22 additions & 62 deletions programs/mpl-core/src/processor/update.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use borsh::{BorshDeserialize, BorshSerialize};
use mpl_utils::assert_signer;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_memory::sol_memcpy,
};
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg};

use crate::{
error::MplCoreError,
Expand All @@ -13,8 +11,8 @@ use crate::{
},
state::{AssetV1, CollectionV1, DataBlob, Key, SolanaAccount, UpdateAuthority},
utils::{
load_key, resize_or_reallocate_account, resolve_authority, validate_asset_permissions,
validate_collection_permissions,
load_key, move_plugins_and_registry, resize_or_reallocate_account, resolve_authority,
validate_asset_permissions, validate_collection_permissions,
},
};

Expand Down Expand Up @@ -70,7 +68,7 @@ pub(crate) fn update<'a>(accounts: &'a [AccountInfo<'a>], args: UpdateV1Args) ->
// Increment sequence number and save only if it is `Some(_)`.
asset.increment_seq_and_save(ctx.accounts.asset)?;

let asset_size = asset.get_size() as isize;
let asset_size = asset.get_size();

let mut dirty = false;
if let Some(new_update_authority) = args.new_update_authority {
Expand Down Expand Up @@ -153,7 +151,7 @@ pub(crate) fn update_collection<'a>(
Some(HookableLifecycleEvent::Update),
)?;

let collection_size = collection.get_size() as isize;
let collection_size = collection.get_size();

let mut dirty = false;
if let Some(new_update_authority) = ctx.accounts.new_update_authority {
Expand Down Expand Up @@ -187,7 +185,7 @@ fn process_update<'a, T: DataBlob + SolanaAccount>(
core: T,
plugin_header: &Option<PluginHeaderV1>,
plugin_registry: &Option<PluginRegistryV1>,
core_size: isize,
core_size: usize,
account: &AccountInfo<'a>,
payer: &AccountInfo<'a>,
system_program: &AccountInfo<'a>,
Expand All @@ -196,70 +194,32 @@ fn process_update<'a, T: DataBlob + SolanaAccount>(
(plugin_header.clone(), plugin_registry.clone())
{
// The new size of the asset and new offset of the plugin header.
let new_core_size = core.get_size() as isize;
let new_core_size = core.get_size();

// The difference in size between the new and old asset which is used to calculate the new size of the account.
let size_diff = new_core_size
.checked_sub(core_size)
.ok_or(MplCoreError::NumericalOverflow)?;

// The new size of the account.
let new_size = (account.data_len() as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

// The new offset of the plugin registry is the old offset plus the size difference.
let registry_offset = plugin_header.plugin_registry_offset;
let new_registry_offset = (registry_offset as isize)
.checked_add(size_diff)
let size_diff = (new_core_size as isize)
.checked_sub(core_size as isize)
.ok_or(MplCoreError::NumericalOverflow)?;
plugin_header.plugin_registry_offset = new_registry_offset as usize;

// The offset of the first plugin is the core size plus the size of the plugin header.
let plugin_offset = core_size
.checked_add(plugin_header.get_size() as isize)
.checked_add(plugin_header.get_size())
.ok_or(MplCoreError::NumericalOverflow)?;

let new_plugin_offset = plugin_offset
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

// //TODO: This is memory intensive, we should use memmove instead probably.
let src = account.data.borrow()[(plugin_offset as usize)..registry_offset].to_vec();

resize_or_reallocate_account(account, payer, system_program, new_size as usize)?;

sol_memcpy(
&mut account.data.borrow_mut()[(new_plugin_offset as usize)..],
&src,
src.len(),
);

plugin_header.save(account, new_core_size as usize)?;

// Move offsets for existing registry records.
for record in &mut plugin_registry.external_registry {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

record.offset = new_offset as usize;
}

for record in &mut plugin_registry.registry {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

record.offset = new_offset as usize;
}

plugin_registry.save(account, new_registry_offset as usize)?;
move_plugins_and_registry(
new_core_size,
size_diff,
plugin_offset,
plugin_offset,
&mut plugin_header,
&mut plugin_registry,
account,
payer,
system_program,
)?;
} else {
resize_or_reallocate_account(account, payer, system_program, core.get_size())?;
}

core.save(account, 0)?;

Ok(())
core.save(account, 0)
}
80 changes: 18 additions & 62 deletions programs/mpl-core/src/processor/update_external_plugin.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use borsh::{BorshDeserialize, BorshSerialize};
use mpl_utils::assert_signer;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_memory::sol_memcpy,
};
use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg};

use crate::{
error::MplCoreError,
Expand All @@ -13,9 +11,9 @@ use crate::{
fetch_wrapped_external_plugin, find_external_plugin, ExternalPlugin, ExternalPluginKey,
ExternalPluginUpdateInfo, Plugin, PluginHeaderV1, PluginRegistryV1, PluginType,
},
state::{AssetV1, CollectionV1, DataBlob, Key, SolanaAccount},
state::{AssetV1, CollectionV1, DataBlob, Key, PluginSolanaAccount, SolanaAccount},
utils::{
load_key, resize_or_reallocate_account, resolve_authority, validate_asset_permissions,
load_key, move_plugins_and_registry, resolve_authority, validate_asset_permissions,
validate_collection_permissions,
},
};
Expand Down Expand Up @@ -180,68 +178,26 @@ fn process_update_external_plugin<'a, T: DataBlob + SolanaAccount>(
let new_plugin_data = new_plugin.try_to_vec()?;

// The difference in size between the new and old account which is used to calculate the new size of the account.
let plugin_size = plugin_data.len() as isize;
let plugin_size = plugin_data.len();
let size_diff = (new_plugin_data.len() as isize)
.checked_sub(plugin_size)
.ok_or(MplCoreError::NumericalOverflow)?;

// The new size of the account.
let new_size = (account.data_len() as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

// The new offset of the plugin registry is the old offset plus the size difference.
let registry_offset = plugin_header.plugin_registry_offset;
let new_registry_offset = (registry_offset as isize)
.checked_add(size_diff)
.checked_sub(plugin_size as isize)
.ok_or(MplCoreError::NumericalOverflow)?;
plugin_header.plugin_registry_offset = new_registry_offset as usize;

// The offset of the first plugin is the plugin offset plus the size of the plugin.
let next_plugin_offset = (registry_record.offset as isize)
let data_to_move_location = (registry_record.offset)
.checked_add(plugin_size)
.ok_or(MplCoreError::NumericalOverflow)?;

let new_next_plugin_offset = next_plugin_offset
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

// //TODO: This is memory intensive, we should use memmove instead probably.
let src = account.data.borrow()[(next_plugin_offset as usize)..registry_offset].to_vec();

resize_or_reallocate_account(account, payer, system_program, new_size as usize)?;

sol_memcpy(
&mut account.data.borrow_mut()[(new_next_plugin_offset as usize)..],
&src,
src.len(),
);

plugin_header.save(account, core.get_size())?;

// Move offsets for existing registry records.
for record in &mut plugin_registry.external_registry {
if registry_record.offset < record.offset {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

record.offset = new_offset as usize;
}
}

for record in &mut plugin_registry.registry {
if registry_record.offset < record.offset {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;

record.offset = new_offset as usize;
}
}

plugin_registry.save(account, new_registry_offset as usize)?;
new_plugin.save(account, registry_record.offset)?;
move_plugins_and_registry(
core.get_size(),
size_diff,
registry_record.offset,
data_to_move_location,
&mut plugin_header,
&mut plugin_registry,
account,
payer,
system_program,
)?;

Ok(())
new_plugin.save(account, registry_record.offset)
}
Loading

0 comments on commit 6791c66

Please sign in to comment.