Skip to content

Commit

Permalink
Dedeuping update.
Browse files Browse the repository at this point in the history
  • Loading branch information
blockiosaurus committed Mar 10, 2024
1 parent 3bd52d1 commit 2c89b8c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 141 deletions.
4 changes: 1 addition & 3 deletions programs/mpl-core/src/processor/approve_plugin_authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,5 @@ fn process_approve_plugin_authority<'a, T: CoreAsset + DataBlob + SolanaAccount>
&mut plugin_registry,
payer,
system_program,
)?;

Ok(())
)
}
229 changes: 91 additions & 138 deletions programs/mpl-core/src/processor/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use solana_program::{
use crate::{
error::MplCoreError,
instruction::accounts::{UpdateAccounts, UpdateCollectionAccounts},
plugins::{Plugin, PluginType, RegistryRecord},
plugins::{Plugin, PluginHeader, PluginRegistry, PluginType, RegistryRecord},
state::{Asset, Collection, DataBlob, Key, SolanaAccount, UpdateAuthority},
utils::{
load_key, resize_or_reallocate_account, resolve_payer, validate_asset_permissions,
Expand Down Expand Up @@ -65,72 +65,15 @@ pub(crate) fn update<'a>(accounts: &'a [AccountInfo<'a>], args: UpdateArgs) -> P
dirty = true;
}
if dirty {
if let (Some(mut plugin_header), Some(mut plugin_registry)) =
(plugin_header, plugin_registry)
{
let new_asset_size = asset.get_size() as isize;
let size_diff = new_asset_size
.checked_sub(asset_size)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_size = (ctx.accounts.asset.data_len() as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_registry_offset = (plugin_header.plugin_registry_offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let registry_offset = plugin_header.plugin_registry_offset;
plugin_header.plugin_registry_offset = new_registry_offset as usize;

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

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

resize_or_reallocate_account(
ctx.accounts.asset,
payer,
ctx.accounts.system_program,
new_size as usize,
)?;

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

plugin_header.save(ctx.accounts.asset, new_asset_size as usize)?;
plugin_registry.registry = plugin_registry
.registry
.iter_mut()
.map(|record| {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
Ok(RegistryRecord {
plugin_type: record.plugin_type,
offset: new_offset as usize,
authority: record.authority.clone(),
})
})
.collect::<Result<Vec<_>, MplCoreError>>()?;
plugin_registry.save(ctx.accounts.asset, new_registry_offset as usize)?;
} else {
resize_or_reallocate_account(
ctx.accounts.asset,
payer,
ctx.accounts.system_program,
asset.get_size(),
)?;
}

asset.save(ctx.accounts.asset, 0)?;
process_update(
asset,
&plugin_header,
&plugin_registry,
asset_size,
ctx.accounts.asset,
payer,
ctx.accounts.system_program,
)?;
}

Ok(())
Expand All @@ -154,7 +97,7 @@ pub(crate) fn update_collection<'a>(
assert_signer(ctx.accounts.authority)?;
let payer = resolve_payer(ctx.accounts.authority, ctx.accounts.payer)?;

let (mut asset, plugin_header, plugin_registry) = validate_collection_permissions(
let (mut collection, plugin_header, plugin_registry) = validate_collection_permissions(
ctx.accounts.authority,
ctx.accounts.collection,
None,
Expand All @@ -164,90 +107,100 @@ pub(crate) fn update_collection<'a>(
Plugin::validate_update,
)?;

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

let mut dirty = false;
if let Some(new_update_authority) = ctx.accounts.new_update_authority {
asset.update_authority = *new_update_authority.key;
collection.update_authority = *new_update_authority.key;
dirty = true;
}
if let Some(new_name) = &args.new_name {
asset.name = new_name.clone();
collection.name = new_name.clone();
dirty = true;
}
if let Some(new_uri) = &args.new_uri {
asset.uri = new_uri.clone();
collection.uri = new_uri.clone();
dirty = true;
}
if dirty {
if let (Some(mut plugin_header), Some(mut plugin_registry)) =
(plugin_header, plugin_registry)
{
let new_asset_size = asset.get_size() as isize;
let size_diff = new_asset_size
.checked_sub(asset_size)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_size = (ctx.accounts.collection.data_len() as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_registry_offset = (plugin_header.plugin_registry_offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let registry_offset = plugin_header.plugin_registry_offset;
plugin_header.plugin_registry_offset = new_registry_offset as usize;

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

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

resize_or_reallocate_account(
ctx.accounts.collection,
payer,
ctx.accounts.system_program,
new_size as usize,
)?;

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

plugin_header.save(ctx.accounts.collection, new_asset_size as usize)?;
plugin_registry.registry = plugin_registry
.registry
.iter_mut()
.map(|record| {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
Ok(RegistryRecord {
plugin_type: record.plugin_type,
offset: new_offset as usize,
authority: record.authority.clone(),
})
process_update(
collection,
&plugin_header,
&plugin_registry,
collection_size,
ctx.accounts.collection,
payer,
ctx.accounts.system_program,
)?;
}

Ok(())
}

fn process_update<'a, T: DataBlob + SolanaAccount>(
core: T,
plugin_header: &Option<PluginHeader>,
plugin_registry: &Option<PluginRegistry>,
core_size: isize,
account: &AccountInfo<'a>,
payer: &AccountInfo<'a>,
system_program: &AccountInfo<'a>,
) -> ProgramResult {
if let (Some(mut plugin_header), Some(mut plugin_registry)) =
(plugin_header.clone(), plugin_registry.clone())
{
let new_asset_size = core.get_size() as isize;
let size_diff = new_asset_size
.checked_sub(core_size)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_size = (account.data_len() as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_registry_offset = (plugin_header.plugin_registry_offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let registry_offset = plugin_header.plugin_registry_offset;
plugin_header.plugin_registry_offset = new_registry_offset as usize;

let plugin_offset = core_size
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
let new_plugin_offset = new_asset_size
.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_asset_size as usize)?;
plugin_registry.registry = plugin_registry
.registry
.iter_mut()
.map(|record| {
let new_offset = (record.offset as isize)
.checked_add(size_diff)
.ok_or(MplCoreError::NumericalOverflow)?;
Ok(RegistryRecord {
plugin_type: record.plugin_type,
offset: new_offset as usize,
authority: record.authority.clone(),
})
.collect::<Result<Vec<_>, MplCoreError>>()?;
plugin_registry.save(ctx.accounts.collection, new_registry_offset as usize)?;
} else {
resize_or_reallocate_account(
ctx.accounts.collection,
payer,
ctx.accounts.system_program,
asset.get_size(),
)?;
}

asset.save(ctx.accounts.collection, 0)?;
})
.collect::<Result<Vec<_>, MplCoreError>>()?;
plugin_registry.save(account, new_registry_offset as usize)?;
} else {
resize_or_reallocate_account(account, payer, system_program, core.get_size())?;
}

core.save(account, 0)?;

Ok(())
}

0 comments on commit 2c89b8c

Please sign in to comment.