From 43e5f4c6651af7c68e9850a75b94b76f8ec5c7bb Mon Sep 17 00:00:00 2001 From: Michael Danenberg <56533526+danenbm@users.noreply.github.com> Date: Sun, 14 Jul 2024 21:43:52 -0700 Subject: [PATCH] Use external plugin adapter authority to validate --- .../src/plugins/external_plugin_adapters.rs | 48 +++++++++++++++++++ .../update_external_plugin_adapter.rs | 35 +++++++++++--- programs/mpl-core/src/state/asset.rs | 8 +--- programs/mpl-core/src/state/collection.rs | 8 +--- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/programs/mpl-core/src/plugins/external_plugin_adapters.rs b/programs/mpl-core/src/plugins/external_plugin_adapters.rs index ceb25fb4..d4ba7828 100644 --- a/programs/mpl-core/src/plugins/external_plugin_adapters.rs +++ b/programs/mpl-core/src/plugins/external_plugin_adapters.rs @@ -7,6 +7,7 @@ use strum::EnumCount; use crate::{ error::MplCoreError, + plugins::lifecycle::{approve, reject}, state::{AssetV1, SolanaAccount}, }; @@ -198,6 +199,53 @@ impl ExternalPluginAdapter { } } + /// Validate the add external plugin adapter lifecycle event. + pub(crate) fn validate_update_external_plugin_adapter( + external_plugin_adapter: &ExternalPluginAdapter, + ctx: &PluginValidationContext, + ) -> Result { + let resolved_authorities = ctx + .resolved_authorities + .ok_or(MplCoreError::InvalidAuthority)?; + let base_result = if resolved_authorities.contains(ctx.self_authority) { + solana_program::msg!("Base: Approved"); + ValidationResult::Approved + } else { + ValidationResult::Pass + }; + + let result = match external_plugin_adapter { + ExternalPluginAdapter::LifecycleHook(lifecycle_hook) => { + lifecycle_hook.validate_update_external_plugin_adapter(ctx) + } + ExternalPluginAdapter::Oracle(oracle) => { + oracle.validate_update_external_plugin_adapter(ctx) + } + ExternalPluginAdapter::DataStore(app_data) => { + app_data.validate_update_external_plugin_adapter(ctx) + } + }?; + + match (&base_result, &result) { + (ValidationResult::Approved, ValidationResult::Approved) => { + approve!() + } + (ValidationResult::Approved, ValidationResult::Rejected) => { + reject!() + } + (ValidationResult::Rejected, ValidationResult::Approved) => { + reject!() + } + (ValidationResult::Rejected, ValidationResult::Rejected) => { + reject!() + } + (ValidationResult::Pass, _) => Ok(result), + (ValidationResult::ForceApproved, _) => unreachable!(), + (_, ValidationResult::Pass) => Ok(base_result), + (_, ValidationResult::ForceApproved) => unreachable!(), + } + } + /// Load and deserialize a plugin from an offset in the account. pub fn load(account: &AccountInfo, offset: usize) -> Result { let mut bytes: &[u8] = &(*account.data).borrow()[offset..]; diff --git a/programs/mpl-core/src/processor/update_external_plugin_adapter.rs b/programs/mpl-core/src/processor/update_external_plugin_adapter.rs index 3cafc18f..8610daf3 100644 --- a/programs/mpl-core/src/processor/update_external_plugin_adapter.rs +++ b/programs/mpl-core/src/processor/update_external_plugin_adapter.rs @@ -12,12 +12,12 @@ use crate::{ plugins::{ fetch_wrapped_external_plugin_adapter, find_external_plugin_adapter, ExternalPluginAdapter, ExternalPluginAdapterKey, ExternalPluginAdapterUpdateInfo, Plugin, PluginHeaderV1, - PluginRegistryV1, PluginType, + PluginRegistryV1, PluginType, PluginValidationContext, ValidationResult, }, state::{AssetV1, CollectionV1, DataBlob, Key, SolanaAccount}, utils::{ - load_key, resize_or_reallocate_account, resolve_authority, validate_asset_permissions, - validate_collection_permissions, + fetch_core_data, load_key, resize_or_reallocate_account, resolve_authority, + resolve_pubkey_to_authorities, validate_asset_permissions, validate_collection_permissions, }, }; @@ -56,9 +56,32 @@ pub(crate) fn update_external_plugin_adapter<'a>( return Err(MplCoreError::NotAvailable.into()); } - let (_, plugin) = + let (deserialized_asset, _plugin_header, _plugin_registry) = + fetch_core_data::(ctx.accounts.asset)?; + let resolved_authorities = + resolve_pubkey_to_authorities(authority, ctx.accounts.collection, &deserialized_asset)?; + let (external_registry_record_authority, external_plugin_adapter) = fetch_wrapped_external_plugin_adapter::(ctx.accounts.asset, None, &args.key)?; + let validation_ctx = PluginValidationContext { + accounts, + asset_info: Some(ctx.accounts.asset), + collection_info: ctx.accounts.collection, + self_authority: &external_registry_record_authority, + authority_info: authority, + resolved_authorities: Some(&resolved_authorities), + new_owner: None, + target_plugin: None, + }; + + if ExternalPluginAdapter::validate_update_external_plugin_adapter( + &external_plugin_adapter, + &validation_ctx, + )? == ValidationResult::Rejected + { + return Err(MplCoreError::InvalidAuthority.into()); + } + let (mut asset, plugin_header, plugin_registry) = validate_asset_permissions( accounts, authority, @@ -66,7 +89,7 @@ pub(crate) fn update_external_plugin_adapter<'a>( ctx.accounts.collection, None, None, - Some(&plugin), + Some(&external_plugin_adapter), AssetV1::check_update_external_plugin_adapter, CollectionV1::check_update_external_plugin_adapter, PluginType::check_update_external_plugin_adapter, @@ -82,7 +105,7 @@ pub(crate) fn update_external_plugin_adapter<'a>( process_update_external_plugin_adapter( asset, - plugin, + external_plugin_adapter, args.key, args.update_info, plugin_header, diff --git a/programs/mpl-core/src/state/asset.rs b/programs/mpl-core/src/state/asset.rs index 44655511..868ea55f 100644 --- a/programs/mpl-core/src/state/asset.rs +++ b/programs/mpl-core/src/state/asset.rs @@ -125,7 +125,7 @@ impl AssetV1 { /// Check permissions for the update external plugin adapter lifecycle event. pub fn check_update_external_plugin_adapter() -> CheckResult { - CheckResult::CanApprove + CheckResult::None } /// Validate the add plugin lifecycle event. @@ -332,11 +332,7 @@ impl AssetV1 { _: Option<&Plugin>, _plugin: Option<&ExternalPluginAdapter>, ) -> Result { - if self.update_authority == UpdateAuthority::Address(*authority_info.key) { - approve!() - } else { - abstain!() - } + abstain!() } } diff --git a/programs/mpl-core/src/state/collection.rs b/programs/mpl-core/src/state/collection.rs index c4056576..7a605fb3 100644 --- a/programs/mpl-core/src/state/collection.rs +++ b/programs/mpl-core/src/state/collection.rs @@ -110,7 +110,7 @@ impl CollectionV1 { /// Check permissions for the update external plugin adapter lifecycle event. pub fn check_update_external_plugin_adapter() -> CheckResult { - CheckResult::CanApprove + CheckResult::None } /// Validate the add plugin lifecycle event. @@ -297,11 +297,7 @@ impl CollectionV1 { _: Option<&Plugin>, _plugin: Option<&ExternalPluginAdapter>, ) -> Result { - if self.update_authority == *authority_info.key { - approve!() - } else { - abstain!() - } + abstain!() } /// Increment size of the Collection