Skip to content

Commit

Permalink
Merge pull request #10 from metaplex-foundation/wip/function-pointers
Browse files Browse the repository at this point in the history
Switching to function pointers for checks.
  • Loading branch information
blockiosaurus authored Mar 7, 2024
2 parents 9f7af70 + 0525cff commit adf6255
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 172 deletions.
97 changes: 12 additions & 85 deletions programs/mpl-core/src/plugins/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,33 @@ pub enum CheckResult {

impl PluginType {
/// Check if a plugin is permitted to approve or deny a create action.
pub fn check_create(&self) -> CheckResult {
pub fn check_create(plugin_type: &PluginType) -> CheckResult {
#[allow(clippy::match_single_binding)]
match self {
match plugin_type {
_ => CheckResult::None,
}
}

/// Check if a plugin is permitted to approve or deny an update action.
pub fn check_update(&self) -> CheckResult {
pub fn check_update(plugin_type: &PluginType) -> CheckResult {
#[allow(clippy::match_single_binding)]
match self {
match plugin_type {
_ => CheckResult::None,
}
}

/// Check if a plugin is permitted to approve or deny a burn action.
pub fn check_burn(&self) -> CheckResult {
#[allow(clippy::match_single_binding)]
match self {
pub fn check_burn(plugin_type: &PluginType) -> CheckResult {
match plugin_type {
PluginType::Freeze => CheckResult::CanReject,
PluginType::Burn => CheckResult::CanApprove,
_ => CheckResult::None,
}
}

/// Check if a plugin is permitted to approve or deny a transfer action.
pub fn check_transfer(&self) -> CheckResult {
match self {
pub fn check_transfer(plugin_type: &PluginType) -> CheckResult {
match plugin_type {
PluginType::Royalties => CheckResult::CanReject,
PluginType::Freeze => CheckResult::CanReject,
PluginType::Transfer => CheckResult::CanApprove,
Expand All @@ -63,17 +62,17 @@ impl PluginType {
}

/// Check if a plugin is permitted to approve or deny a compress action.
pub fn check_compress(&self) -> CheckResult {
pub fn check_compress(plugin_type: &PluginType) -> CheckResult {
#[allow(clippy::match_single_binding)]
match self {
match plugin_type {
_ => CheckResult::None,
}
}

/// Check if a plugin is permitted to approve or deny a decompress action.
pub fn check_decompress(&self) -> CheckResult {
pub fn check_decompress(plugin_type: &PluginType) -> CheckResult {
#[allow(clippy::match_single_binding)]
match self {
match plugin_type {
_ => CheckResult::None,
}
}
Expand Down Expand Up @@ -417,75 +416,3 @@ where
}
Ok(false)
}

// pub(crate) fn validate_transfer_plugin_checks<'a>(
// key: Key,
// checks: &BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
// authority: &AccountInfo<'a>,
// new_owner: &AccountInfo<'a>,
// asset: &AccountInfo<'a>,
// collection: Option<&AccountInfo<'a>>,
// ) -> Result<bool, ProgramError> {
// solana_program::msg!("validate_transfer_plugin_checks");
// for (_, (check_key, check_result, registry_record)) in checks {
// if *check_key == key
// && matches!(
// check_result,
// CheckResult::CanApprove | CheckResult::CanReject
// )
// {
// solana_program::msg!("key: {:?}", key);
// let account = match key {
// Key::Collection => collection.ok_or(MplCoreError::InvalidCollection)?,
// Key::Asset => asset,
// _ => unreachable!(),
// };
// let result = Plugin::load(account, registry_record.offset)?.validate_transfer(
// authority,
// new_owner,
// &registry_record.authorities,
// )?;
// solana_program::msg!("result: {:?}", result);
// match result {
// ValidationResult::Rejected => return Err(MplCoreError::InvalidAuthority.into()),
// ValidationResult::Approved => return Ok(true),
// ValidationResult::Pass => continue,
// }
// }
// }
// Ok(false)
// }

// pub(crate) fn validate_update_plugin_checks<'a>(
// key: Key,
// checks: &BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
// authority: &AccountInfo<'a>,
// asset: &AccountInfo<'a>,
// collection: Option<&AccountInfo<'a>>,
// ) -> Result<bool, ProgramError> {
// solana_program::msg!("validate_update_plugin_checks");
// for (_, (check_key, check_result, registry_record)) in checks {
// if *check_key == key
// && matches!(
// check_result,
// CheckResult::CanApprove | CheckResult::CanReject
// )
// {
// solana_program::msg!("key: {:?}", key);
// let account = match key {
// Key::Collection => collection.ok_or(MplCoreError::InvalidCollection)?,
// Key::Asset => asset,
// _ => unreachable!(),
// };
// let result = Plugin::load(account, registry_record.offset)?
// .validate_update(authority, &registry_record.authorities)?;
// solana_program::msg!("result: {:?}", result);
// match result {
// ValidationResult::Rejected => return Err(MplCoreError::InvalidAuthority.into()),
// ValidationResult::Approved => return Ok(true),
// ValidationResult::Pass => continue,
// }
// }
// }
// Ok(false)
// }
77 changes: 4 additions & 73 deletions programs/mpl-core/src/plugins/plugin_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,86 +19,17 @@ pub struct PluginRegistry {
}

impl PluginRegistry {
/// Evaluate create checks for all plugins.
pub fn check_create(
/// Evaluate checks for all plugins in the registry.
pub fn check_registry(
&self,
key: Key,
check_fp: fn(&PluginType) -> CheckResult,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_create(), record.clone()),
);
}
}

/// Evaluate update checks for all plugins.
pub fn check_update(
&self,
key: Key,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_update(), record.clone()),
);
}
}

/// Evaluate delete checks for all plugins.
pub fn check_burn(
&self,
key: Key,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_burn(), record.clone()),
);
}
}

/// Evaluate transfer checks for all plugins.
pub fn check_transfer(
&self,
key: Key,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_transfer(), record.clone()),
);
}
}

/// Evaluate the compress checks for all plugins.
pub fn check_compress(
&self,
key: Key,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_compress(), record.clone()),
);
}
}

/// Evaluate the decompress checks for all plugins.
pub fn check_decompress(
&self,
key: Key,
result: &mut BTreeMap<PluginType, (Key, CheckResult, RegistryRecord)>,
) {
for record in &self.registry {
result.insert(
record.plugin_type,
(key, record.plugin_type.check_decompress(), record.clone()),
(key, check_fp(&record.plugin_type), record.clone()),
);
}
}
Expand Down
1 change: 1 addition & 0 deletions programs/mpl-core/src/plugins/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ pub fn initialize_plugin<'a, T: DataBlob + SolanaAccount>(
let plugin_data = plugin.try_to_vec()?;
let plugin_size = plugin_data.len();

// You cannot add a duplicate plugin.
if plugin_registry
.registry
.iter_mut()
Expand Down
6 changes: 3 additions & 3 deletions programs/mpl-core/src/processor/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub(crate) fn burn<'a>(accounts: &'a [AccountInfo<'a>], args: BurnArgs) -> Progr
fetch_core_data::<Collection>(collection_info)
.map(|(_, _, registry)| {
registry.map(|r| {
r.check_burn(Key::Collection, &mut checks);
r.check_registry(Key::Collection, PluginType::check_burn, &mut checks);
r
})
})
Expand All @@ -72,7 +72,7 @@ pub(crate) fn burn<'a>(accounts: &'a [AccountInfo<'a>], args: BurnArgs) -> Progr
// Next check the asset plugins. Plugins on the asset override the collection plugins,
// so we don't need to validate the collection plugins if the asset has a plugin.
if let Some(registry) = plugin_registry.as_ref() {
registry.check_burn(Key::Asset, &mut checks);
registry.check_registry(Key::Asset, PluginType::check_burn, &mut checks);
}

solana_program::msg!("checks: {:#?}", checks);
Expand Down Expand Up @@ -167,7 +167,7 @@ pub(crate) fn burn_collection<'a>(
if let Some(plugin_registry) = plugin_registry {
for record in plugin_registry.registry {
if matches!(
record.plugin_type.check_transfer(),
PluginType::check_burn(&record.plugin_type),
CheckResult::CanApprove | CheckResult::CanReject
) {
let result = Plugin::validate_burn(
Expand Down
4 changes: 2 additions & 2 deletions programs/mpl-core/src/processor/compress.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::CompressAccounts,
plugins::{CheckResult, Plugin, RegistryRecord, ValidationResult},
plugins::{CheckResult, Plugin, PluginType, RegistryRecord, ValidationResult},
state::{Asset, Compressible, HashablePluginSchema, HashedAsset, HashedAssetSchema, Key},
utils::{fetch_core_data, load_key, resize_or_reallocate_account},
};
Expand Down Expand Up @@ -52,7 +52,7 @@ pub(crate) fn compress<'a>(accounts: &'a [AccountInfo<'a>], args: CompressArgs)
if let Some(plugin_registry) = &plugin_registry {
for record in &plugin_registry.registry {
if matches!(
record.plugin_type.check_compress(),
PluginType::check_compress(&record.plugin_type),
CheckResult::CanApprove | CheckResult::CanReject
) {
let result = Plugin::validate_compress(
Expand Down
7 changes: 5 additions & 2 deletions programs/mpl-core/src/processor/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use solana_program::{
use crate::{
error::MplCoreError,
instruction::accounts::CreateAccounts,
plugins::{create_meta_idempotent, initialize_plugin, CheckResult, Plugin, ValidationResult},
plugins::{
create_meta_idempotent, initialize_plugin, CheckResult, Plugin, PluginType,
ValidationResult,
},
state::{Asset, Compressible, DataState, HashedAsset, Key, UpdateAuthority, COLLECT_AMOUNT},
utils::fetch_core_data,
};
Expand Down Expand Up @@ -133,7 +136,7 @@ pub(crate) fn create<'a>(accounts: &'a [AccountInfo<'a>], args: CreateArgs) -> P
if let Some(plugin_registry) = plugin_registry {
for record in plugin_registry.registry {
if matches!(
record.plugin_type.check_create(),
PluginType::check_create(&record.plugin_type),
CheckResult::CanApprove | CheckResult::CanReject
) {
let result = Plugin::validate_create(
Expand Down
7 changes: 5 additions & 2 deletions programs/mpl-core/src/processor/decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use solana_program::{
use crate::{
error::MplCoreError,
instruction::accounts::DecompressAccounts,
plugins::{create_meta_idempotent, initialize_plugin, CheckResult, Plugin, ValidationResult},
plugins::{
create_meta_idempotent, initialize_plugin, CheckResult, Plugin, PluginType,
ValidationResult,
},
state::{Asset, CompressionProof, Key},
utils::{fetch_core_data, load_key, resize_or_reallocate_account, verify_proof},
};
Expand Down Expand Up @@ -92,7 +95,7 @@ pub(crate) fn decompress<'a>(
if let Some(plugin_registry) = plugin_registry {
for record in plugin_registry.registry {
if matches!(
record.plugin_type.check_decompress(),
PluginType::check_decompress(&record.plugin_type),
CheckResult::CanApprove | CheckResult::CanReject
) {
let result = Plugin::validate_decompress(
Expand Down
4 changes: 2 additions & 2 deletions programs/mpl-core/src/processor/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub(crate) fn transfer<'a>(accounts: &'a [AccountInfo<'a>], args: TransferArgs)
if let Some(collection_info) = ctx.accounts.collection {
fetch_core_data::<Collection>(collection_info).map(|(_, _, registry)| {
registry.map(|r| {
r.check_transfer(Key::Collection, &mut checks);
r.check_registry(Key::Collection, PluginType::check_transfer, &mut checks);
r
})
})?;
Expand All @@ -79,7 +79,7 @@ pub(crate) fn transfer<'a>(accounts: &'a [AccountInfo<'a>], args: TransferArgs)
// Next check the asset plugins. Plugins on the asset override the collection plugins,
// so we don't need to validate the collection plugins if the asset has a plugin.
if let Some(registry) = plugin_registry.as_ref() {
registry.check_transfer(Key::Asset, &mut checks);
registry.check_registry(Key::Asset, PluginType::check_transfer, &mut checks);
}

solana_program::msg!("checks: {:#?}", checks);
Expand Down
6 changes: 3 additions & 3 deletions programs/mpl-core/src/processor/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) fn update<'a>(accounts: &'a [AccountInfo<'a>], args: UpdateArgs) -> P
if let Some(collection_info) = ctx.accounts.collection {
fetch_core_data::<Collection>(collection_info).map(|(_, _, registry)| {
registry.map(|r| {
r.check_transfer(Key::Collection, &mut checks);
r.check_registry(Key::Collection, PluginType::check_update, &mut checks);
r
})
})?;
Expand All @@ -62,7 +62,7 @@ pub(crate) fn update<'a>(accounts: &'a [AccountInfo<'a>], args: UpdateArgs) -> P
// Next check the asset plugins. Plugins on the asset override the collection plugins,
// so we don't need to validate the collection plugins if the asset has a plugin.
if let Some(registry) = plugin_registry.as_ref() {
registry.check_update(Key::Asset, &mut checks);
registry.check_registry(Key::Asset, PluginType::check_update, &mut checks);
}

solana_program::msg!("checks: {:#?}", checks);
Expand Down Expand Up @@ -239,7 +239,7 @@ pub(crate) fn update_collection<'a>(
if let Some(plugin_registry) = plugin_registry.clone() {
for record in plugin_registry.registry {
if matches!(
record.plugin_type.check_transfer(),
PluginType::check_transfer(&record.plugin_type),
CheckResult::CanApprove | CheckResult::CanReject
) {
let result = Plugin::validate_update(
Expand Down

0 comments on commit adf6255

Please sign in to comment.