From 0525cff3d14cd946017eb39f290851b4658f5172 Mon Sep 17 00:00:00 2001 From: blockiosaurus Date: Thu, 7 Mar 2024 13:42:17 -0500 Subject: [PATCH] Switching to function pointers for checks. --- programs/mpl-core/src/plugins/lifecycle.rs | 97 +++---------------- .../mpl-core/src/plugins/plugin_registry.rs | 77 +-------------- programs/mpl-core/src/plugins/utils.rs | 1 + programs/mpl-core/src/processor/burn.rs | 6 +- programs/mpl-core/src/processor/compress.rs | 4 +- programs/mpl-core/src/processor/create.rs | 7 +- programs/mpl-core/src/processor/decompress.rs | 7 +- programs/mpl-core/src/processor/transfer.rs | 4 +- programs/mpl-core/src/processor/update.rs | 6 +- 9 files changed, 37 insertions(+), 172 deletions(-) diff --git a/programs/mpl-core/src/plugins/lifecycle.rs b/programs/mpl-core/src/plugins/lifecycle.rs index 1231db4e..2c1fbbb1 100644 --- a/programs/mpl-core/src/plugins/lifecycle.rs +++ b/programs/mpl-core/src/plugins/lifecycle.rs @@ -27,25 +27,24 @@ 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, @@ -53,8 +52,8 @@ impl PluginType { } /// 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, @@ -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, } } @@ -417,75 +416,3 @@ where } Ok(false) } - -// pub(crate) fn validate_transfer_plugin_checks<'a>( -// key: Key, -// checks: &BTreeMap, -// authority: &AccountInfo<'a>, -// new_owner: &AccountInfo<'a>, -// asset: &AccountInfo<'a>, -// collection: Option<&AccountInfo<'a>>, -// ) -> Result { -// 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, -// ®istry_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, -// authority: &AccountInfo<'a>, -// asset: &AccountInfo<'a>, -// collection: Option<&AccountInfo<'a>>, -// ) -> Result { -// 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, ®istry_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) -// } diff --git a/programs/mpl-core/src/plugins/plugin_registry.rs b/programs/mpl-core/src/plugins/plugin_registry.rs index 7da940a3..2a61022c 100644 --- a/programs/mpl-core/src/plugins/plugin_registry.rs +++ b/programs/mpl-core/src/plugins/plugin_registry.rs @@ -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, ) { 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, - ) { - 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, - ) { - 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, - ) { - 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, - ) { - 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, - ) { - 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()), ); } } diff --git a/programs/mpl-core/src/plugins/utils.rs b/programs/mpl-core/src/plugins/utils.rs index 90801d58..50b223a9 100644 --- a/programs/mpl-core/src/plugins/utils.rs +++ b/programs/mpl-core/src/plugins/utils.rs @@ -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() diff --git a/programs/mpl-core/src/processor/burn.rs b/programs/mpl-core/src/processor/burn.rs index b2216d35..d6cf6624 100644 --- a/programs/mpl-core/src/processor/burn.rs +++ b/programs/mpl-core/src/processor/burn.rs @@ -62,7 +62,7 @@ pub(crate) fn burn<'a>(accounts: &'a [AccountInfo<'a>], args: BurnArgs) -> Progr fetch_core_data::(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 }) }) @@ -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); @@ -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( diff --git a/programs/mpl-core/src/processor/compress.rs b/programs/mpl-core/src/processor/compress.rs index 7ae2c1b4..5a0145f7 100644 --- a/programs/mpl-core/src/processor/compress.rs +++ b/programs/mpl-core/src/processor/compress.rs @@ -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}, }; @@ -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( diff --git a/programs/mpl-core/src/processor/create.rs b/programs/mpl-core/src/processor/create.rs index 84c8ee54..7d91ba44 100644 --- a/programs/mpl-core/src/processor/create.rs +++ b/programs/mpl-core/src/processor/create.rs @@ -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, }; @@ -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( diff --git a/programs/mpl-core/src/processor/decompress.rs b/programs/mpl-core/src/processor/decompress.rs index a2e48259..4bafe3d3 100644 --- a/programs/mpl-core/src/processor/decompress.rs +++ b/programs/mpl-core/src/processor/decompress.rs @@ -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}, }; @@ -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( diff --git a/programs/mpl-core/src/processor/transfer.rs b/programs/mpl-core/src/processor/transfer.rs index 7bf6077a..01191f21 100644 --- a/programs/mpl-core/src/processor/transfer.rs +++ b/programs/mpl-core/src/processor/transfer.rs @@ -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_info).map(|(_, _, registry)| { registry.map(|r| { - r.check_transfer(Key::Collection, &mut checks); + r.check_registry(Key::Collection, PluginType::check_transfer, &mut checks); r }) })?; @@ -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); diff --git a/programs/mpl-core/src/processor/update.rs b/programs/mpl-core/src/processor/update.rs index 56be20b4..b3b7c6f1 100644 --- a/programs/mpl-core/src/processor/update.rs +++ b/programs/mpl-core/src/processor/update.rs @@ -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_info).map(|(_, _, registry)| { registry.map(|r| { - r.check_transfer(Key::Collection, &mut checks); + r.check_registry(Key::Collection, PluginType::check_update, &mut checks); r }) })?; @@ -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); @@ -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(