From 0c6873701c35f3c87d7323c1938c21122e75b2c4 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Fri, 20 Feb 2026 09:37:54 +0530 Subject: [PATCH 01/10] feat: Add ScheduleCommitFinalize along with CommitFinalizeTask --- Cargo.lock | 4 +- .../src/intent_executor/mod.rs | 3 + .../src/persist/commit_persister.rs | 14 + magicblock-committor-service/src/tasks/mod.rs | 9 + .../src/tasks/task_builder.rs | 138 ++++++--- magicblock-committor-service/src/types.rs | 42 +++ .../src/magic_scheduled_base_intent.rs | 178 ++++++++++- .../magicblock/src/magicblock_processor.rs | 13 +- .../src/schedule_transactions/mod.rs | 2 + .../process_schedule_commit_finalize.rs | 281 ++++++++++++++++++ test-integration/Cargo.lock | 19 +- .../schedulecommit-security/src/lib.rs | 5 +- .../programs/schedulecommit/src/api.rs | 40 +-- .../programs/schedulecommit/src/lib.rs | 93 ++++-- test-integration/schedulecommit/elfs/dlp.so | Bin 424360 -> 451128 bytes .../test-scenarios/tests/01_commits.rs | 14 +- .../tests/02_commit_and_undelegate.rs | 61 +++- .../test-scenarios/tests/utils/mod.rs | 39 +++ .../test-security/tests/01_invocations.rs | 6 +- .../tests/test_ix_commit_local.rs | 227 +++++++++++--- .../tests/utils/transactions.rs | 4 +- 21 files changed, 1014 insertions(+), 178 deletions(-) create mode 100644 magicblock-committor-service/src/types.rs create mode 100644 programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs diff --git a/Cargo.lock b/Cargo.lock index 54a109648..b2f54f2e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4572,7 +4572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", @@ -4592,7 +4592,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "itertools 0.14.0", "log", "multimap", diff --git a/magicblock-committor-service/src/intent_executor/mod.rs b/magicblock-committor-service/src/intent_executor/mod.rs index 893a8af30..e253dbf61 100644 --- a/magicblock-committor-service/src/intent_executor/mod.rs +++ b/magicblock-committor-service/src/intent_executor/mod.rs @@ -82,6 +82,7 @@ impl metrics::LabelValue for ExecutionOutput { } } +#[derive(Debug)] pub struct IntentExecutionResult { /// Final result of Intent Execution pub inner: IntentExecutorResult, @@ -160,6 +161,8 @@ where if all_committed_pubkeys.is_empty() { // Build tasks for commit stage + // TODO (snawaz): it's actually MagicBaseIntent::BaseActions scenario, not Commit + // scenario, so the related code needs little bit of refactoring and proper renaming. let commit_tasks = TaskBuilderImpl::commit_tasks( &self.task_info_fetcher, &intent_bundle, diff --git a/magicblock-committor-service/src/persist/commit_persister.rs b/magicblock-committor-service/src/persist/commit_persister.rs index d16a621ae..2fc1598c1 100644 --- a/magicblock-committor-service/src/persist/commit_persister.rs +++ b/magicblock-committor-service/src/persist/commit_persister.rs @@ -135,6 +135,12 @@ impl IntentPersisterImpl { [ (false, intent_bundle.get_commit_intent_accounts()), (true, intent_bundle.get_undelegate_intent_accounts()), + (false, intent_bundle.get_commit_finalize_intent_accounts()), + ( + true, + intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts(), + ), ] .into_iter() .filter_map(|(undelegate, accounts)| { @@ -493,6 +499,8 @@ mod tests { MagicIntentBundle { commit: Some(CommitType::Standalone(test_accounts())), commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -504,6 +512,8 @@ mod tests { commit_action: CommitType::Standalone(test_accounts()), undelegate_action: UndelegateType::Standalone, }), + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -515,6 +525,8 @@ mod tests { commit_action: CommitType::Standalone(test_accounts()), undelegate_action: UndelegateType::Standalone, }), + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -523,6 +535,8 @@ mod tests { MagicIntentBundle { commit: None, commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 4a9f7ea6f..5998225bb 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -29,6 +29,7 @@ use crate::tasks::commit_task::CommitTask; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum TaskType { Commit, + CommitFinalize, Finalize, Undelegate, Action, @@ -162,6 +163,14 @@ pub struct CommitDiffTask { pub base_account: Account, } +#[derive(Clone, Debug)] +pub struct CommitFinalizeTask { + pub commit_id: u64, + pub allow_undelegation: bool, + pub base_account: Option, // None implies commit-full-bytes else commit-diff + pub committed_account: CommittedAccount, +} + #[derive(Clone, Debug)] pub struct UndelegateTask { pub delegated_account: Pubkey, diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 749612d88..f67ca49e6 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -3,7 +3,8 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ - BaseAction, CommitType, ScheduledIntentBundle, UndelegateType, + BaseAction, CommitAndUndelegate, CommitType, CommittedAccount, + ScheduledIntentBundle, UndelegateType, }; use solana_account::Account; use solana_pubkey::Pubkey; @@ -17,8 +18,8 @@ use crate::{ persist::IntentPersister, tasks::{ commit_task::{CommitDelivery, CommitTask}, - BaseActionTask, BaseActionTaskV1, BaseActionTaskV2, BaseTaskImpl, - FinalizeTask, UndelegateTask, + BaseActionTask, BaseActionTaskV1, BaseActionTaskV2, BaseTask, + BaseTaskImpl, CommitFinalizeTask, FinalizeTask, UndelegateTask, }, }; @@ -97,12 +98,12 @@ impl TaskBuilderImpl { async fn fetch_commit_nonces( task_info_fetcher: &Arc, - accounts: &[(bool, CommittedAccount)], + accounts: &[(bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { let committed_pubkeys = accounts .iter() - .map(|(_, account)| account.pubkey) + .map(|(_, _, account)| account.pubkey) .collect::>(); task_info_fetcher @@ -112,26 +113,48 @@ impl TaskBuilderImpl { async fn fetch_diffable_accounts( task_info_fetcher: &Arc, - accounts: &[(bool, CommittedAccount)], + accounts: &[(bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { let diffable_pubkeys = accounts .iter() - .filter(|(_, account)| { + .filter(|(_, _, account)| { account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD }) - .map(|(_, account)| account.pubkey) + .map(|(_, _, account)| account.pubkey) .collect::>(); task_info_fetcher .get_base_accounts(&diffable_pubkeys, min_context_slot) .await } + + pub fn create_commit_finalize_task( + commit_id: u64, + allow_undelegation: bool, + account: CommittedAccount, + base_account: Option, + ) -> ArgsTask { + let base_account = + if account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD { + base_account + } else { + None + }; + + ArgsTaskType::CommitFinalize(CommitFinalizeTask { + commit_id, + allow_undelegation, + committed_account: account, + base_account, + }) + .into() + } } #[async_trait] impl TasksBuilder for TaskBuilderImpl { - /// Returns [`Task`]s for Commit stage + /// Returns []s for Commit stage async fn commit_tasks( task_info_fetcher: &Arc, intent_bundle: &ScheduledIntentBundle, @@ -146,21 +169,31 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle.get_commit_intent_accounts().cloned(); let undelegated_accounts = intent_bundle.get_undelegate_intent_accounts().cloned(); - let flagged_accounts: Vec<_> = - [(false, committed_accounts), (true, undelegated_accounts)] + let commit_finalize_accounts = + intent_bundle.get_commit_finalize_intent_accounts().cloned(); + let commit_finalize_and_undelegate_accounts = intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts() + .cloned(); + + let flagged_accounts: Vec<_> = [ + (false, false, committed_accounts), + (true, false, undelegated_accounts), + (false, true, commit_finalize_accounts), + (true, true, commit_finalize_and_undelegate_accounts), + ] + .into_iter() + .flat_map(|(allow_undelegation, finalize, accounts)| { + accounts .into_iter() - .flat_map(|(allow_undelegation, accounts)| { - accounts - .into_iter() - .flatten() - .map(move |account| (allow_undelegation, account)) - }) - .collect(); + .flatten() + .map(move |account| (allow_undelegation, finalize, account)) + }) + .collect(); // Get commit nonces and base accounts let min_context_slot = flagged_accounts .iter() - .map(|(_, account)| account.remote_slot) + .map(|(_, _, account)| account.remote_slot) .max() .unwrap_or(0); let (commit_ids, base_accounts) = tokio::join!( @@ -193,7 +226,7 @@ impl TasksBuilder for TaskBuilderImpl { // Create commit tasks let commit_tasks_iter = flagged_accounts.into_iter().map( - |(allow_undelegation, account)| { + |(allow_undelegation, finalize, account)| { let commit_id = commit_ids .get(&account.pubkey) .copied() @@ -206,17 +239,14 @@ impl TasksBuilder for TaskBuilderImpl { }); let base_account = base_accounts.remove(&account.pubkey); - Self::create_commit_task( - commit_id, - allow_undelegation, - account.clone(), - base_account, - ) - .into() + if finalize { + Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account) + } else { + Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account) + }.into() }, ); tasks.extend(commit_tasks_iter); - Ok(tasks) } @@ -247,7 +277,7 @@ impl TasksBuilder for TaskBuilderImpl { } // Helper to process commit types - fn process_commit(commit: &CommitType) -> Vec { + fn create_finalize_tasks(commit: &CommitType) -> Vec { match commit { CommitType::Standalone(accounts) => { accounts.iter().map(finalize_task).collect() @@ -268,18 +298,12 @@ impl TasksBuilder for TaskBuilderImpl { } } - let mut tasks = Vec::new(); - if let Some(ref value) = intent_bundle.intent_bundle.commit { - tasks.extend(process_commit(value)); - } - - if let Some(ref value) = - intent_bundle.intent_bundle.commit_and_undelegate - { - tasks.extend(process_commit(&value.commit_action)); - + async fn create_undelegate_tasks( + commit_and_undelegate: &CommitAndUndelegate, + info_fetcher: &Arc, + ) -> TaskBuilderResult>> { // Get rent reimbursments for undelegated accounts - let accounts = value.get_committed_accounts(); + let accounts = commit_and_undelegate.get_committed_accounts(); let mut min_context_slot = 0; let pubkeys = accounts .iter() @@ -294,17 +318,39 @@ impl TasksBuilder for TaskBuilderImpl { .await .map_err(TaskBuilderError::FinalizedTasksBuildError)?; - tasks.extend(accounts.iter().zip(rent_reimbursements).map( - |(account, rent_reimbursement)| { + let mut tasks = accounts + .iter() + .zip(rent_reimbursements) + .map(|(account, rent_reimbursement)| { undelegate_task(account, &rent_reimbursement) - }, - )); + }) + .collect::>(); if let UndelegateType::WithBaseActions(actions) = - &value.undelegate_action + &commit_and_undelegate.undelegate_action { - tasks.extend(Self::create_action_tasks(actions)); + tasks.extend(TaskBuilderImpl::create_action_tasks(actions)); } + Ok(tasks) + } + + let mut tasks = Vec::new(); + + if let Some(ref value) = intent_bundle.intent_bundle.commit { + tasks.extend(create_finalize_tasks(value)); + } + + if let Some(ref value) = + intent_bundle.intent_bundle.commit_and_undelegate + { + tasks.extend(create_finalize_tasks(&value.commit_action)); + tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); + }; + + if let Some(ref value) = + intent_bundle.intent_bundle.commit_finalize_and_undelegate + { + tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); }; Ok(tasks) diff --git a/magicblock-committor-service/src/types.rs b/magicblock-committor-service/src/types.rs new file mode 100644 index 000000000..4a72a2242 --- /dev/null +++ b/magicblock-committor-service/src/types.rs @@ -0,0 +1,42 @@ +use std::ops::Deref; + +use magicblock_metrics::metrics; +use magicblock_program::magic_scheduled_base_intent::{ + MagicBaseIntent, ScheduledBaseIntent, +}; + +// TODO: should be removed once cranks are supported +// Ideally even now OffChain/"Manual" commits should be triggered via Tx +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TriggerType { + OnChain, + OffChain, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ScheduledBaseIntentWrapper { + pub inner: ScheduledBaseIntent, + pub trigger_type: TriggerType, +} + +impl metrics::LabelValue for ScheduledBaseIntentWrapper { + fn value(&self) -> &str { + match &self.inner.base_intent { + MagicBaseIntent::BaseActions(_) => "actions", + MagicBaseIntent::Commit(_) => "commit", + MagicBaseIntent::CommitAndUndelegate(_) => "commit_and_undelegate", + MagicBaseIntent::CommitFinalize(_) => "commit_finalize", + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => { + "commit_finalize_and_undelegate" + } + } + } +} + +impl Deref for ScheduledBaseIntentWrapper { + type Target = ScheduledBaseIntent; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index e6c686659..6e685adec 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -146,6 +146,21 @@ impl ScheduledIntentBundle { self.intent_bundle.get_commit_intent_accounts() } + /// Returns `[CommitFinalizeAndUndelegate]` intent's accounts + pub fn get_commit_finalize_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts() + } + + /// Returns `CommitFinalize` intent's accounts + pub fn get_commit_finalize_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle.get_commit_finalize_intent_accounts() + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -181,6 +196,8 @@ pub enum MagicBaseIntent { BaseActions(Vec), Commit(CommitType), CommitAndUndelegate(CommitAndUndelegate), + CommitFinalize(CommitType), + CommitFinalizeAndUndelegate(CommitAndUndelegate), } // Bundle of BaseIntents @@ -188,6 +205,8 @@ pub enum MagicBaseIntent { pub struct MagicIntentBundle { pub commit: Option, pub commit_and_undelegate: Option, + pub commit_finalize: Option, + pub commit_finalize_and_undelegate: Option, pub standalone_actions: Vec, } @@ -202,6 +221,12 @@ impl From for MagicIntentBundle { MagicBaseIntent::CommitAndUndelegate(value) => { this.commit_and_undelegate = Some(value) } + MagicBaseIntent::CommitFinalize(value) => { + this.commit_finalize = Some(value) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(value) => { + this.commit_finalize_and_undelegate = Some(value) + } } this @@ -219,10 +244,22 @@ impl MagicIntentBundle { .commit .map(|value| CommitType::try_from_args(value, context)) .transpose()?; + let commit_and_undelegate = args .commit_and_undelegate .map(|value| CommitAndUndelegate::try_from_args(value, context)) .transpose()?; + + let commit_finalize = args + .commit_finalize + .map(|value| CommitType::try_from_args(value, context)) + .transpose()?; + + let commit_finalize_and_undelegate = args + .commit_finalize_and_undelegate + .map(|value| CommitAndUndelegate::try_from_args(value, context)) + .transpose()?; + let actions = args .standalone_actions .into_iter() @@ -232,6 +269,8 @@ impl MagicIntentBundle { let this = Self { commit, commit_and_undelegate, + commit_finalize, + commit_finalize_and_undelegate, standalone_actions: actions, }; this.post_validation(context)?; @@ -312,6 +351,14 @@ impl MagicIntentBundle { if let Some(cau) = &self.commit_and_undelegate { check(cau.get_committed_accounts())?; } + if let Some(commit_finalize) = &self.commit_finalize { + check(commit_finalize.get_committed_accounts())?; + } + if let Some(commit_finalize_and_undelegate) = + &self.commit_finalize_and_undelegate + { + check(commit_finalize_and_undelegate.get_committed_accounts())?; + } Ok(()) } @@ -333,6 +380,10 @@ impl MagicIntentBundle { pub fn has_undelegate_intent(&self) -> bool { self.commit_and_undelegate.is_some() + + // TODO (snawaz): we need to add this as well? + // || + // self.commit_finalize_and_undelegate.is_some() } pub fn has_committed_accounts(&self) -> bool { @@ -344,8 +395,19 @@ impl MagicIntentBundle { .get_undelegate_intent_accounts() .map(|el| !el.is_empty()) .unwrap_or(false); + let has_commit_finalize_intent_accounts = self + .get_commit_finalize_intent_accounts() + .map(|el| !el.is_empty()) + .unwrap_or(false); + let has_commit_finalize_and_undelegate_intent_accounts = self + .get_commit_finalize_and_undelegate_intent_accounts() + .map(|el| !el.is_empty()) + .unwrap_or(false); - has_commit_intent_accounts || has_undelegate_intent_accounts + has_commit_intent_accounts + || has_undelegate_intent_accounts + || has_commit_finalize_intent_accounts + || has_commit_finalize_and_undelegate_intent_accounts } /// Returns `[CommitAndUndelegate]` intent's accounts @@ -364,6 +426,24 @@ impl MagicIntentBundle { Some(self.commit.as_ref()?.get_committed_accounts()) } + /// Returns `[CommitAndUndelegate]` intent's accounts + pub fn get_commit_finalize_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + Some( + self.commit_finalize_and_undelegate + .as_ref()? + .get_committed_accounts(), + ) + } + + /// Returns `Commit` intent's accounts + pub fn get_commit_finalize_intent_accounts( + &self, + ) -> Option<&Vec> { + Some(self.commit_finalize.as_ref()?.get_committed_accounts()) + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -376,18 +456,29 @@ impl MagicIntentBundle { pub fn get_all_committed_accounts(&self) -> Vec { let committed = self.get_commit_intent_accounts(); let undelegated = self.get_undelegate_intent_accounts(); - [committed, undelegated] - .into_iter() - .flatten() - .flatten() - .cloned() - .collect() + let commit_finalize = self.get_commit_finalize_intent_accounts(); + let commit_finalize_and_undelegate = + self.get_commit_finalize_and_undelegate_intent_accounts(); + + [ + committed, + undelegated, + commit_finalize, + commit_finalize_and_undelegate, + ] + .into_iter() + .flatten() + .flatten() + .cloned() + .collect() } pub fn get_all_committed_pubkeys(&self) -> Vec { [ self.get_commit_intent_pubkeys(), self.get_undelegate_intent_pubkeys(), + self.get_commit_finalize_intent_pubkeys(), + self.get_commit_finalize_and_undelegate_intent_pubkeys(), ] .into_iter() .flatten() @@ -407,17 +498,49 @@ impl MagicIntentBundle { .map(|value| value.get_committed_pubkeys()) } + pub fn get_commit_finalize_intent_pubkeys(&self) -> Option> { + self.commit_finalize + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + + pub fn get_commit_finalize_and_undelegate_intent_pubkeys( + &self, + ) -> Option> { + self.commit_finalize_and_undelegate + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + pub fn is_empty(&self) -> bool { let no_committed = self.commit.as_ref().map(|el| el.is_empty()).unwrap_or(true); + let no_committed_and_undelegated = self .commit_and_undelegate .as_ref() .map(|el| el.is_empty()) .unwrap_or(true); + + let no_commit_finalize = self + .commit_finalize + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); + + let no_commit_finalize_and_undelegate = self + .commit_finalize_and_undelegate + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); + let no_actions = self.standalone_actions.is_empty(); - no_committed && no_committed_and_undelegated && no_actions + no_committed + && no_committed_and_undelegated + && no_commit_finalize + && no_commit_finalize_and_undelegate + && no_actions } } @@ -443,8 +566,17 @@ impl MagicBaseIntent { CommitAndUndelegate::try_from_args(type_, context)?; Ok(MagicBaseIntent::CommitAndUndelegate(commit_and_undelegate)) } - MagicBaseIntentArgs::CommitFinalize(_) => todo!(), - MagicBaseIntentArgs::CommitFinalizeAndUndelegate(_) => todo!(), + MagicBaseIntentArgs::CommitFinalize(type_) => { + let commit = CommitType::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalize(commit)) + } + MagicBaseIntentArgs::CommitFinalizeAndUndelegate(type_) => { + let commit_and_undelegate = + CommitAndUndelegate::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalizeAndUndelegate( + commit_and_undelegate, + )) + } } } @@ -453,6 +585,18 @@ impl MagicBaseIntent { MagicBaseIntent::BaseActions(_) => false, MagicBaseIntent::Commit(_) => false, MagicBaseIntent::CommitAndUndelegate(_) => true, + MagicBaseIntent::CommitFinalize(_) => false, + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, + } + } + + pub fn is_commit_finalize(&self) -> bool { + match &self { + MagicBaseIntent::BaseActions(_) => false, + MagicBaseIntent::Commit(_) => false, + MagicBaseIntent::CommitAndUndelegate(_) => false, + MagicBaseIntent::CommitFinalize(_) => true, + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, } } @@ -463,6 +607,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(t) => { Some(t.get_committed_accounts()) } + MagicBaseIntent::CommitFinalize(t) => { + Some(t.get_committed_accounts()) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { + Some(t.get_committed_accounts()) + } } } @@ -475,6 +625,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(t) => { Some(t.get_committed_accounts_mut()) } + MagicBaseIntent::CommitFinalize(t) => { + Some(t.get_committed_accounts_mut()) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { + Some(t.get_committed_accounts_mut()) + } } } @@ -489,6 +645,8 @@ impl MagicBaseIntent { MagicBaseIntent::BaseActions(actions) => actions.is_empty(), MagicBaseIntent::Commit(t) => t.is_empty(), MagicBaseIntent::CommitAndUndelegate(t) => t.is_empty(), + MagicBaseIntent::CommitFinalize(t) => t.is_empty(), + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => t.is_empty(), } } } diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index 2ad5daee6..a8d828b04 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -17,7 +17,8 @@ use crate::{ schedule_task::{process_cancel_task, process_schedule_task}, schedule_transactions::{ process_accept_scheduled_commits, process_schedule_commit, - process_schedule_intent_bundle, ProcessScheduleCommitOptions, + process_schedule_commit_finalize, process_schedule_intent_bundle, + ProcessScheduleCommitOptions, }, toggle_executable_check::process_toggle_executable_check, }; @@ -70,8 +71,14 @@ declare_process_instruction!( }, ), ScheduleCommitFinalize { - request_undelegation: _, - } => todo!(), + request_undelegation, + } => process_schedule_commit_finalize( + signers, + invoke_context, + ProcessScheduleCommitOptions { + request_undelegation, + }, + ), AcceptScheduleCommits => { process_accept_scheduled_commits(signers, invoke_context) } diff --git a/programs/magicblock/src/schedule_transactions/mod.rs b/programs/magicblock/src/schedule_transactions/mod.rs index 7550e01b6..05c886ba3 100644 --- a/programs/magicblock/src/schedule_transactions/mod.rs +++ b/programs/magicblock/src/schedule_transactions/mod.rs @@ -1,5 +1,6 @@ mod process_accept_scheduled_commits; mod process_schedule_commit; +mod process_schedule_commit_finalize; #[cfg(test)] mod process_schedule_commit_tests; mod process_schedule_intent_bundle; @@ -12,6 +13,7 @@ use magicblock_core::intent::CommittedAccount; use magicblock_magic_program_api::MAGIC_CONTEXT_PUBKEY; pub(crate) use process_accept_scheduled_commits::*; pub(crate) use process_schedule_commit::*; +pub(crate) use process_schedule_commit_finalize::*; pub(crate) use process_schedule_intent_bundle::process_schedule_intent_bundle; pub use process_scheduled_commit_sent::{ process_scheduled_commit_sent, register_scheduled_commit_sent, SentCommit, diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs new file mode 100644 index 000000000..832cf63e3 --- /dev/null +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -0,0 +1,281 @@ +use std::collections::HashSet; + +// no direct token remap helpers needed here; handled in CommittedAccount builder +use solana_account::{state_traits::StateMut, ReadableAccount}; +use solana_instruction::error::InstructionError; +use solana_log_collector::ic_msg; +use solana_program_runtime::invoke_context::InvokeContext; +use solana_pubkey::Pubkey; + +use crate::{ + magic_scheduled_base_intent::{ + validate_commit_schedule_permissions, CommitAndUndelegate, CommitType, + CommittedAccount, MagicBaseIntent, ScheduledIntentBundle, + UndelegateType, + }, + schedule_transactions::{self, ProcessScheduleCommitOptions}, + utils::{ + account_actions::mark_account_as_undelegated, + accounts::{ + get_instruction_account_with_idx, get_instruction_pubkey_with_idx, + get_writable_with_idx, + }, + instruction_utils::InstructionUtils, + }, + MagicContext, +}; + +pub(crate) fn process_schedule_commit_finalize( + signers: HashSet, + invoke_context: &mut InvokeContext, + opts: ProcessScheduleCommitOptions, +) -> Result<(), InstructionError> { + const PAYER_IDX: u16 = 0; + const MAGIC_CONTEXT_IDX: u16 = PAYER_IDX + 1; + + schedule_transactions::check_magic_context_id( + invoke_context, + MAGIC_CONTEXT_IDX, + )?; + + let transaction_context = &invoke_context.transaction_context.clone(); + let ix_ctx = transaction_context.get_current_instruction_context()?; + let ix_accs_len = ix_ctx.get_number_of_instruction_accounts() as usize; + const COMMITTEES_START: usize = MAGIC_CONTEXT_IDX as usize + 1; + + // Assert MagicBlock program + ix_ctx + .find_index_of_program_account(transaction_context, &crate::id()) + .ok_or_else(|| { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: Magic program account not found" + ); + InstructionError::UnsupportedProgramId + })?; + + // Assert enough accounts + if ix_accs_len <= COMMITTEES_START { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: not enough accounts to schedule commit ({}), need payer, signing program an account for each pubkey to be committed", + ix_accs_len + ); + return Err(InstructionError::NotEnoughAccountKeys); + } + + // Assert Payer is signer + let payer_pubkey = + get_instruction_pubkey_with_idx(transaction_context, PAYER_IDX)?; + if !signers.contains(payer_pubkey) { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: payer pubkey {} not in signers", + payer_pubkey + ); + return Err(InstructionError::MissingRequiredSignature); + } + + // + // Get the program_id of the parent instruction that invoked this one via CPI + // + + // We cannot easily simulate the transaction being invoked via CPI + // from the owning program during unit tests + // Instead the integration tests ensure that this works as expected + #[cfg(not(test))] + let frames = crate::utils::instruction_context_frames::InstructionContextFrames::try_from(transaction_context)?; + + // During unit tests we assume the first committee has the correct program ID + #[cfg(test)] + let first_committee_owner = { + *get_instruction_account_with_idx( + transaction_context, + COMMITTEES_START as u16, + )? + .borrow() + .owner() + }; + + #[cfg(not(test))] + let parent_program_id = { + let parent_program_id = + frames.find_program_id_of_parent_of_current_instruction(); + + ic_msg!( + invoke_context, + "ScheduleCommit: parent program id: {}", + parent_program_id + .map_or_else(|| "None".to_string(), |id| id.to_string()) + ); + + parent_program_id + }; + + #[cfg(test)] + let parent_program_id = Some(&first_committee_owner); + + // Assert all accounts are delegated, owned by invoking program OR are signers + // Also works if the validator authority is a signer + // NOTE: we don't require PDAs to be signers as in our case verifying that the + // program owning the PDAs invoked us directly via CPI is sufficient + // Thus we can be `invoke`d unsigned and no seeds need to be provided + let mut committed_accounts: Vec = Vec::new(); + for idx in COMMITTEES_START..ix_accs_len { + let acc_pubkey = + get_instruction_pubkey_with_idx(transaction_context, idx as u16)?; + let acc = + get_instruction_account_with_idx(transaction_context, idx as u16)?; + + if acc.borrow().confined() { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is confined and cannot be committed", + acc_pubkey + ); + return Err(InstructionError::InvalidAccountData); + } + + { + let is_delegated = acc.borrow().delegated(); + + if opts.request_undelegation { + // Must be writable and delegated to avoid double-undelegation + let is_writable = + get_writable_with_idx(transaction_context, idx as u16)?; + if !is_writable || !is_delegated { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is required to be writable and delegated in order to be undelegated", + acc_pubkey + ); + return Err(InstructionError::ReadonlyDataModified); + } + } else if !is_delegated { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is required to be delegated to the current validator, in order to be committed", + acc_pubkey + ); + return Err(InstructionError::IllegalOwner); + } + + // Validate committed account was scheduled by valid authority + let acc_owner = *acc.borrow().owner(); + validate_commit_schedule_permissions( + &invoke_context, + &acc_owner, + acc_pubkey, + parent_program_id, + &signers, + )?; + + let committed = CommittedAccount::from_account_shared( + *acc_pubkey, + &acc.borrow(), + parent_program_id.cloned(), + ); + + if &committed.pubkey != acc_pubkey { + ic_msg!( + invoke_context, + "ScheduleCommit: remapping ATA {} -> eATA {}", + acc_pubkey, + committed.pubkey + ); + } + + committed_accounts.push(committed); + } + + if opts.request_undelegation { + // If the account is scheduled to be undelegated then we need to lock it + // immediately in order to prevent the following actions: + // - writes to the account + // - scheduling further commits for this account + // + // Setting the owner will prevent both, since in both cases the _actual_ + // owner program needs to sign for the account which is not possible at + // that point + // NOTE: this owner change only takes effect if the transaction which + // includes this instruction succeeds. + // + // We also set the undelegating flag on the account in order to detect + // undelegations for which we miss updates + mark_account_as_undelegated(acc); + ic_msg!( + invoke_context, + "ScheduleCommit: Marking account {} as undelegating", + acc_pubkey + ); + } + } + + // NOTE: this is only protected by all the above checks however if the + // instruction fails for other reasons detected afterward then the commit + // stays scheduled + let context_acc = get_instruction_account_with_idx( + transaction_context, + MAGIC_CONTEXT_IDX, + )?; + let context_data = &mut context_acc.borrow_mut(); + let mut context = + MagicContext::deserialize(context_data).map_err(|err| { + ic_msg!( + invoke_context, + "Failed to deserialize MagicContext: {}", + err + ); + InstructionError::GenericError + })?; + + // Get next intent id + let intent_id = context.next_intent_id(); + + // It appears that in builtin programs `Clock::get` doesn't work as expected, thus + // we have to get it directly from the sysvar cache. + let clock = + invoke_context + .get_sysvar_cache() + .get_clock() + .map_err(|err| { + ic_msg!(invoke_context, "Failed to get clock sysvar: {}", err); + InstructionError::UnsupportedSysvar + })?; + let blockhash = invoke_context.environment_config.blockhash; + let action_sent_transaction = + InstructionUtils::scheduled_commit_sent(intent_id, blockhash); + let commit_sent_sig = action_sent_transaction.signatures[0]; + + let base_intent = if opts.request_undelegation { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(committed_accounts), + undelegate_action: UndelegateType::Standalone, + }) + } else { + MagicBaseIntent::CommitFinalize(CommitType::Standalone( + committed_accounts, + )) + }; + + let scheduled_base_intent = ScheduledIntentBundle { + id: intent_id, + slot: clock.slot, + blockhash, + sent_transaction: action_sent_transaction, + payer: *payer_pubkey, + intent_bundle: base_intent.into(), + }; + + context.add_scheduled_action(scheduled_base_intent); + context_data.set_state(&context)?; + + ic_msg!(invoke_context, "Scheduled commit with ID: {}", intent_id); + ic_msg!( + invoke_context, + "ScheduledCommitSent signature: {}", + commit_sent_sig, + ); + + Ok(()) +} diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index fc999fee8..7948cd171 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3760,6 +3760,20 @@ dependencies = [ name = "magicblock-delegation-program" version = "1.1.3" source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222#293e9222c2765c5405e2dfb4139cd71b86641d59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0e25f9e37194cc27c0f1d3dbc00e83795f7f4012f1a99c20bc557bdeb62e13e" +dependencies = [ + "borsh 1.6.0", + "bytemuck", + "num_enum", + "solana-program", + "static_assertions", +] + +[[package]] +name = "magicblock-delegation-program" +version = "1.1.3" +source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer#1347f31982a57762bd9321c91a021a3d32bebe05" dependencies = [ "bincode", "borsh 1.6.0", @@ -3776,6 +3790,7 @@ dependencies = [ "solana-curve25519", "solana-instruction 3.2.0", "solana-program", + "solana-security-txt", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", @@ -5101,7 +5116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", @@ -5121,7 +5136,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", diff --git a/test-integration/programs/schedulecommit-security/src/lib.rs b/test-integration/programs/schedulecommit-security/src/lib.rs index c00ea2230..2cd34e495 100644 --- a/test-integration/programs/schedulecommit-security/src/lib.rs +++ b/test-integration/programs/schedulecommit-security/src/lib.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use ephemeral_rollups_sdk::ephem::create_schedule_commit_ix; use program_schedulecommit::{ api::schedule_commit_cpi_instruction, process_schedulecommit_cpi, - ProcessSchedulecommitCpiArgs, + ProcessSchedulecommitCpiArgs, ScheduleCommitType, }; use solana_program::{ account_info::{next_account_info, AccountInfo}, @@ -82,10 +82,10 @@ pub fn process_instruction<'a>( &players, ProcessSchedulecommitCpiArgs { modify_accounts: false, - undelegate: false, commit_payer: false, has_magic_vault: false, }, + ScheduleCommitType::Commit, ), } } @@ -126,6 +126,7 @@ fn process_sibling_schedule_cpis( None, players, &pdas, + ScheduleCommitType::Commit, ); let mut account_infos = account_infos .clone() diff --git a/test-integration/programs/schedulecommit/src/api.rs b/test-integration/programs/schedulecommit/src/api.rs index 661171dda..b88047d4c 100644 --- a/test-integration/programs/schedulecommit/src/api.rs +++ b/test-integration/programs/schedulecommit/src/api.rs @@ -14,7 +14,7 @@ use solana_program::{ use crate::{ BookUpdate, DelegateCpiArgs, DelegateOrderBookArgs, ScheduleCommitCpiArgs, ScheduleCommitCpiWithVaultArgs, ScheduleCommitInstruction, - ScheduleCommitWithOrderBookArgs, + ScheduleCommitType, ScheduleCommitWithOrderBookArgs, }; #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -185,6 +185,7 @@ pub fn schedule_commit_cpi_instruction( magic_fee_vault: Option, players: &[Pubkey], committees: &[Pubkey], + commit_type: ScheduleCommitType, ) -> Instruction { schedule_commit_cpi_instruction_impl( payer, @@ -193,10 +194,8 @@ pub fn schedule_commit_cpi_instruction( magic_fee_vault, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: false, - commit_payer: false, - }, + false, + commit_type, ) } @@ -293,11 +292,12 @@ pub fn update_order_book_instruction( ) } -pub fn schedule_commit_diff_instruction_for_order_book( +pub fn schedule_commit_instruction_for_order_book( payer: Pubkey, order_book: Pubkey, magic_program_id: Pubkey, magic_context_id: Pubkey, + commit_type: ScheduleCommitType, ) -> Instruction { let program_id = crate::id(); let account_metas = vec![ @@ -309,7 +309,7 @@ pub fn schedule_commit_diff_instruction_for_order_book( Instruction::new_with_borsh( program_id, - &ScheduleCommitInstruction::ScheduleCommitForOrderBook, + &ScheduleCommitInstruction::ScheduleCommitForOrderBook(commit_type), account_metas, ) } @@ -329,10 +329,8 @@ pub fn schedule_commit_with_payer_cpi_instruction( magic_fee_vault, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: false, - commit_payer: true, - }, + true, + ScheduleCommitType::Commit, ) } @@ -351,18 +349,11 @@ pub fn schedule_commit_and_undelegate_cpi_instruction( magic_fee_vault, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: true, - commit_payer: false, - }, + false, + ScheduleCommitType::CommitAndUndelegate, ) } -struct ScheduleCommitCpiInstructionImplArgs { - undelegate: bool, - commit_payer: bool, -} - fn schedule_commit_cpi_instruction_impl( payer: Pubkey, magic_program_id: Pubkey, @@ -370,7 +361,8 @@ fn schedule_commit_cpi_instruction_impl( magic_fee_vault: Option, players: &[Pubkey], committees: &[Pubkey], - args: ScheduleCommitCpiInstructionImplArgs, + commit_payer: bool, + commit_type: ScheduleCommitType, ) -> Instruction { let program_id = crate::id(); @@ -390,11 +382,11 @@ fn schedule_commit_cpi_instruction_impl( let cpi_args = ScheduleCommitCpiArgs { players: players.to_vec(), modify_accounts: true, - undelegate: args.undelegate, - commit_payer: args.commit_payer, has_magic_vault: magic_fee_vault.is_some(), + commit_payer, }; - let ix = ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args); + let ix = + ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args, commit_type); Instruction::new_with_borsh(program_id, &ix, account_metas) } diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 7d3545be2..cd278496c 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -7,8 +7,9 @@ use ephemeral_rollups_sdk::{ delegate_account, undelegate_account, DelegateAccounts, DelegateConfig, }, ephem::{ - commit_accounts, commit_and_undelegate_accounts, CallHandler, - MagicIntentBundleBuilder, + commit_accounts, commit_and_undelegate_accounts, + commit_finalize_accounts, commit_finalize_and_undelegate_accounts, + CallHandler, MagicIntentBundleBuilder, }, ActionArgs, ShortAccountMeta, }; @@ -70,8 +71,6 @@ pub struct ScheduleCommitCpiArgs { pub players: Vec, /// If true, the accounts will be modified after the commit pub modify_accounts: bool, - /// If true, the accounts will be undelegated after the commit - pub undelegate: bool, /// If true, also commit the payer account pub commit_payer: bool, /// If true, accounts also have magic vault passed @@ -119,7 +118,7 @@ pub enum ScheduleCommitInstruction { /// - **1** `[]` MagicContext (used to record scheduled commit) /// - **2** `[]` MagicBlock Program (used to schedule commit) /// - **3..n** `[]` PDA accounts to be committed - ScheduleCommitCpi(ScheduleCommitCpiArgs), + ScheduleCommitCpi(ScheduleCommitCpiArgs, ScheduleCommitType), /// # Account references /// - **0.** `[WRITE, SIGNER]` Payer funding the commit @@ -201,6 +200,54 @@ pub enum ScheduleCommitInstruction { /// - **4.** `[WRITE]` OrderBook account (post-commit action target) /// - **5..n** `[WRITE]` PDA accounts to be committed ScheduleCommitWithVaultAndOrderBookCpi(ScheduleCommitWithOrderBookArgs), + + ScheduleCommitForOrderBook(ScheduleCommitType), +} + +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Copy)] +pub enum ScheduleCommitType { + Commit, + CommitAndUndelegate, + CommitFinalize, + CommitFinalizeAndUndelegate, +} + +impl ScheduleCommitType { + fn invoke_commit<'a, 'info>( + self, + payer: &'a AccountInfo<'info>, + accounts: Vec<&'a AccountInfo<'info>>, + magic_context: &'a AccountInfo<'info>, + magic_program: &'a AccountInfo<'info>, + ) -> ProgramResult { + match self { + ScheduleCommitType::Commit => { + commit_accounts(payer, accounts, magic_context, magic_program) + } + ScheduleCommitType::CommitAndUndelegate => { + commit_and_undelegate_accounts( + payer, + accounts, + magic_context, + magic_program, + ) + } + ScheduleCommitType::CommitFinalize => commit_finalize_accounts( + payer, + accounts, + magic_context, + magic_program, + ), + ScheduleCommitType::CommitFinalizeAndUndelegate => { + commit_finalize_and_undelegate_accounts( + payer, + accounts, + magic_context, + magic_program, + ) + } + } + } } pub fn process_instruction<'a>( @@ -230,15 +277,15 @@ pub fn process_instruction<'a>( match ix { Init => process_init(program_id, accounts), DelegateCpi(args) => process_delegate_cpi(accounts, args), - ScheduleCommitCpi(args) => process_schedulecommit_cpi( + ScheduleCommitCpi(args, commit_type) => process_schedulecommit_cpi( accounts, &args.players, ProcessSchedulecommitCpiArgs { modify_accounts: args.modify_accounts, - undelegate: args.undelegate, commit_payer: args.commit_payer, has_magic_vault: args.has_magic_vault, }, + commit_type, ), ScheduleCommitWithVaultCpi(args) => { process_schedulecommit_with_vault_cpi(accounts, &args) @@ -261,8 +308,8 @@ pub fn process_instruction<'a>( } DelegateOrderBook(args) => process_delegate_order_book(accounts, args), UpdateOrderBook(args) => process_update_order_book(accounts, args), - ScheduleCommitForOrderBook => { - process_schedulecommit_for_orderbook(accounts) + ScheduleCommitForOrderBook(commit_type) => { + process_schedulecommit_for_orderbook(accounts, commit_type) } ScheduleCommitWithVaultAndOrderBookCpi(args) => { process_schedulecommit_with_vault_and_order_book_cpi( @@ -500,6 +547,7 @@ fn process_update_order_book<'a>( // ----------------- pub fn process_schedulecommit_for_orderbook( accounts: &[AccountInfo], + commit_type: ScheduleCommitType, ) -> Result<(), ProgramError> { msg!("Processing schedulecommit (for orderbook) instruction"); @@ -510,7 +558,7 @@ pub fn process_schedulecommit_for_orderbook( assert_is_signer(payer, "payer")?; - commit_and_undelegate_accounts( + commit_type.invoke_commit( payer, vec![order_book_account], magic_context, @@ -563,7 +611,6 @@ pub fn process_delegate_cpi( pub struct ProcessSchedulecommitCpiArgs { pub modify_accounts: bool, - pub undelegate: bool, pub commit_payer: bool, pub has_magic_vault: bool, } @@ -575,6 +622,7 @@ pub fn process_schedulecommit_cpi( accounts: &[AccountInfo], player_pubkeys: &[Pubkey], args: ProcessSchedulecommitCpiArgs, + commit_type: ScheduleCommitType, ) -> Result<(), ProgramError> { msg!("Processing schedulecommit_cpi instruction"); @@ -632,23 +680,12 @@ pub fn process_schedulecommit_cpi( committees.iter().map(|x| x.key).collect::>() ); - if args.undelegate { - commit_and_undelegate_accounts( - payer, - committees, - magic_context, - magic_program, - magic_fee_vault, - )?; - } else { - commit_accounts( - payer, - committees, - magic_context, - magic_program, - magic_fee_vault, - )?; - } + commit_type.invoke_commit( + payer, + committees, + magic_context, + magic_program, + )?; Ok(()) } diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index fd2b4e3286ebdfbd7cd4c0036208a6e7f44217c5..caf607a72d135b520cc94d5c7b45f53cf97817d4 100755 GIT binary patch literal 451128 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 z r8ulz+jA`Qd4uuk-r>sS3VmD71gruXX28W&`!5&ewcT8bR4cj$*DL*R2L#$n0Z z7N_2!TJIpIUL2kGcj^r}@II>W<~sG_;FUY|-tO=h6u~%>PQ5ojALbkOaZwK!qT76{ z0N*S*KZW^LrF^Rh^KCP=r=QKY$~uapNnQ~@C%td*d@h9_`55_o@oQmzT<*{h_iA7q zzjW$dBNpF40 z@)0**^A5gM-wMllmGZsMsTW7Ddz^Z=J9N53;oa@ji-UKkQ!j45e$=TKH(xiRo<;W^ zSXZ>>>my8e*}pOSkxB1^drar7gI}Cn-r&@Wqf47pFHSGM!>JbsZ;ewgj?Sx`dTkDW ztChb^sAtic?>n^Ud?(X6uX>^))zOZzNnynlHQRe^CeDS)H~yelmD}v zdU13-gX&F1U(`BqG>toCr&>c;o!IUg|L1wcK`P-q;q_8|qI@MegJD!s8CUadJQ6)Qh9jSE$}p^uiY$xN&-68|qo~>T=}u zmvq+4@0If$eP#ax6!E=C$ArH z>cz=xC+b=BA94KQ2buocRbEHJ@~Z1nN$>DU^#tN!UhlE=z!Q$%#B=DOcR6@J_)cd&u4{p13K8q8Dt=sSe!e}|vj{a_t}?nf)|HGRfp>qqL( z7uJuO8UE@mS4!Hll2db@&hDof{|@wyeTvgL^>5d5v#+syg_gssqx$o!IBi;R3a9?<^^&Um`};}$^hGUP zUeH&0&hmM5cYUbRktZ`>${4$kkASh3b=vUy&B^Um6LGsY=e>nBx`0@zqS#+y+^vwkAMf<%CI;eRd7$&dzmt%l zU-mp%Z_cie_2=wTU2m?;vwpDqg`5NK_h@Rl^U;o*zD>^y=QC6V(EbF&GkP!S$#=N? zn`;;k=nVqx(LJ2Z_mrL&K{;xebC$TT1o`ZWMy@w^5jXb=`|JR1F^IAE7*aCUp zQr^A`c(s%_^L+%X%5PIU{{c?dmcM@&ddMyne%o~EB0;hDm%(SF$0s`%hIRaGM>oSa z@<98RoVVda5R07$LqEmNgLQI!+266@tmJaBk9K(vm&<;LUB0*8=csk;A^O8S7^L_u z(_gD{^X|xbocB*U4#5}ubbERpjQK_K0{$9)x#z(OdVRjgb@m{YZ?pcP{?T#OO)O9$ zIuf7kb*pn|e#h@yZ4h}V_#MKp*nO*<&i8}_UUB!tR2C-XHkxIgFVoTkht;v4=*dRKBjGk7*X zPkO63e^@n>k?j=zDxAa7^Je$&2d{u^-hP~T+2zWQ-cGT9hfBFRpEfLJ&zqZ)@`4^Z z8M9vaj`UL1PpMglA2p^%tH5Z&3EFgXiOKFwdJ#lJ>CUom9cl)xWil ztNUHGoZ9^IV&>aVmxFI*$~TWwW53NjLwr!{#0URM`qZ6YuHOK9$vMR9c%G~wd@%!n zH~u)Gn$e{GWgeZr;Oem4=jA!x7Xn|6e+qv*&TrogIbAR9CiB~GbLz$UhqpTQu5jkj zo2VZf!vAp)1$RPGy8#xn6h*2@w6l<@DakDN-MCYbQM~ymvx*hzQDAPSkITvp1ms zbB~4f)3~$V@6sVU#z*E?WAE&?v;$@aynHy>C$aY`N$M6Mv)pRBCVFKCb7j&AAa%5Ay(e z7_iKHEeog}&SRteD(|EG%)BRK-irv2lir&@MfRP;<@DbCDL&K9@bLu0FP-1O^Blt8 z*du%VwHQAZ5$FeffuE^okN?wXPkO+94!8$V`@%h9PWxixeu-2k;L5naAmd&oaFgEW zC67&8`hkz=(!Y|k~mO8r)SrD2U8W>Zs7d|dp+&G(;;so%x@Dv_*+LMf1c_GeJ_XNRHi4r z_r}lt-knlU@h^sVp6F%cc{kC@$OZgwv5Y*9PIEqX;ew@HKb#0k6TbYvx>?J^pdR$DA)l{fQJg4f@MgPB0w1{s`9}=kktn8Fxqdc0Dh=gH!u` zVm{~JD*!QnnBE!5gHP|}_wdIA|K6RPqMW)ZyoZeZ`zS7^^HTiW;7jkdYJR)WKPTfZ zHcs>lI2Y9s|IIwgDPA;g#AkT^5cOl;BQSg!UMclHCJDXw@Ku(p)f*q;eph!4aZ2}a zF+TSA?eSv1KIhn1vo3a*qu;kdo-Mi!DgNcKuYE%@pL(}(YUU^K|F8q62XIyi;&}em zWhCFdd1;^P;S}YdcWU<6xMFJdcX&RhX8#w@=hW=~WX~}*dyL;-P0fCmY#FT&%>++1B~9?*hgT?n=}!;) zv`O!4!WWC4W1!1fs6p=_(0T~Q(*~gQOD7k5XpmhXa_*-ZxP0z~oUmT9^;XdCNNp$c zru244X*+>mdb=gsP7Fus?T*%V#CZDct{vtrscF`;bj|3l#WR0Ma|ConDZNKa8Mykx zJ;+f#`XBmuu8__1QJH?(i-ev=uP417%$L&J3tfZu&rGqs;1RU{{uJ8_orCsIPqDqw zJ81tDw@=Ni;`OrB%>8A)%{-9lnVwnA^Q}$e$MnoQm2WDS`>9;goW>7uLvmSY_c3j! za#?b_yR@CaPkOT%-vFO%2p{^ssq@_QJ5_v5zk+Yln_&GK^m})xU%%w>Y?&qHU3D+lkyHz2|rwwtm7~NqQ$T-RyGg8z#M)NI4`Z=^Ym-#|lo;TN){cN=tf2MamE0 z@*^VU5SgS`9Vv%Pm-G&el*408dIxj)@GX>~UwR*`7lidNi6+%MAX1L^2$SA^k#bp2 znHMQ1RYdh)8!4CXq?Jd?_viW|w>EuYU(7ibyIjs+v)dZ7BQPmR@0AGuL=XNoQV#oP ztBD2)Q5y5z28U5;f*D|-$lxyZ|Qs6k#bp&_!XD0A!4y!?xV`|!#Y0e_RD2{Cq20zVa*iV1^r&b{42e^YY&>I z*k15A-C>jsqJ%6*`fc3nUR@?*s_Dqf+YPsK3 zBF!rj{y;tF{r);hb2Xfr_|=YkMrnN!a87+a`H6aOPAb7*c>VR5U#OEq_#ys2l2YSW zn{oI#!M|`n%4Uovc>f@~rGm%THuxQ0r(Cz?8BP(GZL-Eg_tP_;Hhx_cADHh$p?=kU z0vrFD_xJ4j&(L`2{al{s9pw!SucN${{g96GdQR>7qllAx1t$DK&>Q3X54wkd;xdLq z`)7==-z#xpcIi&Z=XU7xG0q#h*zk8KeIG^qqI5|mM%l0T2Zb)F#1#^kBxcNjT%;0< z6VOko#C{S_B)-RAx=tmUC4NYJSK^1n`4T@Qu9LVS@kx#w(uvCe#>?va=^f=Fe>PrA zXo17%KlA=lVf|RwO)#F9#<2f(Eb}ijxP;TB_XyK9UH0-!*mD~$=x5?GbMF-3d>{9W zs63|jxs>JK9}v0q^UC+zfi>xK@PSerF8BmEPt%+-d`Ts~$w9rrAMNVU?hg8gezS>) zwUiFu$ypEkx=WD%nC3~etB~KMc}gni|Ln$jJWg}35AMIAu8E#yQhuw}CnpCpe_hK6 z)5GtVcIJL1zhCNSTej(Qm6w)I&eQjEC0#0d*6crL&uf(O%S3*&B)8}>yG7=6wnONa z-6(XU`?2}CKOpjH)2+ezeu9zj$DWCPZ!Xh+$zRb=X0U`&Z_ zR#dM1D<(&uW;wc!=SgNz&Nn4J8NUrLPJXW7`%z@PSZ}a?olVueJVSD!bkX^0!^J$L z_s_Ulx~!*UxqTnxHZOEfmwkdXIOI?8FzYpTKSoYZq4^H|DE`~!%pa`Vf_~7WNbjZZ zBEkPM>!piL9uMhf_BU}}3jk6H8F@PKt{JF;`>0XRUSDVWwV{+`nfiJD$Cm!4`G6ee z(dtKtZ(0xi0}qrRVU?qO^H0L_G*aJq_>PIW7B^-wWED|(Qh|{IwV(W z2ZpbgJjV5*U&9_esq=Wd!rR4mFkN=?Oz1KNzJ$iYJ>El+NH{IuJ8AW9*)yX7|)th!uYZuX3hU2 zXgxTi{#QD2R}zwx=@H1Lgdz#oBLR9 z^m|=%RxrG5hw@$Z2k2Z6ye#-j0Dq~-lR4)HIkmUh^2Q9SjHf^b_k4XDoUyuzMz+@N@FL zDRch=-LuSoQns?2<*}oD6W=Sdw!HZjOc1*t#4*EL6%X>N;Ex!;3F{Bkg3kj&03bK+ zd)_o1cfo(aFU`9Sn0Mnmf3ub6@_eNGw={pI<|Qu4R?2;3zTU^0tz5>>+w{EXy2=YV zZ~T*WMdGlyIO$gMbBHdiXZ(Yz7{6glZb5HP_rd`kRU1TrTsvsrtiO zUZLgU&o)(W)bc7Vm;K15>RYvZ374l6td6L^8qM=#$`e!Rmrj7Xz^9JWRN_%a4E{YJ z6#S`ve$3y+W`8OpdH6HCob%X+(<8{usj$~py%W9~$PeTl>vgDil2fnxhv9ly*F?P& zP%kI_LO=0$m{v(1&#yin^c?>SN{H{Aq8xH!{5s^%qoJF)6Zv}NEx2ROJ=!%IXI)J8 zH`D(D!_5rJcbN0-Y z4c`zi;D`O$qbW^#Plh*5g(5r%j(7Scg!%pIssL*Vg9`kv;!#(g6$aj8ElW~eGScz zYrawQ6Pnlcf~8`AOgx`1yPH=)+j3HGot`@(JR;+cwWfG5Py#{5%4813xbK$$ zq4_>=8skUt0jFjiHdWTaaMlpeDr$0p`g1{?C*x_$7`orU^&|alkp66bJ_Ne!`dKP* zFSj$}e6{Fr*4d{{f6>QDuZi*86Tjq-|4#GA@=M^Uf)8J`%Hfynbk^(4dfR_m^=!Z7 zMk)oD$qRsE$wfQjkhQ`m;B)YC#Gl?y(XY97PLtk)Twzbf|Fng_y-s$Q zRX*AHziHL8$A2l6Pi6dH1srSqJ_(q-52`L8d`evJ2H%sG4P zEBuc1p$)f~KEwW9<6>}LexUc)NiVwlAby|dA!FZMxM+9ZH)vg2*IiPHsG&b?I>C;a z^+d$IRmiu}KlFnRW4)$w4827|rE%%HgjLS=%B(jP^sw6bf}U2rT+ri2ZyP;t^t#$Z zy^pq_x7D9YCte5icwNBO+u5bM{y@Zs{?4wDb%gABqc5X=_Ok7gmXB}>zLA*h@_Quj z-z(4Q94A=^mJigvQzWM&*;*;jI(ggx8S#Q>vQ9` z^k`o6dEn=WoCJQ3$WgX(o7NY<(0ng5TjKtepA$YB|AYJ|p--jQpKOQNV_V*v5kK{U znqj}=+Na=myo2K>S|8>#=^f8<34MSc;;1VrO?t<0`JU*n(=Gi2{e>>T&sQEM{4Bj2 zr@v3O+S~eTnA%T8e;w=SuSO@nT+RAxCDVia6;6%ZCB5>J>F^C_odbS2;2dI&1NwTs z?Z?o3pRe@}bn3m}z@w?n@D@1ZsdL72E{~^P$5R&?kNF;vS;qx_$G#r^g~&6V+e0_r z@U8flQ1b)XOOzgzXsoY|BqO zn#aGB^)|&9oEm->8~?sEej|@b?|BAn!#Do;w&6hT=p3=ow_p9h0hx#JBWnnP-QM*h zpQkfZ!G6FeNdidk={|Y3Mfgzg*Ui3wHD18Oczp6ZBKD@>C;pztVd7g8*B7%tbyU;X zvBEm{b=*AI|JVJje|-BRb|BvVh`oS5I+%t?-Y7`(o_PP{=+7_DAUQ-(i0?#n_)ue2?sSuh>cV z`#72YJ9$231~+j^=Q>#r74*)4$|LC`o==wj_%}ySg0JA)JE146dUe*l(^y|dWQlss zPQ5M%9*GLqTkYtbZb$EKp%?4uUS!7K&vkQZ{?r(WFn-t3HT+*$|2INr%esSYC(Ww_Vj^mwi)H>t1 zipNo>{g(reC|x^Hxri-eWut`VNT9=ewv=`rSzKR7EMB|KsOvs*ez-Vf^b3q<`p_^d1(v zppbrrxb$9)7cY`>#EVt*=kUdvCp}hy{3V*FxSEFQ!A>(D6%VYRFQD=^-9LPg{zg}Y z?-tSD_!agY@0NVFL+n;|qpZvM1LB`#J67^Ivn}HH`2C}@uG`Ws_D9bhWcA#h->>mi zi^g01x-Q(ZN#JbBORC?UqVLZ0yrg|%DPP(s>52wP&#Ra8vN}%9dU{slqIKolxZLJr z7v@2)jLTk+J?16EMYr)h$P9Mry#5gLWB3NCPxs$C{1N=jI+^i50T=$V*)M=U#r(Nb z`&Itf=P7M{1G!*6T>~zX-l6}QPx>7{VQ@^72+57xbi ze;m_(9f(f9q<22^nfz*<*XL>eS(eA7C*SL)bD!GJIr{u0t$()WpVIno)cpBcU%vBA z=YzHW8T$N5t$&*4kI?5UIG>)C;P-)tj}$zI->B))lBVfYUM2lGjKxp-rDvV^7v$54 z<(%5{0REHTJMl8=K`&lGdsXpq#8U3xFYFuDvAnEqIZe_nwJJX~oZ9{5-TjYOByMS4 zN^;w`jmJythMW!$0vpm>WEa@Kv+U11m(#d%`kW>M;xRMdfPXi|Wf{lL_yeMkV5h8K z=fVTu#qpL6Z>J+~V+0@mVJ$TT{L8PUv!5+5F#lF>8RInDA?Mp|I6_yEPqaH}Qo3Ho zcm#CqR=VD)bls$M?TXN~+o3DY$)LYCF&WZRK^n>r^FM0H;2Y)+NWmJNPDxdGfDjVuQik5v6SIpJ&IIj;odfLUfJKE`ftA~ z9zxS1#d`xGL_dE&Xkpy9xJ2;L?>_lAS4jEt#aa$7Q~jH(IBi;fc%fhFn#QGi{&3SD zS0lI!rG4SK=~wDCEjmcyYk8l-Innf=(&v)*3(pN6^YwW>cj)&CAN&&~Z}y?hcZ2U= zB!X`4*E-JRK|J~$c8R2yQXYysHR}KjkMzW^_?+PVi^f@D9=1s84ZmMgk`?@t-mm$2 z!B2~suZUNE?!-@!GswwTzC!a>=QZlZo%i{oQ!mcX|19cR^6kM-yPeVH{&tdXB>u4; z^>ZGlz=NhiAudGz$rHo+Wg_N$&-dtDaAt6V^zog~T@6^x5ozF83_6raS^Q51_PU&3Szd)`t(hl>) zbI!%#y-~>Rg-*S=b8+W8^JEj`dzHWkoSS)`bhG@?djp&nnx!8- zotQWMw=rDuuQ@ev(uqU=TuG=Ty`M8efj=tt#fIddn6IM}~f8_?%AlFQQl3!E$n!`q#IaY0MGe?jZlGLHFzPdYKie+1=aoKGiy?3BxV zNGE>il#9JdC!W!Ai7$hFLtW3*{)P|aYP=7Cp3FX*e|VL&-%t8)TF$S9c!m3p`xNgJ zF&kiq*^RN<*JyiV50!tqkLMp=E6?XwaoV&%=WR~n4PWn5O(otSc2e~Q#sP?Qucy#W z*BcR+0aII^D#-84E*;`}koVV;JV9T-$GT@XILBNieqUt|4}|oT<^z2Vl9i&bS-$S& zVR4*3y>rYOKNrq1o4C!KV-`IaoMYDbd@r73{_Vri*J1fI-yb&g&MqBc`qI5b!jJhP zFTuHHe!Z0Dt$8kTOLmm$+*JKno=?GZkr$Ffeg3lZyow2H?q4Fk?mQQHOzZo)0bG&C zg5EFSBXXGLw@XR>3*~j(Pb%?#_KW-h!9TKJmgj1GA2-J}>m?7p9(OMKt}l~*w(1?~ z=zqu=0gQ&sx#chy0;5jSH z7kLZrPTWJ+tNqaUYBVkx$GM2yiwrk2DEDX^KP^4ur|d^zJrH&P`!e{o={Z5VCxbAy z?CBtK(KvB3zw;d!|7K}7nLSLr% zbKJe^OToW32E*@r#@(yF*r^wHZ)TNK?`g|^U>zYvU4fnlJN4r3%{&10EdJJFePXTP z3pj6K`Kn|4L-8=DC`VjVu+P;M+#p*i>!f})RiIzt97%PV=4)jgubQ*;yoU33|7P9b zD3UAKNBdrA^m_!ABTmN;^B6z6$A(i{_htQo_2()oDfq>Ceq2;9#_{c?FA*KqOFQuQ z*AATt4W{#NoqBP6`;}Ag5a)Y;2P(W5oO*G5dk*z-IxeEq67X$<+X^SzAKL@fF>EgIp}UsWS%;d>bmYk94t^Q$;* zTJU8~?eU3z6u%MU{5;Vi(2t8rl5G7b_O1{&#Mm3a`60zMc0a5iZ|Ck=4wKN2?z*JD z&xLtp{W^^wx^O`=<730!UHtI1=4kvt_d_zD%sm`!xeE4|Qi)|c-hgj)gb1BmV1 z-doiF?@>A2CVY#(7?)?Ik{Hs$T6p7rher|EAv> zZWs9frd;$(;QyQQIo)`2Fu%HD`hP3;f1CE-#cABR1v=-%`rUj##~z>YD?U%~DEJ5fr+!Zvr-uJ_ zocw4_n9lC^2+X{ggLyINF`P_p7NBka0rWRnebDKdhnW$ls`` z@xxPzSsW)qJ_%^XSk7#CYiJ!JTiL+n*^RZ5cGN`bfiHBg9GBBNIQK*GljgfLFLF%ZE8z>2I?9*4 z0uqPx9?==|pHO0dqO|XE98Vmi{WyxE@dw%?jpK7VaVzt~9;f)ZW2|pLk1L5Dt{yP& zwWJd7lX3Oxdbz$2y1GTqYpve0gP)uC`s{wnh~D;i;rBBAF+T?837_(15k3iivJZ;- zZzTNuK8ZI|GvCVN_xsf^C96u0J%3Q}^S4TzYT`c=599ryGDrU%MR82qW@=17tOo<| zI^);s{p`i`)x=*Xm)oO(@4$rYC+5A#_;ylzTW-(d@r_IU-kqGnb?S)@xcT<=G`tFDu2w@Bcn}Z*#`? zJdbai()+akc6#R>e7?i@7%(t@g~P5bUu<( z%umEWM(-hitFzv-9dIl?3B8SachUJ^y6=tQ(ER2!>7BvzCe#0b%I`;+o``3voVeml z#T)$x{#JlLBpCf%Pxyd8_&qpV>>T_**gLw1o6GI*PfU;=$N2=bN52`T-$SU}jQiDC zkGz8LMZc5AQEIn=$6M|3(YP>FGftbICeApL;@s5i{Y5YIjxfFB^gf;Q6uH&+w#>Z< z!Tw%7(~sVtVK~OGHhx(uaWX$Q{8^m%2Eps$@rAyBcHm7U!7^@cApg`YtT>zh0zHBs zeJ83y>KnN5UplEm(mRu@1@ml}{f|AFXLFqS6L-#JmQycop6&W#c%HR8^X&CJ&pLIU zwa3o0N@t$6#>}%*d7fRT^Q=|pnar&(Jgye_5*T(Y{^}b8{rM7;kkCC5)AU}ikB0o7f_x+C>e?KGsp{{e&dl5Wddz|Bc zo;-fpOmy)F#`$2JpP%5=Za+rt&HfMQ_QAn9gEZ-rTVCM3)S0uarX}HCy2X8 zHUDbG-LJ=tnnK*&&wQ}yCULF!k)X%*M33nF*ElzE5BKL!Bkpb>dfWbniMwyXyclQ{ zKII!Cd=mV`ZwG!CGha>I-6i-~ad#upqm;ON zDL!?APfqp`>Akseh-9$dVAdZbjxI)rvJf4{S+Dwiy3V$;Jk7&zGxvoho6b_y-9Dr z_$_K*{h0XHzgPMDCXI7XCWg^3yBJvAVcz3HqMHqf|jeRmJ@qe1!6Bl5FV@hPkm%KD;DF&2J%bDgl>!RI!{r(W^7UGQ<% z)l1nItf9D)8}%&xvjh7)R{V7a&$}_^2fe4kDfE)8Q^|S@@`sZ?u;Gk4`$a}Cw;fIT zEccY~cW{)`q<53VWBu`%`QQC}Fo@p2 zR{3DIQ+|Jaey2V^pP!Q-=;)VU@j8j&d;Ge}UlQnN_w}ADq9^G4;T5;C{}z@z$m5%o zA7Vd^o;cw^^hSJ8e-HBVF!}j~{Z0`>mZN{WlFHT3GWE@Q5T1Wm)AO<@yv@{ZD&G&k zmg<9VnBQ0N>J!0Tqi`*Msh#{GKPUS4;RDa)3g$e7x#!=U6T^6cTCi^^?GDrNx0Ltr zzGMr%|A>ptvmIX*{*^z*X-oMdnjd)uBnkZdRxUU157IrsoVVq=hsHtiLDBQgv`-l+ z&vQH|=g4e0vacy}m2DA!(teKjdCa~!oe$UrJUhy(G_Bx%I?6rGPw+T8$|df!;dDCl z(D*<1bNtiEa+IEPSHwTVccx7|YQqz}1z*UeeU3Z8cl?!o8Q(F+%WltpZ!bNhAD{0c zdcse^`0ze5_-fuih8#j}0yz-B-|*F}Yi29oq5Qm-)0XmUG~fIR;06305q=I(A^mX9 zt_=LtdoNr(3-?6lv_6fuo9QCw;qCfD7x7Pr^ID%e-;Vkl_1u94N9Zf-C-}}cfhPWT zYTB;+U8(s-O&cQe)$Z^Yel_UU#{6wp{x(MVEAkaL4#79dUxRPMF5zz-<7LwU{k!W+ z_V+ich#ufK#%ta?kMddOT}yc@&)-$$dFES3c}~;2HQlV~2RU6^-o^9Y#;2L+gLNVI zo}mid@3&R_Lcgz>>14ON4R}(!D#8BK-m1=ZU_qTbJKoQPb<;k|n~If7``QNCw#lJrDjWcqJnJd@s4Y=1NT@7Mfl&0nec z4Cljk6ZZ7G{5)I^dwRLr^WEFi?~y$#W=|hqJ-I!tg&l@6qMxz1kfQ-=Hx+xjp6bWh z(?CzQ^L&WfOEa%Jd0qwcYe?tOHcicZ>(P9-rkgbF;?$lm4UjKO??G7X;I%>80}u3% z_WM(c_B~GfM#iIF@u-tj*YUC|ME?y>g3pix@9hpgH4Z+&1NdNR5BQ8a?au)|1GR!j zzJ^nKd{qRmn0~v7_NDx-OBDYqX}6v_p`VGz(BDp{zk2ki@8i<@w#?_iA5#076FBh0 zrs@xgKG_+OAJK#2582~`zd-MwMCyzE9Od#o@sBFN4^c1dj~M^xgS(eYGq8u$&tzU{#z_col0n0?!pqp)sp zh|p`Wg43k;M~?pty@I&?4_safz2f5b7d}@Sy`FRG#nJ1BsAtiu%%RtOrq?{BS6M8* z{zwO=Y&c#Fz3Q1>vy@(*((Btym#{sBogIjYTbo25>AKluaqBNu6JF~@&kRG@=?8xA zSViUJx8rBz&yHLF5A1UhJNsp7Hx)a3C)JO)v$8Ju@PTJB9_HLY5U0wzYBWxjcGHhj zWt}5i+3M)!=7@frs$R~so{j1=(brMEjCj46UKTxW^xX90*6r9Y>SgkV^fK19=sXT&BfqE9iu?o86x z{?;L;58Z#rsm-6=#jRM!H*rC>QsgQ-1v!#=9~Td59Q!KDO+H3$E@rvOtK7u-YjJo> z92fIVoyh@-Bj%9r>TCtJvH;EUG17{Kh3<_`*CYGtQ=JNWD_ZhbfK8R!%| z^6i}3<7*~(#q`^~v_C}aa*BVmv@>$6`-sKj);9E~-yiwk5Vx)bKZ^KApQAV`Gq{rJ z_Ww`Z`a_8;`mbcXlb*asFZb=QvpZ6lf(;IHqdO1lk@49K; z`Mm+Wb#!D0^7BoL9@!S5GsW*bAL-tInb)~)&DU@q?`K2q;eXlRTQ+tEnxCiiE@OJz-?QQI^lCpq z)|p>CKC>Q4<7q#XMUNX`T%Y_5;idQZW-E`AbFq34QMPii=2gE|F4VmAm#s{3er@^w ze+QjcmCJiJHoe<#gCi26bM zKRM^4&_BwLpmjliaES3udS9OJwr4zUM=8P8`HpsF4{!=@_ zuRkX|==>e`2Y)UkC)NMOOh|ga6g_6i3GncH)ehXu=it!-s{-I>2_4U(w%wpZ2$+QRJjg`pd3p z;Cyyzy`+^wmk1sk0FA~;dN$4;{p?YUSH|bsJ%2#_fu_u-nMmf`D({aG+_?TQ&oL12 z`w8fOh2NCP37lJjm7I$hp>+6z$Wfk*uJ6N-q+|=M!R3gX|}RL34+7mGcUSWF%{``1y6n3% z@P|!*)-!q4GuFI|^EcOF+ylkuUDKNLp>{&^0(5ZuGx`zpJM_IcqBj5l@2jnTn%0~t zaBl&0nr}3SaZ2}?&#M@m2R_I7o4FpP-|;pUBV2c|E!(Pxa_1>x)e8Nv^-TGSB6! zD|bkF{!3hb!4d*OzqSFf6B&)qlHMUg-<&*$pAu&ee*EP?FQyW=5oVBcfoG2&ek;bA zg#8;FE9g0!ehUvOW4lM+`(Zk!%MRu^%!b4AIfZ!WFvv}8JoF-Qn)tLA;-LjrKTX&C zRNz|i&j%j4v6gV-Nq zKkT^SLXwxZ0gvZFeB3b34tCUTi=9V#IF1s3itC5sDD|&eqW%@m`~hf0#B+AJ_(LMcm^U<3ws%l4kPqbT`W)Z% zQX&0}y~8>%>SJ7$579Vt{FvY8H}-G^$*iA~^Uc9MWNL3Kk79Xj8yMk~;si+xdb+(F zc=$P~m#uuC@G~cP)A!yupY%S@@t@m&F@GKt7XJK*QTK0a?XBPcHZ_xGs982R@|2pZN!*&DmXRm8Tp3@-NPzXCZvpOGBvs)wm7(RVu z+pb;dvX)uIQm?IB8b;_j1-tMz@`HSh+prF2+o7hrE)x5v>nZRrYN$(J^|{?|8RU1V z%yZD=e40P@bJ)Gz`}Omjc~usgSL-&4z5Ji>=f^F7*W4>+j}QE@{dok?_Vda7c@rO+ zbt>DhzmWLTmRG;NU+vjlCl&Qe%)H&5eTDt12Y!~GVEl9)MgY zwNj%sU(l~{sP?UBwbIsF`g!BEYVlT4tKy~dt^Zo<|D1iEb7mlyT7Td7{9vB5?`yBy zUVH7!1N!~*d*wcxWG}=}$FCES95&KZnBP;cf$vw(R~ANbId9>5chL0i;I!jDz8!IW zW_m65+bBE{e84aF?Et>1AA}xoybRlTiFn!OS(EPqkr&K^XDTH6XQ+@&Qs4mR&0kYg zY6AQ)UGj_dAYG#P425BvKc_P+s*v0PcX!e~^&9F}i0KV@!{eAgeDf&!Hn$v9k<7Cr|(cc;J&1)oxV%s z`&zc>yPUVvUH@0@^xfKz?x~OIms0Y035R?h=Y9y_XRLYLhk&0k=W*{ez3h6IcsrN8 z#qi|yfb#V=a0O;M1qXzbt$=mVNkx8vpXS?L&-vb^YFF z{Y-cJ{6C_{#<{9$G(+rf`c>$^LoVlI&NnwH{p;~y_8H=9?L)KEG=GhKXm)72!R)+& z-DbDs`w{E8816=T5&qR!FAFGYzuCLqe%lB=H*9!nWWRk`=9w`(;2-F#2@B7|e&f2M z&vU77x|=>f8Sqr?w|~#sZ#M20k{7BS-aYk}#&Xs`-;L$R_zlR}nDbHluGabLJM@2g z%{tuGFpu>69=-C;<7+(s!`vFZ_MFG1*YbKw?sHT97519l-0yaCA%Q2X9xnQSI8Q~t z?v-(_s%IDBSYkuJ0{!?u5l37&WPA($j>nNXv;Rx=Mj`n_HB0k&Y1ICg)HA*RzC8d^foBZ@tOXv zSkIk|>Z@N5`8%y2c#EDct_yAwKj>mfz7_U6OoTtv1BN z2ewL7Fq-I|ECu9g-Kei*RK2)j$L-#z{2Z5CF6EeS*^YlxB_5~0G)hn9TrFxuKc>#F z>U-+PJlyhq8Eda%aKQft{mAp8ijTdj`ZWXh71N&|*SABQmr3Z=XIQ>x+P=+KWW&)169h?0bV8 z%mVSUXGrqCRS8tTZ{j1e!$szWzK+Fta@ykKZG=aap9cDREW7AI$Pe|kz*QqZ;T^{R z+YCs^&kp(dWbGo(C&#mk=3xHHeGlPX2FJY)hwyE${0#SWXhh5pxG$UX2)f)U0yMDU zxY8-kcU;Hs;~C%9u16Wa$am{>{g8YYDyKYb{5Cl4MCP}F=z-p~_S({{{#rZ5_+Rta z*ePZYA-=|5bH5_u&oy5Kzm7Lw&HMAfFQb|LR=Z9g&sS67lm7kA_haq@_-keNu+&-I&tHFM=*Ixj+>_6~6mBTz9!hWAWu0d%j zFRkDGg{sB||6_;*Uw-eyk)D*+YV_pnGol%7o$jc-^X=5xrG3b4^?q9H<*FU{;z{Vp z$^JNwt046%T$X$ zFLn5@{Y|kS22C$;ewC+t_td|dfQsXK!H17$-`_`K{0leK;D7yl6#tKBo$D>pyf>!v zBT+j&>nm1oWIvXKK%@K#ydkK5m@daHK~{o3VvB5}X3 z>Ge=K>c_|74B5b}Ean zwbxEse-1c4MV|6{;3VL2zkIweb-U0t-VdvMxYO!M?^~zx60c`onj7CwO25KEpBHSi za-hp4l27oiaPj+%a(}0Xj~l!ZJ75#^%v zcR#Z>eMc_+)46ouC*J>gYc5^sI&AGjpTiym98-l4fv4z^^$FwuIWuOexMz0DdM__n zJS{)DzaQhyQ3@Yp#>!xYD*?TcP&_C#fQsmzS z{6EQ!3#8jWiGKp=({Z1K!xKh~4q@>u1u$(tX6-JPjDWM<^k-OX6J`0Hsi$kQq#Its z3=8wSui+vqA1?HIr~A9h>+SIRN>*+|QcB=}%kVLMt|nx9YkIqfU7t^v$%Qox0WuwP$_k3GCyu-so9^U2Q?H=Bv;SI?_ujio0f5h|c@$iQ{yvxJy_wWu6zuW8i zgx0em`Id$Uldt&u^Zx#fzdxyO@OiD?T&eXTzE;n!&f;tJa&HzNk8ixEEtP!~Xh`Vj zdTyzQk9xSv!^b?lT*HIYI)09MgUs*r9gmYLx0&9qu8VIGxsBxmdN|e}Z_1@l7l%<8 zHhm7c*qBT2(sYwkq`y9wzERUnzLCBzm%c~R>GwrC?x~I8JC5{iN(R-_y^{V^jt@G% z4O{)tZ_oqTc;WlZF-`!_fbTPNF;3XHSwBvE0n@&Q1MR|(i!ueWoP z+bey~K&zP7|48d2UgW&G!Ds3yA>3I#gwNCS@NvJ*oJC*Kdee)IF6j-{UV4u9IK@L7OTCKmQY=(clE_WLB+-v2q9(`1PHrnsM+U=H)UtZfT z?1OXf3+gp|XZ!tEdw8nK*Z&{)`~SVry?(#{$CMDi$o>B7l>bV~e?8@=312N1-eKlZ(tNGuPuovvJ*nT*o(`U|@Zbr1?>=sCzh5l9@3e+- z4gd{5k#hhmvG1?a;q@NXchzrc`X^+5%ZEMP#($Zgd)Vv)nV)-jslK_dC2Z~04u%=C z^qsb!v3xT`z~o8Wtsh~A>lw!bziZBO5uviu?T-`Q&TN-aKdBz0x#6gEc(5rfGpM_()=HqR`w+^3<|FDCcj}gA^ z&ui_6jZ!b-?~(Wd?@Jp#YH+ttH~eSwqN(1WMBg#|U2bn&CH2U?w3?nD$L6%DJ6*<8 zt2bR}d?V|MR_{XN8`;+evP5>qQPq@jkw% z^Vq)gpPw%;Bv+oX_8ku`C%ye6-hZM(R z{nS(RKBH>-X_XJ!Z~RVSs9fss5nml1CcYMFxR88J^;@;R?KSn$Usp)hIGn7<;HtJ` za2JyAYrUcJTyKwd+f^DK+ioK~$Gkk-VgD>$?qPQLJiZREmR?9!8oa)bGR^qc@zQ>Q zwlmNAP0` zmL$AZB0J=L(-rbZp7OA-i_Ea_`pR)@*Zm>oy^m$G{%MMI5O)rW-yKXnb6m zkUX(p^MKk%HZJG&dQaOK)xYsL^Tl~G4w*Wy8IL}Pc;Q>EU+^ve5{_TZK0iFX4YAU` zz2u&a`|VtYuV02WHc`Sn8yY;;!;6HTSl2vpiK+sv2jklZ-+lIMv)lJ#7b*Q{mxSRC zqo>c~LYo#-yAL36pLAGrOcNTlJImWWoon~q(ysWua_yBgJm~!!t38h6z;}F~n~vj` z)b?BL0n$zSj|cR_gZxjI{Pg$L)6X*2=^23!{_8^0ZtxHLyu5v*>nYP)eeGuVjG9@P z&2O`LxziPL4VG9X_14VGy&UAH#$S$uGxBi$n@>;udk2N&9h$LRF*tZ%Oy4tn{!V}4 zGjj8Hhvz1TuaEc3+@;M*zqf0>)$zc_QI3Cw2>PswDakzf72DF=lgDbg8G|sTQ+zb>G3~Y2t9s<;uCa^o+q?F@D&F{zqtya z96=6VKF`KY5cY8IXKlS8vX^g=boxCSm4At(13u$Sg>s1drRDo*T3@Rl(nzOS_;ByX zt(}VX3RW=W74UpJx2_n=G1Avcd$iN&N6PlE3ASqF<7JLbnE%^E&K?yd48AEQ|EBmTB&&4*ko)TD`&@US z-xT8y@Q8Ll+A8{GzuR?!7vgFEdU)^K^m;O^^uw}$U%`3rsbt$2sN>*q&*X6fw@ z>bp8W`V-6V{cbc*0{%gl;RTTQE4AP02IKSKdVbWEHs?!WmJuqZ`$6nC-DdbfeP4gB zjf0KnOAo6YRp(0wJ=~%2KIQWz8Ru)(RsH-i#_8Jm(z(xj!D5X24gECMJc;87^#JWU z;O8be-_(C7G5$SZc2(Yf?Ya04)w_tVUC&*u z>GxTp-{W?vr;R%FcuSwVs%%leSN_c;Da3`A;Fa+3MMC<3h;% z`G2hWtLNT)92qn{6b|{g?(( zKXHE!*J~b|GG9u|c^c}aH5#mG$HrY7|3=?r>8STRqNig2JLpLJB_2=L<>;;BtdmENyyU(#o?DB@$$x#e^!LCRF+K{m-&kGnem%^&$)*0;_`{WRrM>? zuTRAG2I&;z5poT>JTfjG^|Q4N@wj>nJU$2UdHjtyJ_T>8zsnX5!#3^#j&PoMeC9du zc=7)b9^W=D9zUraj_F5!yj<`l-^tN*Sa+Zc<^y=--eCkqU%Fn();&xw6%t$57<~Y_ zl4POqEA|;&E$`dqP5sd7_=X;VU|hBnf2AF*UEZ!2x+hpX?GMhML7!K(Nqv@_G?%rw zmPgcKJv~~jZ34iA5No_P2(;6X?PJQtF; zsogW$=lB&pvO|7`HN6@U(~WZVCfIwK-7r@<`|+P^vGKb8T#JqO=YOu{x6lodxj!t8djKlK8wxV*`s&)a>zOM5){e%nzOJ;1+BOp{oSKtIY2 z$1UW0P40VKCy_52UsvbS^Y+Cn^}g2sp7E9ASUkQ8i|Y9L@i{{GG3^v{_{I1m|Nc&n zuB7*ibMYGm4~67AXfEQflgeiy+t*?DF7zK7o4MbbMpL{)We+c)Y25^I}lZ8*A z*J3}%oQv)IBB5e%bALgoSieNioBa5?^T7Q!V5XalpT$3`>D7I7woZ`xzL-Mt`znw8 zUUxd^{2Iv@=n(uqQNVeyBzW=t3}NJmjwjjrjqq~}f6p}!nY{b@Zd!J@+UyPgoczny zvEp^Q_0kUQd*DSKHC8P1Yaf2_gz3XdwLbDqF^6Zw$9DGHrT+8p$KBeG)(5Sf!2Y;@ zKD1TakNZPE2Jm*1w8#F4J*#jxyMH6|TLU5Tn0HI&K}|odn{OIDs($c0rQY-J#~W(t zaSr$k$%yg~@c)#Iw~xc_*dg?)`dN=FpTWxGTdPue+v^XV98y!}`nrbzj47itq5YRV#gXY*M4+1F@v&ABD$9ooNXr}>lPdF@5# zIqv*H?z@IM?rgL60QbGQbc{P350L(rTsr8>ajVgI@$+X%e-D}60sgDeE3>atJs;x{ z^hP_NUmQ=p8zi1|2_ue&Lk2(g)y8-leZJ#yvAr?R#e@1=#=}>HkF~k}0$(vc`XpVx zi(~e9b`FvLl`YDraX)N-;Mjh3#pgbQvk_jwc!2*zj8_>hYVdmR1!Lkh9Rsg7B0i7D z5rYH!pmjd5)8TUd1RQ^Q$=LP|{T;~nqI2M}^M44B?~U--b8o#|lOJCx_$efR4D`!= zrKTsUdL#Jw$$LHBF3a?YkH?W7xm(snipc|7U(6pHg}-8Z^(`Ypmj-&|_pq*Vm(e5b zG(Gi1^+~Kp-Z~CFWBYYd1A30$?fkLL-k|$gxra3FpXn3x7b5+qxpd`!w}Tt$lQ%{5 zs@Era-Bv^Y&ipa>{yXqLt}}Qudp<7*$a4e;@WTz^fURPphzdT%TB ziTQK0b89VTFUI&hsebM!uTO4_@mi-(?y2Kb%Efnqzlz}xW)JoB-ylAZ$1(IttS4rS zhtD-tzWTs9@c8im5FY18c-X_}m-Dc@hNNHECm}-ypP@q1rQaP3!@sWMp?rr(;V%!rQp4Qe z)j#rb4P#%as0P{hWd4PlT<)^@UTz;)A-P8FaQZ`d@BR90pOnc>b=~*N+D^#!d+acH zvUOkcht%)ySf+hi3qF@$Sl{iCH}BOi`?)o)^R6F0?)4tEced}<+8?-euEww5XYk!| ztI?~k^LZLC`^@y6b}qK^*}m6K4d2oJB7OI*n5Xa2846yq+2I;!zs%D8Uh2&b_Z=nj+|#S+u|7YB_1#Sxt>fJf7umY}+oOAZ zIKK;(>m?@PPQ*^=OkD&0lj*g!wBFU$ZXn-}giOAJxEj z?sfU63tVx(RUby>Dni4yl0YhU+*bX3hvGMg z+!d3Rny&q>+3)?t*6r)@)TR0_?(dNtoj=%+&RoYo>U8Eh{t*vP)q1gx4>~uxCoa|# zar@?nt=B7dZwAM)bFbqk&||}jzRZ6R@6&1(e|_98?U)y1+|KSGJk@dQz;~Wpu=I=&mr}-zs<&<;Y8&>ZGW?d`?C4tc2D17cy&LY ztY2w-%JXmcTR;EEUea!d)z{+XeP4mxlW5~_wl2kV?jP8y^$u*X`o;eW^;RPfz*B6e zUH)w8=YEqO_$ZTV{r540cEcOfZy{zXprA$>>v zv-rV{7T>_1^~fCPo3CS-tD*Nsp?B=h`anhGrolY)u#^wmQ5ycN1^Rxx{w(erjOU>r z5nK;|^`F4I=v58NIqIKT*!V*3x6*Ko2h!!cTK}zDf3_~Wwim^duwGv^^vvs(OQBaP zmJj+Denx&b1naR#iPIq;avzP^Ut{=5d|PcSGTPZxs^#`LehS`iz!OS*j&aueYlctw4Gkc&?|{tnR>h2%D^ zFQapLhla;ne){?KSj1rE*iH_el-M{d}^1I@0@JXOBnkvf?3bm-JRYasztbGzPsd zQ+hwk?VLS1{bv3V?oVyh-Wydf2tnit727|`dl_XPu-9kbzv@3=^);&JwOWtQm$Gsk zug(p}>vH`gpLgWq$>&d(e%Fobvlm-G{QPg&YkW|gbjIwjyLv5so4#u77PJ@pRUQI= zM&lLe!*#uw|7PX*5BwRA?-%9LjX$g7`}AD8&Szb2;(GKOTl2n&$NyAEeoSXd7<}Nx{>fIN!C7(f-$^ z{TN>I&Bp}adA!Y;{Q-x=_&jalen1-!#LuhaY9ZPGLvT*tZnGOgHh+AY%1L#9_(di+ zgNeT5{fsYs7VP+Y>g)i(7q2J%8uYK*@nOI5G3`z0ν#u+I4SskG<2&QmXcQ2cW- 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 TLq1)Kuk4NEO@A?7^Z5S@V(cZ- literal 424360 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°d^7PTn}Y`@|{rV zh5BKBj*9dIehj(s6%C@QeA0pKuxU(B++a$oDdv?>Bn8MQ9_hPTsRtWO|Kjfsa2;~#8P(@F zk160C?bz^0`^0{XdMHGi9-4duAGIr@pYmtqEAaj&!5e;yrVkihC=dOMcKm)zNBIR( zp6f{YBT`X5>S^9?<*0}8+=i)J{QXRM=hx`;cem5=W2LlY&_%!AYd> zwspcCoaeT4i?p9TvD`E*$KU5n@qMa5=Muz|{(SyLcnY0KYtM#B`|42Rbz@c6DH=UZWD zhL-QV*v@gK^-dS)eZt{<8FUU=JHht_(t6+%@PD;1fba9vOz%VFJ{<9@lZT^Ui9^+c7Y-P;|X zy^c?x$BFM|jhFNVR^h*|yY$R5J>Wd4=N^mm_ZWiz4gl$)zl`^~;UAZ>mn$COGS@%% z3&LeCkE>1@9+z0ZQ9pUEf$MFw+wpfr2CTf=S@e5iM@~u{_6T2zztecw_)fn%3=V6% zJ+lk+964e5`2C^L^cY_+m>#Zk`+c>1=~LQHT+cWUdeD!le|(+n^Kd`mg7NWlGUvlz z<)_$Zv=4n6l=(EzZ(ex2Bk7Lo|IU|Go{Q~Hk#;$5<}T0qK9l3T-{dz8yPO|!`9AFF zy>7q#UL*Yx`p2N_kDtc9aUoPbd6!W82R};!y2HQ*>#ulE!StQ`j$z;q&o{Z|c@o}J z$RF%bxcU3%TXZNjrZ3&nI7B(j(&BL)B=|XL&U4`>i`b8_2g8V8Z}mXm zBY@-cLEcm2Iw*e!o%iObAJ8wr&0BUEeSSVAUts)A`%BwP^so=@yWfcRZ<9Fv)3_h& z_|*5Wj#)cAe;D_(&S*O4Nt`#=-?Q86`KP`9ehr@uKiEs)6%xL1-xK~U{B!bw`^a^> zXLyDieg5($3&V}pZ~2=n3^%%+dy~t>jn*Ien=A|mjjsH5#$7*d_wonN8a=l=yn|1B z+}m}3C12`%^WPc9ys#o5Q@g1BQ?+(Lw``xpeX%gd;m@{wp7-c%oTv%;osOs5YuvL( zMhYMEWWb#!VM%v!#gDnu@%44xe3j9c)_cn9eOSV%4=W9i_;QfBIVb}f9U9P_I-U{q0D}DdtK+B%PG$fSEZ7CSHyGc^XWlCcml%IK8~#JT^I6OaSj77|k0dPskRbn;##_GQ3t-e)h%`We3C`mfx}llMFD z@x31K0XjiS8|DyCgAe|K-p(eI8@>y~@uV#GL-9d==ZFKs@v^h@LzSa2Q?teIGkCmTn)-9! zmiK9hKks)@KWhV4AN`2&5A6aU;(>PMI*Q1x%jckv)Bbygl%syXKN{OvY;d{XP5tG% zVVkehZIf;RN6`-EfxPD*c0yW&&+ZRkyg^FNdzG#~>A7wA2OJ044&XL^E1`duf|d0y zgCG3-WZP^@Uv^c!AHY%kJ_ULVaNgKgx6^!w~4~=`a^3W@k|BRFe9L7H)u-LyyC*0vA{e0xA zBJJbdtEUV0@r{yx!E#3XJXI>AzV|QQp`0Ocyh8{+6y==1!;;GR9HE!(<6fSS$ZvaV zyU7L5)1>D?J}C9bmw5kX416jAExwC5V4$gYW8rh@^Tg-j^TcPh<8!|JX?ULaY&%bU z=3gK_|FG@(_19Zde0+XYyV3fCzaPc@@l#=eE*fOl;@&)^?ysvMT-A{ylC`(Jwqu)vQy#*hr2Jl^U zuh?^cX8`8{l5ac5m6Y!NPUj|B_viZ~JRi>c9URwF{-7THK=faSw|`3Zz}X*lzHe~4 z)@hiw4}UL(yUy|1eW&o<&$n^iwn$Iw40F&@c-sr`PD&j3EphyQSMbaG`wXAmo1M>w z--YnGbb)-{>~xLbv#&SteEwK`M!l5JE1iy^G5PFtEik%LzMLrVh4_38@_qQE@nP8H z^nCaX{Yd-ml*Cgx_!Z^zF6Z-h=d2ARnr#GvE2E5 z-!S}_=K2JIyd;5U$&G6VF z{yN&B{p0zq>X5DsN#|g~yQ~H^nyFXcy*KNUoIz4B+f32UN zt$$BDJ^v~{rNH?%f47W%s^5V>f!%wt-#%}pJkZaeU&VFZxb70)pE_y$i|Z^#2is-; z)cNiC3yklnJQexPb*6ReM)SL~(Iy)7C*!$Up7VEmME-KUsoY@a6V6Beekgl0^wTJB zDZcPqV9#DE6Z!ai(#{8#=X=4lr(8Fp9pk!aaKDx3r;F!TD8HlmdExfvPeea^eO;rj zp9beb^z*NTKXv_l+T_6XlkXoB-`)ZH9TvXF?Z@n;zOB2~<>R!TgOT4O8g(8<$EC!6 zo|64t@c(Vq#o$I zS?FW`#PuqNm!413aeRk1XTQfT@(z19<#Sk3u@CSb!?}2_*X*pPuMvCMnb|%W$GP)e zr!9HC@%TplO!)+SfzN0EK3V@NtT#O$`nHWj-|IyF{yXS9lF-L{`RErRUv&UIuy9G6 zc0}-X%dXv~r>WdOE#pF4+biy0E3pwibbtS&PS{?Ws#hbrxQ5~@Jhh6?V6ZCue zo(KI=-V5vX^{1^%&HoDr%)j2cxPs>89cHu&yAElPa0R$y{xU-Dr$%{je*@!?{68D- z{e8+e<)eS{S*4@?UYp^O+J!Ta-z(9ow4d;OBJ>iC$%lTceh=q@${Oz(_?p7q)M9+9 z`n%6v{%&~~u=mL7{IT~R$)BDf+fUsT`D4EmwrO#j!q4ZL{mG}q6`6+ueWM;wA0@WhI|XV)c(wueC~&F+y$S$ zCwyZ%<*(RId7|N+*873fOW}7U@W+EQ!_Wk(__h=8P_=}$JIpGkaLsPIo$_+P`){5n z-W@VNrSMlv)6a+gCkynac#?klFTwQ&>#yh!qgKYjxi8i~gEOXUrs4#<#Y6 zxWm%7_FB2TTG9Nx!QjOACH;4t^6NCaKK_njcQJnC3-)TCfxe#9{p4?WW@}D8M+pt1yoJmE7|P1IM&I z-tUk14*VQ_(s>xx0Ef?Fr^dx4TE+5q6E*8hr{NF72&o{Z&Nt=?)}<+7&f~X4msWfhSyrRw`qH) zq&?{2{sJF2;J!>%!DjP>AK*9V!@U2Jb07RsGi3P|D<6gp513&Aul80zh#dck;pg*O zw3~d}^SKtQuWy*2%Kdx%?g(1qJiC;+z3}&_c&}uJ=vDG<&z+7U-H_k)Vz;=S(^@ra zke1{6##$*y`#?L!@j5M!{sY{P$nWFS^+GmbN?T8&-gQeqpyi{F z;$P9bM>QDTz8g!lyQk3ZW$Wtjxqg=7k99e=2fZCG)c@``q#uH{%XgaCFSYwD{pfVZ z&+Sq;aLo8QVXEQ}dFuOp8=FxhU*Nx=+>)I|JjG`}@HvQ7vo{FS@!~e%(65V@br-|5XCw{q0K<{ch4vn}?( z`n7X{{oW(|qp}nM{XfUSL*lTPSWy99dwT^p*Nc=7l-EC#@v&%Eg5ST)r&{~@dJ{md zm!;$~5@LiJRt>O54!Idbj{^dOF~$Y0F&i{sRK z+GkACmGB{zN)IC11ZQ9ntH0hxL6KLS!HD&y>$ya}h(_{DZE!XjSCJ_Yt|j zmM=B~$nhm#T(NRIFR~b1kb1r^$n))S{oCPj{>^uj<=2}!%2Fw?2U|v7j)?@hlR&(V1ExHnR-MciKBXQJQx=HM% z_`~?HPXi62{Ec<5_Kffs>z618zvYgCzrPHA@UV}+N8HXIui$#bvfWaty|<_z|ygvcM|>Ya*6zhzYcq0<1&A*roOJ`3ZMQ%xnZ_?dgTV2XP*z8 zz6$~pW5WVQ`b9ScC;+>e6W;u zw8wvsc++B&x2oICuEoaqF!Y4+Z?O=JdVVjKcDKjh8`$J_H@|PbmZKd__YEPhJcq^p zpkEyJ8z0A$U)n9&ZN%mO>fcUD{B8JEr%s44`-gt|)wiMDe^xsFGyVMZdhMU#Fa}!AJVxN1aXR8;jm|DZSv1^w&6it+uI*_-AX@2Y-ozCP}{9L%-# z+c0Q;B-eF&22C$F&27_m^Jx<`gdKt;(GLA*`2W{JSDpWOg%bATN2Mp1{%G}NuGzs< zKhR^*o{iIQlMMGL;8gucseCKLhp}U-=@r7$;x6AK?B6_pSJDJ?}a4-6;AQ z_3_o^!r#A(?^OA@+|(X&9R+lgF3Lw*PW^!Oik^;h|MrjY+ie``Y_N6jSbvF?Bb+&t z7G~2WiTfw1ztMs5#m8Of)yucn?FQ(=N+0aUTV&p!mRnLN2MtBJHy6s?P$&mhqulL< zayJ&rVFe52ZZ4F&wNP%dms^#T<9Z6}cPHtf?}0*njMFH0eNqncz0f0sWDE!TSSca9gkpW*%$^{Q){t=|G~$X#*0fpU||-&r5;EAmJE{0+DV zd-RXmF7=pt$@b!W{WAj{1+~#>MKdl^cIX`Vi$mpq^*B@uSY~!?u6c_!}84M7eRU z{$f?R@pXCv4fVj$a$}dSyp|h($?o?w9@byNDmN}ve9Db;vP-nwyY)PMx$(XF3ti>L z8#0Wf<;Gidy{g>!`V3uGZrrL8Rc@TGa!_tupf6saJ*;1W4vYZh#$U-^qTz#CtA?-0 zUaDbN)~4a>vWkXVvvv)y&A=MqJ4?gYWwSN>IrXEjJznQ~No!kr!((YWZlhcJpN>eM8`Jk}OUwUaOn>!z>*>%RoPaB355@d> zBjEjPOrM|BD`iV#`Zq_U%b*~i((%4}JM_B<%vPvgDL9S>%up_1-(8 zo*c6A^v0xp)PpBc(%br0?`#6Mq_+wz{auB6=;u;a$A8-UQ~X7d8|D!m5xFAH#IYrWfJz0MK%EQ{%L9<1XDe4x*z>C;a+mig0ug@g-@b~FaepS*A@W6P^_g9gBNg*Hhh`$Ss{M!<_ zLVehcl3EGFH&5C{{^gnvD`WZ90({sPz8??xZ!Xk_eJQDxv--OV?V|@us?C=F^GSY6 zcWa?t_!;qBowR#6sRz7YuKAK7AMko{As-awes7ugfjN$hHSX>5aqlBN0#63Z4{Wc? zZ#)OWeYSW`WY;;gPk*t0^2u}1bJTxw{X3yz*<;%ezlQ5!NPpt$3ExKgd%k}8UizC_ ze!@)2mG|dY{qf^GFNO3^9?$*`>HoB5>4~v^zwN_sYUFetu;HKhLOq*UwEn?eSrg`xaXl#JVm# z@f2>Ypns{prSFD*bp!P3FI|t+G)Vl9Jx;y*oX0U*qI}Kc8a*$)yVU7x+VTAC7sitx zXTAGv<>Qauetk>Y0Uw&5Cm$gvKhAu7xv#h_Sjz`ruD)_?6iBc#Of{0_^=SK0jsj_+G0zd{e!rQ=~U^!1>X zpC~FKCF=Vwi!2@f#PY3m{oy(Q=eyw{J692Q*|~~Nzn>Ha=9#{>yiUU~(B|>$JU-py z*Lu9!<5z0fJMan(x3=7(A=(3-TU%_sAhkPB74C&#{Q-EMmU|b$rVCk3Yym#(Cxi2$ z>ii$H`yy-GB}3DtBErG5dT(THyZ1}g?bM*XGrG3j{H;)}ptzLRX?)h&4lgrVcRHj| z-PZL{n%;sQ~rJ#`G-9}StndvfCqU5yuU(uUpFtVm!RBm!Qstg_b~YG)P#$#j4ouQ~o);-)w%^rT6~g7?`e@|SAx$1r4!>WZYmO8Je!nMl z5nrw^rhNMCBp>|#`vM%UkA5=c&lqwD%_?OdQ+o1M=4Xuh9k(kC|L};*(W8Q(eBm+I z%lB3^&fo9l@8$9LR>qny==@+%t7X{lhQ9*3|3&Ocu;rF4__-|Zdqg|Y>+SpgN3;{Y zv=g>38SO-`;m7^A)^>QKBG0n835qa2zCG1r!3Xm?-~)Y4?H%w&dY{M->V2S450)&} zbNNMl3*-$#D<8)X-izoGxxz<1r=3jOJqA1;wQ_*B(c2&CU(tW`eWUn(*fHzh#DAoJ zHJIQp?|Pp_3wRd?>m2EP4*kRNisw|I*TO0}&uDT3yxLF>iSl(zSdnm>hge63{&4>h ze6aZ6Dt_P(;&^8ZA>=xKfb0C@d5JV10BSZYWOvQ7S~p*5;WnvPkw1CvmG2~ulJl8X zp64%8{-2WeLEo$Hw0<8spCsQ;JD=&dn;dd}4Zof9$#0FrcdS31FW*zYUhii*f5?Y! z;Rop6<{{3X7{6g1L=J_&%5Ql$QTgrs)6AqF?@Ig;&69sX=v^HayV?7R{mgSjT|SOc zu1CE~dmj9LvGaT6yz~6|&3WfD1*5L$X9)9elOgi|W7<4a1Q6*L+Vg99VAlWQA0auWPRPd0oD*#dip} z?^VnvKGZ+H*BCA_c=JSlF=Fz*Anz0K9vkpnB!0XMlS+StbA1QU(Rc5l0&5qUBH$f7 ze9#ji^W0HSuh}xao{tk&%D%T1T!V5NxA!E$e?W@oP23*wp8u%z)0?EQe9?}(pTc=p z%J;L*ckF9poBAPpl;e2I_kL4*J5^v*2kjmK?-z_`_wrSn)i0*~lY2WB zH+LlqxA;76n(?*uJ`1CM`g#0k+eiP~g1$gf(0}(PatuBFR-qim8} zrU0+(@ZMG^H=dqWlXB!Y@OfvF4!pOIqo;39%BAlf-Y4nf=_&j+exRS{nETDW75V#f z%?`JkKa?-np#2r5F46RSfr_oHx7$3G_n4%=v|Qf5$HLv)t)B<1HJq=T1i2dYxX^`h z8}$Comjz#+S9CU*e!%Vk)!I5MzjorQ^$(=u<33|`_$6jX4$m+cih#Je&)|Tr(@FVA*I}ote~kMn30>qT&vTP5wEG|EzrkV0Z@Bk&zIIVokot^ES~Bw})IAp}M~p2saW+^6w1$d|v$4R@$~#QvLZ|QfP&9PC-~`~W zw>bNsze@%_%}DSB+*dMs*M*Y;R@-2aXC^;!I% zDGvxR|1dt$u72U~1pmZOdP$)iY60)h7RrrhS5FkmwHM%VUFmlU<;JtCznPRHpMlSx zCh4%NKR1qD{a8{i3|haV{vS&Ecy<-{;;`>{91eqgVZh|NYlr(SKA-P5u@w7dj%jL- zq4Lr{st4(Ktnac=4u{O1a6CqTuPpR;S>&bmRz)LQw#NF9=k9ra9qX&>3iZCfL-6)> zNv{7;KAUedcx<=L{Tj62SAg>m0;jgw%O`RV|1S(W{#!j?{2+XQv!?*(b~%3?29_&7 zcEx&im->bwvG1^V}toM)xkt*vW!tWD;FZz9w z>9v-RzxN^iZ1YL{EB=t*tE~F{*x>hG%M)xO!uK75pLa&TPx`#|4eHY#)$a+9w#UZ= zAC5D$tHAG#f?u~RzElLx&F(Mpo-g;)c%LST-Q2 zzoXwd57-MIeZF;YQirZ9(LP|j1_Z!AxlQc0&JJvx)r#_uWJ$X((`YqVd-R8}jsjPh z>k{;n*X|Ss%7?gy5*7BGTj=TZ;M*?YfAD(>q+9(RfzSSC|K}?@BvtzRLDT>IzKX^DUQs+x_%pQSsb zT$hz=b9>$lBIPTtmmR&v9ZJ4F+*Ngb*{1r7IPl$6J3hSv2@?UYEGQus`soZ~;G+(vL?47Tl zb3Fj?58Z8c$}Buu&9--D75xMHweAbXdnEAph*N!$VOaKsPDFj|d)k?;Sd6kea|m5q1xcim3=`0>=J@#6{bb6xtZbHe!L`_Z6Nij63T zbxPo89)-day)ynFz4BkohvkAFe~0mf;KTos_bT|V1K;Bviw{f2v@f%jA>=FO4bU^_ z(Xo^-3#{LY{lRyzxX(ITPTbG%-^1hYzK)g`lk3s)VshC(dD!KCkITz`4O4%kC@=6= zNEi6=ne*h+rOv0+-{3v19Gh$M(T>#Za=WI3u90^6|31C?@Okp-yJBZRZ)%tMPD$^; zHtnyXJq|-l%x=t5c4b@rcg$toU(;)MSbE(q_i1`~*!_z`mXGsL521gnUf%b~`MY^s zXF$K-)0Oxc>#aP}=c%21xh8~n&p3-e!UJai!-Hn`Q+Ygr_O@7kzJmlf56F5d^{+^8 zYr8N=KHf9Idv+FIu3=q%UZZjFb9JhB?!TvaU>?l-1}Hz$F1xm0-{|?^HI~J7ZLYKC zyQir9r}6=V0J&>|z4iUnyyXtF8v~h!dCO`IA&)0+>zC59j<_B3O7ky}o_+ea^b+B; z-=F=(yk&bV|CK3aHIm=&`q<0z7SlhJZyf&DN2FHv#$5x)@|Mk7KE>+<>{MdkRwI4@ zHDsQ8k=P}Pb6pqse@w;**++AHJ2d2bCwa?!kDv7XipNiQe1?Xc_hLLq&$j~pCV}6n zw{4{zjwb_-kI*y2`S><1cco^4&W;gsY3-$Sf{yXW1>Kf%3iMxfFCce zyx~bi{&~rvkLJ^Wjqpy=ukU^T|Hj{&7ySGu^J#Yf0O{+0?QcJg^qp%zes@02966-_ z-o}e{GVr0*>sIE|%t~(YcW1HAjjxp1_?+@b>GS>r9h1d(2}e%3JeYj&{4CZ(Q~TTM z=W|Lv|BL5?46PCSLg-h(f1CVHXzzf@cW1*-XXw3fxUL7ApF=**YJVDjpnEL8A*FAM zmOrcXr2P+;#PK#+?-|pN*a7a@dg<-j|Hq6!ML!}bH-!GT?zGA>RpmO-$J;IGpzNPu zL`DA~A7bz?J`xdZ)ZPc#q=W zwO~lY>R_+O_d8vtU-^P19(TQ4u-xN&G~BdcrG{89hMd>mr?LL54jO!(YpMABn2>paKoT5+DUHqLX*o9K=H@M+}>-ysY`f8uf3 zFqUtt>l=R`hJJCrYMt?u{)h85*fMCA{w_)%@ZVwhbKe$n^4Cwxyo}?k=OaC@V*H(@ z6~M>sBlKXewL4(&(9g!lVNFN*vFv8Lk1}#xeQFdu;LCd%{ga>2{Qk-Nb^WV<^086t zVA?-}j*lqQUeKH9$q_N^^iRT|@p~*idHTyH-v&wljs70?LGhI`V|Xeb8_?dPnyvG} z&sA-l9sB;nW~GPs-Q|3g$Im*QPo2Yw6!3ARejL+$q^I|za{nDuEuY-0;`s`sr}we) z7VAHxkGx;u^ZEgkE1q{q=>%U>eYs5VO!KuLhKvu`&xKr2Z@4Z1eSy6L|G%NXhcdRl z)Yk=2T4d7g6yH1e&*~5T^}J=qzXQJ9S40r^TX;Vceo4x|wTsX@QqJ#dB7ekvwnYxd z&toD#?XR_q%%=>OELS+N6KOxUw$Ik|c>Zfxqq<+z0egek8SdoMwVOfaDBc8 zKmHN{0sfZ?<;J_mCPz-{=c>GY>QC5a_)y!aFVH#ygir{8PT2a6VupE@gKADBNF>*hqalA^JnT%9l=2 zIfj1W10DDMK;D->bmE7IcTU)>{&lz?y)hEb6C>bEQaGspt6KjFtzQ;@ADk`u{z$mL zV-%cYfa7*B#bc7fIaYwPUhC)ko_+>@q;>@T6b9>fJRlb$_oVQ+m>MFO>tAr+mR#YyUAtNBQ>lTSnre=Z6hl&F_(S(5i#KtLHhZ zhn~|oFS#eGcy~73s^#;I#_!%8 zdo;ea#q#rgPTzp>NzPGdz1k5iruU|mp9vi&AqPXAFLWsX9B0D&VPfB;))WfTy4L z?v!~7KCWX|j~L&ohd!bFDrH@oUp?{}rAOi_zttnZ>+!0`KjHDaG+uLmuB5Mw!9RW4 z(x1hyy=nJIdk>Eje7PyHSLwOiyOVU-yPqx8Z}T-U^0IzrWntjgq86Q)=Lr($cYtjz- z2Os+<44Pi{wp%*w)>a6Qe5K6ZeUabkHGa-qsp(;>23dHe#gEPs0_02O=*a>-Z;|{+ zkIP}ohf|Ipw1~g!5bobDF&P&QXrSw&`-L7kf2#PT>3dMLObjGxY^G7qx)xy(37q= zu)kjWeW7QgsRaM^SmYx#ggSK#?1S&U_LX4mRQDen1fRBK$sAR|>k=_=j zCBBjtB`4QM3J9?}nks7S=clUVH7m*ZEU!ejdLWOPMZum&*W0Md6F6vO?39 zuFD0XpLIgt@qPGmi>3>lE1P?{LD1!=ob^2H8RyU&8%LMU&<~`ayjJLW-h1%dxO%Q< z8^&G0i|I2AKEm)AeMGlue?*)UzYp>_V7=2oRnfUR85iY?GnJnE8b==jW%e}=KZL1b zU8CS*sBszBzo~I4uWL&+{Ft1KahVV}(GJE1{YQJyvk>CE@6>D}_tF1fln9=_PK8JK zzSPvAapU7Tj=T6n{p4Rw^C=xS?M>wy1f4hOeV4MrM}6z!beaF$dOJ8>^arxD=z2cT z@DSHecCm-3Yp{oDxG&Z2IP`^zwnv#UFQdO7`X2P%ah^ZBmz>P{s@p#3g7lCQwcc!`d|B&F*YC`KyhP+3_U*$!^iT8S)1AZWlloa~ z>Rh<7l?`-oG+hyK8G${fgfzXLw~cXNKbH@{xjOTHc$EiZ7tOS;ctdS1!)L6%cT>52DAmO;uxzf8~D zS#*Cltxvkm?Ul6`sJfc0MxBpV~cI+V9ylLZ{t;c!T}-^J?| zm7f=qAfw0VKAKSZdEx1tUXT1d!;_1!M}ZDs^_^<@dGh;`afTfQc539?;N{DbpX(@J zmi+Yb;_}JmL}ysnK(2?ubs{%nKYxaoHtuii$4~9V-HSjaz)uH<`9)`PSPx#_=FKZ- zQAzaoa<9KxczL#$Zx< zx95JrgBvHffQJ@>8{@+J6$1hv=GiQKoaNyo%YWI*Bfy94r-s1~c%B$oCga_m6NJ?> z&RPE09__)K)vx2dd|CZkG*7>PN6%{lKb+UQwy#)AE^k!1{9_to z$mOrsl*|2|T;7%h){NP-b+nuk>B%puUp{5Y-$Ab*S^eGY<;#*!ubHR67-vYLP*2?_a#rM1 zJ>!-oXRr0(%j(C~UcRh;bT7~ktSpV+!{DhhE;n~js_5IqI()thVX3vB<*t1X2j{ce zD4q7nSw5Fq*YbP2M+mvx!R0n`y7||Nnkf z1h4AjQMpIu^<2TW|gzj6) zd{mZp$WEX{TA!xSlx)bYN z%xlAr9SL~C1A7pmit&YYmkS5{71Mc+6y8TTeKeK6g41`W(hF2Co&QLs11>r*oJucn zJtLfM{vWz&*O0ov>pFyCz{jHEbvN13IDe%6;pn@A8b2VR&QEmSMB|-Q3+QT)b3VsUwv!R-aWd1X#R>UANUP)g1QbL{`qAn_f#qe{zkfu!}a|2BxnBl$5V<4XCla*ZYr zaXeZl@6Aqca;VfQcE=iadgb?J9Fo4t_TO4|n3IW*j>b;^n?cZl@C}_uV!W67WF2q& z{^rlkl^4R#2N|xYyr27*ZQqu4IQbLMe6n75>w~=_v3DQ6eZGz4vnvnHUi4wIOBN^F zSe|w-DW~o8EQiD{;KKF0u+Q6gnEfM`V`Zf)B0tcT?f=ZTufz1Gd{mQe2=DdK&FE}m z*MJ=OR2AJURXUi`@$F|ia`A|9i2W0kWj?WeTsNQKTlWvkGQZgUZ#Umku21ZdLyaSR zzig;+Si?bXf2eV-#(OmEO2O6Q(F^Dr{kxv&rG@DwIsb7DGjJ6gOt-TC>849R+POXW zQLoz9(f#S6#x6c@In>y}@VVsyhfl}u{zx13-{cYYcOa1fHx)Y^O$t9pMUgjcRsQ5t@<-?;3x1&^ zJJ$fZIh*iztaK9wpJxIoPG7`ug~8uw{5*}@`;#?3!|$=q!IRdTK1->Oq~7$G+-^O3 z)8}u-ytaqsk*ha-X-j>2)2FF?ExqX>u2=MhBhi~qBt7g8PH(E{d_(+NrNh<5;gVpc=4!{Gu zFUqg*$~Q4QhvXbtc}~KKS(!iUfTzu??`{vC10Fnp1Mpm=@N|0R8vsxFAj4sLeKdW5 z?1HC*`(LWAvC_4m_;&+TBHPo4!N(Cy#$3{|~A@F~{jH9GD-I zb0Wi9IwhhSXmJs(m_k04NEzvZS!ke_zOM{)WqGM>u!Sa%gD|4kZVKVHsf zpThWc$7zq!i)&|x-U9nM+PU|IH2!9{ncO4vGd;_pt&iOLrl>xY`*)O^*e&@hQvzR^ zDy0YVXiW3%rF?FA*G^N~-pTzV|3N8wsJ6?DbN$J=mNAWYaXGRtalbb=)n}i^O;W82{#s=?)lde8Uy>%RwH4?ONuc`9+QeW^`DGOr1Y84$-}q)8&tXOum9FSF7Fs- zypi7&4qbdLwEp`r(N!}4Pbq!%r`GM5R}*`}xaLcbgN)B_Z~fPwK~FDddg^CeV};_d!(vJz@O)bICTJ_H^-REZlC{Ev~@y}@d z4vl}B zH`k}fOj7w$<9_BV+m~Vem+O`EBe6p~MCDA6F@5oR)o zH|ppyz(?Fe9fQ5$alF62k?E1v2NE8GyjZu z2*1V27RJjTj-BBgp683x=gD{$rC%FJ{uJn^*%`WXjlY7OA@c4u#`c3%$W3x=jm&4! z*()S|h1!2sW7SRXua{CK(akMShGg)H|W?`P?1gPniQANNd#hvpT= z8~MxNdZHcDFIR4%9+ytAzH#S~$F$_m^-^toyhpv){2&)2PtX^OWBQS~w%-n<{@R z_WkgIw)lOOzm;Yy-yXlO^0#8&4rU( zV(FeBkH`8VDIWB!-@-xc$2k)55DXN-9q_ZVg2Nb3J2}ed`Wa8kPry@_pOvSe|4zR9 zz3+;FYXE$n?F|fAf50WqxKDAE>4E#B_?WLhrvpwW zU)H#v;^oWg&oZ|^T5sGRQvbO>PCtKjg^VXw24QfI%zu4@!e`0%C^Rm9&&Zz6@fjUo z_>IQMnqL`P2e|SE`|G9FVJX)scmiDaQ~RK^9}Xw-j?M+@exIB}p!)$Dmwk9zcW|86 zufL(DgVNR!f$tWoke*GAh2NkfG=Fot*)?2v_F!Lf2WRJd`D+osQ{w~*)ezsqDy@L9~YYLfF8G~a1l&S8+hE{zZ9{AA}^Z{YYqSNBq7~(xWXHW#UiuZy4WO)q8MJWs1i+zPGCPFrvzCO{a+% z<+l_NP(6D%eP#0*9G|(3gGAoV!^c_oSMU0J>W9O}?{xikQ1d5J6X@5cy?j}8|1ruJ z%R7g@30;RFuO37786RW528K}o`$7L8B6`B$dhX}I77{@8bmzptb|n4%Q|~^}YN`kA ze9-GhR)62WKtI4|Vel^uXH*utM}G>GPJV!ezseM$2kF>H-3|S z_JrSLzuo1xMyk^I%caXB;ivlVf&cFL>NN1xgy1#02v{XLxwBRUT!^5>EazPp4F zPfv>PE|K{##dnt!klo=sZ=Uh^&Ga>wpR(>fzR;t?pLq8pmr=W*lTI&R7T;Yq551DT zfboL*&I6wbdWe1xv0N){ZR7W}9+U8j4#i^&_rE(w2S(_j^YxOxtWDE}VUzTBO;@=U z=kMV3d~PL&mLKDW7U*0**ISQ1l65aNb@WZP9CHHh> z;Z@H#X5G{I3BlvyA*+8s_VQ)*@4y2614Y_>NLP*vT^5)w2gk>CouEg3Y`B&lb%@t@iCmx4c%nyPru*L{*I)5n!e3eN9O-?5nPz4eo;M+?$ll0! zFSWLC7}>fp)~jH>1)b{qWhCejkM%3m;=cFgy{wy(@&(Bs>s$5nZI--$r$?{9_T)Xr z9rAgrmoH1+zhxe}j>>{B)b|>qN6br)qx!?Z_HhkQpmOL}Cf_Z+P18-jTe>gbExm*D zC-Pm=6ZtOjdgMZueBa>VB@2J+ynI>my|+&MJy-E}CiT$hBMeSa`Dgv_(*D;^Ct33S z3J?CQem=*`mnHu?=IJNsqQL!9{%Vr`B=TM252t*8q6c?Y{~qt<%j)0R3-k}7#N>M- z#~V^|ob3d<9~4dW@O$u2M1EMJDOvwPt~<~0N=-1o#{~iwPqOi+?Gf_`NiR9w;7Fo}3m36C~qqFa550o$F_uaV-3^v(g z<9_`S`JcxB$>-AZOTJ2dp!@7g z9t;3Me#u4b;mX!A-Andze_cG9-H5WYzq5^=9si+!BfidIREaJZ(E!s^Y85`G{UqjN z^7E#6>lV6e68lS3exb(2P7{@%qj9n4MCE5{d|c^E?Da!*4+!lHHA?-shm5!jca~jg zxLfA&R>~juJNPcc7Y4U-JFdMO{Wp8FokPNUzhPgZmxAB!V?1d8l}-&Wv3+qHprm$b zIME>LDR}kVTUC$HV^Ytd|3-Ni9#97AY4_^+a#cNZTrR2SV5%MvJnHH4>iI%dJqNsc z_NVHB28en#di8v!s-AsbJ$qC20K2GX*sEuERXwv_J$q91fX-3Rm{-rvs(N-yJq<#~ zE`E>K^1HqAAL8;p-S5|V>wtt?_i-4NrGBzIXY(jeEhN3tEa!J9_5c3{WZQg;FaH4 zv%e$K&!$oBuk8!|fJUGAZJGo2^PMFR4tedoyb4Yompb~p^lQ~}<)u~i)GrTOym~IL zsz>EP4ZIPnFu!zoTrZpFWhLm1p#H~#l|?JTZ> zvwr*^^y>NbLFffGAJ&im;Oo`&|BI@6>c{^IubzLas;B;Wtj(+EKvg~aGUpAOzdF70 z`?UOl_3 z>ZyMmXT5rMR@I~981r?uKC<7d=Yv)Cs6JAIuT2k`^UA-M%lq^odIGJxlpcgG=$sYP z8|^1^I<3z%F7!g@3N;jt_d&Ga}Jp0s?h6fY~9~A6vX1F6-)K zzueZz2IoF*pX>_?hpfNN?j4;a^~d|$14?*1F-&h}TH2s}^f`S+;~?zdYW=fX{{0Y9BQE^I4lkqDv+IWAfjq?>aJt`Nt{>1Oy3XON@`vxA5%}pCPKGfKwe(YLO ze(XROM{2i(UkHq7X}gSjJ{Tg2TZ13B2>jV{Q6@?kA42binBE@?yei-3bIP|BrT13V z`zk{3rB>xvv#ZZT|DX@o4+Y!P9Dexw%c{p|{MXg|@E{p%i<3JT&f?TKhY4TY&K-}Y zM>yT^Mfb-!9xdzQ_xaoz9Qyrt`R-@Wq5kW>LcT%IO~?E$`bn~%kfw9NXFInGI{g;v zi{;0w1kOppXJm3i$Iavp&NuJ%>_h8cOMWMdT%74MM?W{?kSRT;H`)2*Xh6m-pOXxx zN7;L~|Hikwzd`(^=g=)5=(LII4}(e8+lrGnGJO}PWcL2o6$ahfmCe8O*TK9N&0Pr?tY^m9%_!5_(MjqlZP zHr3u3_^rZd;B%9vkA9!%qBu3i?RPhvmbz!z&TwYIFYrR&sP^w+@Xo5AF#Y~)S=*=l zEFTVf`n@qzCmTPlBJ`RdOE6?q{A${hFn= z44$YW<8glTTe*00o@y=YH+_v8e#;3?Zu@|`T zNq+?Hv>!r)dqlr4mG<)oI9#|`-iUg{=iMRKpr4}ODL;gIZZnyGY~C4G{W#KaK*Jj} zEONN1aV_s_yZsp_Jb{kg{afJaep)9)JEmlQofzlPEq5J_EBLZNaAKbF{SIDp40L63 zvlczcxTs$E2+|My9l7IV^z&$$mlz-24I5JPlF&z*ZUkOgHAg7w5Mie`w#H)B73+nVu4PC3?wF;|0u*_%0blr0t`- z{ksT!a1{E_vMRa~`IzWIqLIK}jZSPx-th)Z-N`ETcTFdrYF*ESymzt@xgQA;m* z^-Ywo4!z{%&|hlkB^63P620UTlplUFXxJ0I=!Guf1>!Xoh|Nug0J4?2Y6hp z|E7z+}@E6u|i+I%#qagigWw`g4Chs!_gH)>LV#=SN0 zo!QSZA1(7#~;#eC!Yqx=r>M^qVQdLntip~=~loS}L!RH(=IL;03h(>RtXogT=$ zLGa@`i31L_4>;hL0p)!^lwV>vh82!M4r6`Imv;^vzF&wNJvcUcaG-s_fvYco!}mYA z2XIXG3mnrMIduEgL-o~~_kVgB=KZx&ZlXuZslCMTfcAX9ldm9n6Fu^O&ib?~Lmoeh z<#89|r@JBTe^Ta+v^)2*UUFPG+@^at`v+FQAN zH78cTC;x`=d(}_WZjSw|VJh*Y$8)hN`94i@+}6eJy7Qy2PvpDJ2kv@v9P+=0T>n=} zKN7kAE6Sh9^<@m;Of1)NtJ24V+fSU{^4}+T>RtYQmDjS4gWMXX{K@wnBz*&=1J!ts zA5S`sLVDbFStrqtjq~}ZZRPiNe;~c?=-_r;dlyh;<6dk3^kS+%C68&`P|oZtkT3o^ z^_yhEjLHS3H}W^2{jG1ETJL(oJ)bZ}aF({G*QcXM*L~q*S)Vp|a>dpc!(WG<*T8(4 ztWT$S99;PgKF?ks>H3t$xZ3`etUEA|9nHD}-%p z%z5@wqnoEQ-OMo_x*Ps9wLa*{pcjFAVR||HVW5{V5Cfg8(}uRs9}KsnyX_sa&F`jw!uu<8V{sDBGotpI!R7gYZ?4obv7S&#a;=k&nsx zRQRIa^=YK{5*D)4m-G}ZVva@~# zo!fc|^hu;S@A`ES$?vFgkm--kw{dth>(^bcte!vj0j_oEmB>->)qLyM|3`csRrV_! z`y`x@bpf4^5j*)QGIv9Me}+I6kzodjx)b?sj=yv50na2N)=IGpK` z{+U0dnWt-fm4>HExcY>Z0W4?nePoA^*$!Wne4w+-M|5(bB=9w2ke~nXcZ5&P2fY(3 zHlzz-B0yWwx?AAbr}>+h&yU&^>B;2BlFOIY6gWit zmr^?z|7t&KV*jT5bgb{u{y5vkqq6L`()muclW$}{YBnE5CsBp;Y-*&_Q-EuYoO7?` zM~&_0J2*S1UQ7wg3E5wH(Rn=N#qBnx6na_>Jt; zs&@$=p&tcGr|(noxhGdo8Y8}oD#CZ@=e-@mZ?2yL+pmtw<2PUX@2U?)>o!nkMe4OQ1=MBJ1k(=T3ZCUuc$;+4JS7(!p zKdrYG{$5U9!#G3Y+I_DuxL4(X;iZcKqwi{QSWiE*{OVlm!JpO7tG#?#erLMp=_mSi z2KUSEtx10pzd91n^s6(;-DUmQUyo$@O}os4JF9ej5PS#tA93RzsOm7;|cp}GfzvF+C9RD=@9_c;G zY`}VPV|e8$InJ2eKh<-xcE77E^?(n|PWcO3 z2VuQ{6-*fXqpY9xevmt_?Dh7q%x~H-l>=Nw(&xjkj@pM#OD!B8=$tl&;v#`C*55p5eHC5#PjrlCO6Kb_2kV0_O&*A4Q`| zApL8t?jQMyS9p?jSsUf2^%SRXpnWH3tjAMG!Por46-vh&)oW5%*HAqhw^l&&c z%mLd@xu3Vu0MTxgp&)0m7UcNuis4t{^S@W3DrAybavjC1+*b~Y^--!Q+;$iS=9)G(3CgWWZI_O<) z<0S?%qZ{yLf#4;(73ZHBqX<1wMd%{m@OX~XcY&ln{Z3HST#$72&lJV?<>eej6yKLu zdC)p4Z%w{Gy7qZ{I;k{2kuU;|V;$9!THM;C2RzR2hPfy;%#caE7JzWT*#y(aYNp@~2UgU`iqg3|4~5Ci3VS^w?ErY5Hg z;Ya0vH+`GSMP)hfm)!5WPv49EE-L?n#%+H|&bb_mpSlkd{xLtc5?sJ9p6=i;6rRLx z^E2|R*&Td?J7DLq(|!r(Wc*Wp2`wGm3I3)A>GAFE)Nd(Yw)_Rom-r<-B;ygn<7=}OfD?4q7SUOgYHs;ASdrz2GlC>ZrDy|;S2rmN~{ zmwL=kkAoM;F_drd%9pu34Lm&wJ?-axecI2KF!uK+^(X%R1kRMdze%o+?GssacgUmb z(W-tZ-PP!a(c98*RO4Z!WUn-uJt_}s z;EhO~>3xq^{<4~Q8&kZEE8YZuvA@4M=wzSQ&Qq)4tRHU&y?V~Cs;7Ru1>daZkF%@l zQM|?Y?@!4a!`}+8p3|%9Q8`)z|0X}%yz(b;d0*a4DgJjW{$(6ue}8r0ztd}HNfn&+ z4{SIL>+X++9^q{o~l+&D)=?s;B;OEO_{EIWx}f_Y z3|HdsPv9hdob%EB41F(hfzC&3T;u}z$ zmGnt1Kd1F=m0zD23&GrA6veT!1lZ_nS~M{(Zt znEn09`Yk$3^uKsN_?Z3u30-0RcBKCPzIid}0aR{&e}Bok^DC4e>r$MXz&aHtt7tth z_O-I~3-%4MD@?`XI`vPCKc*M#Gds`l%4RA+Pspo4*b{`#$ZrOZw@Y7U&+H-lO&I*0 z*j-{jS6yO_ zzkL|_C;BCSWn(ITkJ^uJqkL{Xaz1sxz`b==!Uez2u$JqO{UnxqG`?5*UEafZ|LuLB zLE3ZswUPMP><4c8ev%KiZg$fLIsX{L?WW838AdrhAAEu7#P@HAbM>GgJI4sSY=Po8 zX_)w%d?G7-k=}<->}UG~Z_UC-_4}I?I}+@q^pET)Vjl)SJ+l5LkIhb1oRsrg?s;bL zE8wor-=x@kAqRjle>~`(yx{o{*01EjSZ*~FzZNH|{h~z`nfLOG$hihR8%S;xD17lP zh>2W02cf9NB+pb1H67x5Y5rz9Hvq`4Ks_IC?4&Qent}_m+kxy-P>Te(4QW!Kc(xb+;qV8MB56eHi$C)X3G9kDfXMG z`%+hn9F6W2dt~Wqk&C5=!EfdjKP36pDDb=EgnJ{HPu%ktm``x70(ku5GpHYvdOu`J z?u)qPanHk@Pkw;>6MF>@m01qm{J6(~dheoqZu-&r&6Il|iQi1Q|3Tj?RDExp$Lo>z znj4u$mu+pjOR zu4THb+wYwE>2SyMX#LJzT18(XFQfRLsPIRm`^rahFLbyrzjM1yJ~AJ={gH9D{raQ# zJD26>=x2Wm`PHTLm%iu!`{j3T730VJLeqCyS)L~Tj!xG2Mckh-SkCb<_`f8Ph%Qaf zQ2os2zty?NP`*b}Kguy2S^5Cxk!_?0)zXjNPky)R(T{G29;NFy)1Of9*C_o+^rHim z{|{e3vUyGJ^+#ouGbEmXqQuV;`S+%@WZoOqd2d8Rn+FFqE^=!=KX(Pl`6*DFoJ->M z>CF;{T*LwZ>tk46u%7h&-2I05G1Bi2ko;jfjwVD7*K%{IVY;Jh}R;*{RRt`QRYqrP4t$uKXs84c3wSMSMTF-qI3GxlUnnJ)VDhK zO?sc6H+G%23dMN6%|G}L)`!yG%H`*BO7;2?>uG!cMQ+#ZPV@PR`8%2)Y~AOstKm;A zo;SEQ$UU_K6$L6gmxg&_2J=jf`D2MQf5dhqEnjPWy#n(GEswFjzCKvS4Mo$^ZWv_w z!LxqjR8uzIdY9kFd}HGZc{WV>6F+#;&IU@SfAKmx_JdcZL{0DH^}pn|@jw5xxAJ?t z7m~~q=7+n3+fVz$6MCq%j=uOP*U@w9Fs^%5UW{tL_h?-9QC+zJ{x!et^{#h*oBr^| zJ$Ym6=MUZk{d1i8_L%+Qk$zVtclyMh2LJJx=N^84c(Xbl?L0n-zo9{;6S;>y)L6ei zywQyL>nTsi{58gSiY7)mbjSZ18h`L}f%=Jg%=gzmc}(;qd{S%u+|G2T>*q(%FWyK7 z{roZ0&j{nAyJ3B5{Velpdi^YL>-yQDld~TNIw3#K5I=$Wc`^Btxo%$251!Il><3Tu z+25rfylblHN#tUp7YRSqyIxMtYh>varWY9f-ADf=@NqYZC=sADR?bf5`>>_=pmY(y; zS00(3Q-NMoL(lm)O1E`#J$lZsDgW=Qo|EV=ovJseylAp{>f!f~HwgLcta~AM-E|!; z>E>PcK92Y+sthxIl3j+wqw$aTr6P^5qvve|TsJeBv0d`f3J2Dim?wSz?vG(O`W23i z5>BXocNG5dKJCHNm?Ir@-YCzs&WmcU?GT9!|@5k=r8Q-Tb1@rse#@HBO`Pu1mGpOn^>(!TS@c)$E$5f?OFeoH zFWG-zDtImPYhG7MJu5gJ_3S`B@%I?}q@F3kTV&s3)c!^lsSom}-#bro0p+p#tytgE zzhJXmdkZ#UT}|=iJB)aX^=~JK$@dMPEAesz!$<2l|Q&91VE z$O;7F!fD_0d@A+F?r+x0*GcL~-1napkUm;{PA%lqthLgK zQEKEjez5P{6ellYJlE5Ym4HW%aS%NoVmRmP&riNU_g7DN*&)CY2HhOaT!k3n>2e8a zUy$W+sa4Olwn)19-HI+%KHVZ=sdW$MKe1WMuaNYi#TIt(i=o9dnbR}0xQ#Uiph4ri zH6CbuR^rx=rZI`XSK6D|DIxr42ABs1Bo6vR&j800Zy>x)Yd#u>S>)66La`l#^6&BF z{STc;TQZaTq*r_?9= zKx9XgewAlszH90fd9`z&#D{t$KD}4s+q*cleFeyGz!Oa=zHa8~NiS3UUM6v~tI+;B zw`b+(91quL{vYZ4;}WNSqux@h%)@>3y+qX1M|LjR&!X?mQQLI>hrc^lx?&H%C%umA zw|g1XZ%r3^G5euQPojq%;Q7K$$9UPkhMPXl>1lbkmebREp4209E?rNup2zxOsB!MF zga;WOe1BHrdo`R*!8u3#;OZf!=bcFWU!0tiabHpp`me~i$LA4-q`uPjto{hxrB;J; zH^WiY53GYK7#*TD8aMRU_5q_ELSO0c_=ugnxbs1V&-_?`UT-5g6b7rfzEY#K>$it| zS5Q7T9ql6hC6sRWAdD`}A4YNKFQvUQSI>G*rL7o+ z3g3G;Mtrkf@gC{B0;t^}Fwp{#8o9 z=LBGf-V55|@_-Zg#5+4D`F+Z7_6?(x>-qK!l_yy6guIJQ<5ksv^i#&JI(_b0y)6f- z`fuOQ-9YdHGT;S23@_GhG$G?<^Vx}d4=c7;Q5lrqbs_!|+!C-q82tP+;SKkHx^s7N z`!)|m6{*+eU*uzXU6J{$cloCze;KvPeiHa7s_bL>0$x|s+1_ZU&`JJyLK;0}?`644 za+dRve|wJm{AhLw)N=;vnb3NUyN>Iz^$(rH7CF5`>(TiX5nP1W0`1|eJ zzkz1&y`CpUe?d})$L?T^`)l}$%6l08UEAKn>FN1tsm>q5-^sicXu6a?Q|Y^}aRtvu zeT@w~Kdoz&`DduH%=tGpj?4E%n*IePo`!HoIt0+Q3k z$%BlC?j>ikTz30CK5st+-ud?R>s^P;QacN+LqLzRPIxZUU2*4Ec$|vLNA!L4n(4;R zS@a$T7i+nnG9JQU4aZH7FI};h-3d3dofNUKDxd%CSmBP_|!uecJ z^g7YwqZ>tkr}Yt+kH)2ck-`28^Edw{Z~r_n$HP zX_oY8so*ou-i2s9dvtu>D(|~b5WP@H%=GJzL&KmkazSYQIZ&Nc_w$d4J|xG~bOHK2P(%PU592C2sz?W?D4e{EgjC z9i%7PBjldr-x@Dp$4%Aw zC=2I%ikI&UZ`}=Kp}scCN8cA>db0MBPTf2lsony)0E{Ai#Z%}%#r^Yoc}kD;p5Xdz zg5UK;DnyTxUl84<tkEbRq???vL0$gJJW|mUzrRT?q~}ahu=d^ zA6O>w%}pmtzseFvKMqno&~ttGanKF@y3`q;Qd3u|{E37Yx+lZwrM?ykw--1>dH23| zsc9*vll*76=>D6=4{E%F<3o)-v^E00wI8M`C|q&4kwUlsOm`F7527>3Vc1N{`^O^QL9yc8)m(M;-^a%L@{U8kPP&!dQ zod@5A40-Tz56%lb{5)3S{0lGNv%Gwu2*5o(Uw?{}i5|B<+q6HJm&0I4=xlil=S#`= z3st@^Z;Rho$@dFYjx5iR?-#0kU)CYzi4Lped-GYGUJw0d$@jN&RTfKZ)^!8@T z7ta?CU%c9*Cz~%Kuih;Aek0{ui0({3w|Tdg{DofyjQiCzj1rKUs}U)GzOW;8R|{Q{Gw4&&`A>@XJRjU%mKt=kYOG<6``wA%?*g zmHVQ%+jlN%%^!Po{&*LakIJ&YW&35(q}UJX99h-4)|x-2GUkulsotZXKg6!+&L78Z zN${4;AG;a8Wd0C)=zQ}BG?}BGKemW|Wa}F9zx?peBj+76|7`H+?r9#~nclz7%a=v( zy08&7aK5RrB*1?7}QB9R2@$wu0Z}X#_djkL934>AIAMxM&^lkTBFb=m~NcBx9 zeIIuv*F*O~MDJBQTC`(DiciL9{)OEM6p#J8;2)BHquwQdMdLF)rh36Rhuyj7^A|;I zANML^4%h+UHxEx3JdeX@o7kP`9-oxoMitT%>j~SG&(x1Z^j>~Vcv1aB^}|T{vG*Lc zcP*EC?7U}e?^-VHMH4dr$M&ve1+F-%2plVyKb_nKc=p>9yn(Nu zs`=jJ<;&vN$jkSD$FJxa+P%@sm&LEIrF>a@MgHV?JW5Ss?~KaT`cks~7J4c530?X0 z2Y9+bciwop`sEAgeY`&w)3?}jiqmH>Jr*aWoiMn7=^lIlO0sj$+53r45I%W-C*`L6 zDrci*65qAW=u!6J;_;s1?EKvl-~NA|C%;TSKL>cUp78&#hiRO-{Es`CR#e{>SvBctE|_SHSp! z`orLFcs!$<+Za*U52Y+LZwf!>7f}K|NJkDke}VZGahqT5dry%pm#g&cQIc2g`N8)R zT*c`-n4XK1qavS{>^Thl`Sj|R`{@O=pXkwFv{U8h@w>SnI2Ti(dR}}3{h=q3r@}8r z_xT*Gc+_47UD*S5%arLb?BUwjSAh5X_x10tEKb8H75AiB7W zs|i*gms5KD9w!W7Glrggm#qsV^u0Ik-v(l8N(yGi=?^`a zk9o z1Iq=j?nO;GR7n1ph2EDdy)`FryYyyu7y91)9CBE_rKa@xiCNJ7gw{iYh4HcT6p%C5 z5)a`#8J^2PvTdMGoGRewY#qw zlX&@n$c4&5$*29O1^*P$n+xxigfrNEAgA;hjw(}J@5<$}j~|uyaGda|?d{h1UX4qB z`i>6AQD2)Q$L#w$ZolUU4yupgMgHL5K>702I#)Bx`GxL>8l}HOjeGfg9qAbyx_)!{ zoJ&RO1HUnzixS5;4Skj7*YW{@U-xruezo(xh<^#|;j;AG;HC3))_=i!S^8b8pJ*5L zJfHU6?L4cChf(Sm-k$*bd%wW<9tmi^yqoD~{r0=Ko%LJya7g|gxP7<3ZvUV!-I}4_ zG|~FPZGSiD*TIw78UGgRkcmCQKb74ax_DWJ_Z5Z1!7Fv=aK7P<+=CU$2Z#_zLB8Qf zyg#3Bn9%r#Sl;Cu^m}6s@8EeP-*6S5bj~-7$vUTD8?Tp;julD1;WoZGlW%xAuj}#+ zqr9%qHw^K9Z@!_APwwU$u4E4^fQL{_<%;Z~CEw7?=S=bqH?il_d_#9|GQYoy&spUg zUdiW9@(r&JPUZAow%5A-k$L?~JP!HeZjyc-cZT%qxPtWSxF-bA^9D|$KlJ2jos5Cw1}r6G=zH1Nr01CoA85++AEgo)7CT_c<*m^+$D=`)e&H@;VIunEPw+B>lOO zE4KcG!Ammoy}l}6{czk=)o=P9OGf?CQPw|HRe$|(m8$R>1{X41E}eh{$bOkhhnCG+;m4BM_AlLZS#Lc*RS)D5-A7HO%efPwQ@0*)l6`O6O^2KagJ-4c!K`TK zcsGy`McmgvPFzKa^hBgP;3>6=-eYP^MCX*(Xa13E?SI|(M!|%bsOmq z?)`=iM~{S_M4yZ$eXO0^%jdSTh7pz9I6eTOLC@-jpXVUAx*Kvl|AxW8LoCrfsPX^i zuutykMw7y~(X{k?^VS)*Z$TgJciOe{imu+Y|2NQIr5y6_-wh6t$L__t`DZx4+`AfT z>|%J6^NO9UKe+j4DZi_i0WawPs;{8`a=+5iM;UIquOa%V-q$I$ik^&e(97KV_o-g` zYO?3#8=lMffqsM^`G%c2(bv}H(5rmINvc=9DTg7*H&j%QdVUV`M!w-isz>E>n2+)e zEo`B|IG)b&9P3eG@N|f|Dm&3`>St7uahchSxAguF4X>9F@E`bhvd2_D!Tl`iJ;E?} z64!@zFrRiGfBs^GZa;xHv#-poPwKmo^#6fL8Nd9J!eXY+DWR)qTIea-sc>zQa%MMk z>o+{!Oh+i}9#lT}0VW2sf1z9l;L`qK-46@UjHpe)@dSSh;;*AW^gu2bD75teh#aI{ z+B(McJ2OZT#J7)1{H+qleKL#>?jeJ}Huudkokf$9kG==5ajB=&w_D>vH>JK|j?;d* zgzA5*v}UcuujrBRYN6j!qwr5@yWp`jB={?B75oh~_H%wa-{#_N?Sr-Hd+k4^?{^g| z*RlPqxMMAcVekOsx6~){W2muV4s`3*KL-BMc`l2-Kvxg_2z2!Ur7O7y7Y6?<<5yO^ zQso%uT6FX}=0{z}f{2obzMFL&z#_Z4@FDpV;dbc!F!O1tbxz}R8b74*LmCe_ELLQE z*0;(%PvUcdxAI+nzrOXKIi4p$F8as=49P%Q%5TiucLJu(>o28SOH$cbcZ^Q1zAia&#g>Kw*(7E}Ubkhr*E_CIlGu`XCZ#NxuZt}O( zD)a_E1KpQeg$|AWT)Nov-?iy(8PQ#F=UvQC#mPOwS7oY<9`pzD9`y1>te;gL%v>k$ z!{CEVFNqxbz;X4;p&t?b4D1yC$shmD<1lcM$)QQ6gA^ z#{5D1ZyFcAi^@W0G*9b$m18!4mSsHR`E_z5m(MRDz~~9}UNGkUdq=2~`jlEl&SHNT z^IqwS9>Ld|E(x#hl(4abLz|bQafwHF%KKdv-8r8VUpQbU5tNhXL`E6D|0KT6>x}PHOtGp=nO>uehi!I^Rig&t? z0hG{wy5<*r)BcUdJN3Pcqwz6~o4#+C`g9&~>9s#&-gy6aNROBp;qn8H9R(v+tlX&c zN59S=9XycO7sHQkA~>x35XXb@gT8d9rq4jhp(nrSuQWAU%MUdkVt8G99P1rL z&d&FoE_dhz`%<79jQ`Z9NuFpvv@7dR5iBlz&;e?}hx7!#S&GsAO$^`1j~Tu@JowOF z7<6$v?)-}ccbs-Z&fdw{NG^@@xS0N9`W^cJSe}1B!S6}0<1h?F_eAf8Z1A_rXsk{DX0Ok;i9P2cmz^aLU{K zjr1NT9pyK8IchI<}^hND|e#yn$&IT?2;!CBx=|_?3y93)`oh5idRP^L? zXK?7ZH?xkDN&bsI1UkCu9|+%5Z7j#~4UZy84t+!Pidb)p^*qss5J3rm(q|Y}$T}%10=5@$hJfO?RQy2!q=We>mJ-{6XcQZa#FS(rU zef8ia>zwZkJotya{2*u}sv(H0Rj*mrqM z;e}tpyI;0Xex!F`96#y3@DK2O>A-uxgS7tE*LY(1UqHa`-S12HHs8VNrR_qO=GV#W716o;I+%$h1iX*~(E$EZeIy5J`fnHj z_T+ul{a*9mFwh>quj#*Gpd)@?b>HEFHv^49J>!0cr)M@%IgICHyzy*(Yqj1A$&Y*u zUcRS#^kYS7U8Hh_@yws%fd5hwouu+Bo zW@!Bw?=}uW4^{YYZqWCNe|leq|7KyxXiG;@-u0i+d=1m@vEcu{Pgd*2S@_@Y<;%kV z-&4LU`BFX zTL+p?-w(aub0R0+%dZ(OKoaA9r>2veu9+T(^tXfVivl;|TPY4ZmG7_Pc1nl*mvaJQ*oyl-nc#!_t@VMU59be1->{c2>%4Y}@@3I4@Z-vByPt@3SI(QA3hD0r zV0ubvNc1LGPceP@PcSaql5x38@sIgG48FxL+;Xrt&zzIwKZNz$I*DW4ur3XQuX92) zrFzp&(U%6+E#q{%2asO`ZIs$Ca}ewCrf1CDBI&^Aqwgg=>Hb&#gdSFKk6Eww;7jyr z(L;}3pH@9q_r;`86!{sXjfac3Rzci_{MU+1I&TG^zS@pX$?UpH04(HzxJB_DFaP`t*2) zKK=0rurIJf_2zL7!(f;@Uex`k;tuIY7`&0wL7&7T@%MnpUkRt%ehKzFe@^l%MUU^| zY=Q05;yir&R};Mf^cj4H=+o9^JB8n(30Xfx72yNFUX=UPmuR0w=`i20j_nW8wD60a zAFz4fFCX*CdVvr19U#BVsr9eIlRy3%&RE(m>mIWYTEF7`-|MA5?Dw|O&zZFvrvUSi z$y4Yh1&Wh>pVyym`U*}TOr--=rKbK=I*~S|Z{&2cw+r1oT>B)`Lic&~lXm3$Bx@P2 z($!rOHg<9dd}F?g#w8xzDet2R$-m$}$&m16vYs6l{)+vuD8K1B>iFDs+19hdXNe!G zaW21k>#WwJ{2%YD%DCIUYH9nF;5l=jM8?(pWhMJ2O4sqeNr$#4;}_36eZmJW-EPd- zC%N$-LAS4ZkjNk??%2p-$ks0CYf_KdPu%+KoWn|*hrr)BhZjvw@%XGihZ5*n|6C4Y ze`Q&IT0`=Zh@7RZf~Ofr?lK>gr5@0I5BgzpLFXxxFQAL_zd`-k(Zl`dUc8UbvB&ux zeIFX4+aG)%y40%t^loVn^}UqqlkY?47mL5cF!&N@C~Z&kStq@LUUc=%iJU66Cg&1P zLc4cL{WF;C=|TRvFDCi1zd&7OeGDPsShP1DN)g*R!4d9#V)VelFH z3w$cS4{|h?qmVaUl;rlm6L?j9g7)ut99_KLN$nSRbTVEOJUpLTrg5*xxY_#Et+$== zDtw84T>J#lKkpe%`b%~&-FNNa`b$mY8gJM57{`YiM<0Tov#GJ|ArOq)4&UF}0cdD_ zPk3T|N%73`l~+1(L=cD%6eQI1C@Y)!7+QVnABWySzo0{m z_hUanbmgpnPJUl9?#Oqt<~za5m$e_UnDWJXySM(ac@XXXdn@q|p#^#y=opXPcMO9* z9v|C(1V0q;zKmRie;T9$UBpWGLFBp1597=a@?EIz#n0jX+WhX@ZQOcSP`z}niuudx zxBG^G`);mRzN?e)*)tign4e$IQC^?6(NDMjrGR^ryf^*Ah5J0NU%tPS)PIT8-zR); z;{`mp`ULDM1me8>jtgw&hZOz!YZ?cvkE;1y^|bi=JT|WdzXl+-uEKdp@H@&s)>-e_ zJtmyj%E* zU$FU9)Q0>kna+xpYgmqvKLw4S&HW66(=>jizCTstXXyJp$Bm!zxy1|z@DV>Gx9r~K zwU}J!ao?i?+i$uS%s|hJS4nu2(fx%I4};^i{gbu*kmIGTGSAt5do6w$rS(FoRpx=x z8li6&&*V~?{OpQfg&8nCJ>9vN=YUtY-WH0x^gKfK+Wb;lBl8*P>RPUEgx4QdUo!u# zV+^_Vv_W622wW)tBBIOWeAF9RLPYU7AK`=eeAFbMCAmQ26ZN=q=KTb)+YZa|b&?Pl$1eciYKBkF4U(SA^%i42 zxJTMi|NAaoQ4fb#p7Mo=K|-ef!Ag)UzXkL49XYJpG8IomnX6&Jwxzd_AbMd z$zvNgTW63Ri1A$OJUr+ba6R~Vkw@-#sgeFGN;iGW#?Qtz3~u3ZC{|vea#6mMW%uVZ z<)F@s*PbH%a_N=jpw5f296U$z-9%(kpr0;3&f&b$&GH`b{#g6*^(wv9=CMPH2b;&{ zG%o8i%wrJEfTt;A9>e{hta;4Vf3@bX?O!7}8C$j11I;{N#Onr~r_%G=V)3heiS*Zh zpU+Ln`;2yy`AIwhxp>Dy-Tc`b-e+|F$(nCXj@x;7@R24`dojrsJpMeE&pq*> zCQ3K`Dh$qJy*R5q%V+Ib`(dzJ%9Xj9#7_DyiGwcQO>|M5@XpD`>t>PD`P@l7k8aTU z_QjV;`DDHkdFFmMjOQ60uc#vR(Ed2n7218xxz+T_^N!Lt-uK;wdB>CM(=zWw`u(n| zae_QQ^~(&H%Lfa|^Y^?wEzj3)*K^`SBFEkOWS$#~`|(P`UosEBhugRFAo2X>;UE3` zI`yCVNl=Nu!&cAA{+WH=?lVOyf6PyK?<(z&uD7GJ2odx|CqZipg5FhfekoEv&vyPbda|tddM~`4 z^F`|CIeA~;^pzJH-lSoymobCJ=X5IljHl=U)7Rny~i;PEX)^t>){La6-m2da}grJ7T@7q#uamfgXzaZI`CcTq)`K#RZlu zSK&P+(!i54#JD93W{^W!AaekBc$oI9H`QF9(Kxch#bJo+;Ds3ah^Ev8oqIej*o%0tf z5{AK6iN|`L^s`vLm*rg;T*Upg^9HdVrRNJ`Jxb3L#Cp^~2bas!cXsh$z1TuwtWQmG zGW&gE`L;#kkneBv_W94ESLpwekJ0?$ly!uQ}dhnx;{-gDx9ngoX*Z-IR zhy4H~Zu186{gBeb;6D|ABKM7di@JXh24`}|Tsd)LlhvS$>_KV>>g>N&{q zki8Gk{8IMXiRGEh8zG-ktdTE<2dm`j`QktZJpV!ZA$?cIgXaLpql(DCEPr5|XuQEk zZoloG%sXMXQ9a-MCE2-ex_8a+8Gm3MO{fl{o3Uzu{OOYR)vpzu7t=Tm2EP~jHTiCS zLhZh3e7<0$!1-f;b}c7p9Ia7%dY&-t&raG)`?C|cRxZDq%g1!SlcP-k?mP}U&)P4a zCb~2_L%vy0&xhy%{q6AbWvv@N&K}eXpk>b@}i{iesLHoV4|UTh8d~GPVnfo|HwO6e`ofm|e#AU;rexD7F)JKyfV zjS$Z1p50&lfu`*K+X|ZhAj7?~Sr8i2?PtZl9 zmoLliAG&m_^`boHZIeHU|Lk0m7iUrZHlG^*hQWU@UAgk3h4!axeTDJ|sXXYkdYv!h zOZ%ZL50d?<7L5yiV1Ekw!vCiIsarv(@%|JsIX%C<{VBO1AJgeP^KKTM{?+d4dDpei zz^;LH0O;bAUcM|k-A(zj=1JoR)c1bSDX}l+wJ`WF(@~^!9j#NoUQZe6iLR4%QR#9G zpDyX8$4kDF?juJ#21PHrq*KbNy*paXQS!GT=_i6n=_%=V^@c)89|}7-eJB*YYbb2f zcngOv-wYGq06%!ppFHtru{^B&Ao@~bN0AMYG<^L6?;`-;pa)-$;Da1!B6v-YD3%8q z-hA#q*@Vbh6VDi@1 zYsh~wy$^#It3Dxg6yvAv_2kzWKM%)x@?!LV3s=YIF0%OjXN2CXY&Mgbt(2gl~7PdO=k=<7@KIE&TOl zt(9Qb{v>kp zrQCp9ZyWR*XW#N3g4@nz<#U&F{-`4R40e7gs>nG;+y6H@!uiROd+CopfbX&{s&9dH z{eaRn^iTR1Y?f(==u_o)Jl~9SzaEMCW-sB_oo}AUc>Rip*S#5dZRQ@Q;GNR>@@7GZ zeg8K#KQ0nJ8(P%C8HX0>{J5x1<09AGahnBQYrQVqZ4CF_9^A84aChe(#q$)ci#Xlv zCG*)=)|36qx37f3n`IrP@*)hrsQg`BFWvvrdCs#lDPLrbe;9mD>f1&{L{B~^2GV-w zv8;9P$Y0hskKN+s%UbWgiSotzSdqbGeFgIv<}HXqlQYp&7vnn&&h^&67jVJ2Upu89 z%tzo)cYU7KuU7+JwVPmm&YE{Ndik>YwchQQ)(d{-el^JYJPbmf7Y4RbgY52#{>51YRL?|*sr1mr_|F9p1c*ZK607kc@!`qk<7%NwsS_%e@+%V#1VMGgU; zlOP{szc-h1f0KPS8Q*yS#_PZJ1NFSZo2UG99jkbrlKHSZcM@R^a#`eGY`;`LP0=cm z7o|0#7e}kw7_N98KUd@j?Xxre#rDgSI2-!~ry&hWYh-?l&MEMV*p7LQ+}DY8f2H?a zI;cud6n~FnlM1 z^`jnyG5&P_U;`x89k@jrUgszb;;d z9}@lUEj(Uw4kUlvN43604zy890>AM|m$YO4AXI)EokCAL=;>*XeKGh>%4OQG^?s%4 z3ohJyX+1n2z21O+l=td7SMjiOAIIH#_OQJyq1T(a|FfJgs_aSSpQ8N0doSg4>k)dJ zWBMu$DPJr6S@#W+bK<)dPO(=;WDzke9* zS)&B63+HDU&N~#&(JDB*bCq8;)r7DA5rc2UgKsCp_jZME#Dni03||-==5xH}FS5A9 z_V=-?BzEpkc;^QmPw5yZ$m4|G?OdD4Lpu)``}eGI-w1LN^*l&=6y*PXUOPC~owSqC z{R5OA^8)Om=J(F`+d=0S{)=8`?u(N@P#%Yc_RS+tUWS4Cg)8r1e45@7r+fYo!{Gju zKDy9(sh|Hb!2%JZvl=EgRTfp zJT@QWyDY$veeW#fuSQ6J{?((`ODJF5AN6Bsdb;h);r$0|wL|De(`XN&+aJs~DEG?U z#BaL)Z2PMDC3%s96YWgTJ|86hYPQRIHNLMT^tGVAP|aIi6)t zu=O)yE<* zKRwZ8V96m#NmHYJl>p6*UlyasoZcqEaZ^3=4 zJGnTGTfdC6>T5ICNjm!TJkl2de-kCe@=g0yEVr;8kk9oW#{1&V^Eht#XrD{uM@8tw z^{d>%^{tS0n-PN@N#~WAF4{ER<`tv2c1_1B5&gIH4vy#9E5CC-aFUa2o-@eW_gdu9 zMb(e z`|dpb13wU3P=92j#riX_j2M`n?%e4dX7vZ%9hW5p-%QZ}lAWCCKe7MxXuc5%m&th2_gXpb&fg6*&&{{4eiPLnl^b+E)B1KU z<+xkVA>wm)zI-3bO$3~e=#lx=&3};c1O821zrb6+9Z2A?`PZ$t+72|Qa>C~2gBrJa z`H`{%{Rh;fpgZ_~tN}x=At8}hKjZgi$FcMB@jR&OS{tu??p)4q^4;`$zh0_`$9Hw^ zW28TivtIk$2U@-YSny}pso)OL5BUfGnR^!5L%G~a`yM^F7U$?l-tT0++}eS@HB8x_ zr24z7ufF!GL|)qc8I1Q$w0^Mrs(yd0yq!}-{_CioQlrp^y+`_oxqeB%N7osp#!;bf zwSR!Fu?|E}4j=ycWhi$Sl>?t6{d%@`5}Z4wT*zNn^YIfn{ilNTV7-t$3I2MQe^>Qb z83)5p$X_V}J|ukul}8nLj~_Aq%2F%R2iXoIa7AU|+w)JAdlylB&uxVDpguac1r)4n z?C1DU;|(0*ydh?AYnSMY;dA-rRn(6A{UxkVfPa+3Iu;@9d84!RM<3wvju+6l^v!ZR zZhZ|@-t=km*OF=vcJlc93Qm9V9dTP;JFRPKop2>4&8EZ2b@%{KyZT220c1^o+*k5|m@Gnd^kn}^1$3{0{ zAp3&0o;Nvkrmn9|ejA;g55qk@W{2#i??d7-ecaabrPeW~BRjW2_wG5~*Er5}mB_Qb zN_U@Ex|@B7NQLInv>dw|^gqGP@qS~L9Gmj!>(|eR922=|b^+rHcRa>ft}RW;3A97@ z@>Kd1!Bc8F$Z-FE_PzzquByCuPm&YDRGT4ik}w)`h5!je(E$PD2s%83fC2#>z(;IO zMhFBSnT&<(**+#gF~rs;AQ0n&IWtLSLPgUjX{&d}*EL#eV{0|GdYf7w@!9eEXhf0w z|9_9Y*V*TsnIwSq{_fqsWcFF_Z+)-zt#3VcSdY^6pu}f&o#V^#t{R_+KksIX;|Q!-uL*8}&osuGL=-_r$MNe;pL~ z!v2ZA8ZvsJb3!lZEB4dJ9Y6o(daDqXq~Gw13f%Z!yi`!GTx#KuTliE9k4f11bZWcl zU9eXNp8~sSK{T6gD29r`E8R<)3=kr)sd@jc@C}#%rirH2nXSzXP)pZ%awl* z;i()Jxp8|k9+{AE*x!RTf6dz+pJ}7raY*HE_@I_c*QpghYUw^~QyIcCCyPpdT%aY<&19ncrjot-*fVB>i>2k?+fezfA%B%zV}MfYn#H?x;CdbZ>bqKk5+Gv9)TSl z>JRms)ap&uvrk-a9^`sP9ld#>=*@%XUsV3>ZrV|!H-DS#>CCU}{4+_@G zFV!=(bWr*{_5P*t2K@9P;ivH`e(G+TSEGlNUmC$bH6NV{&V1tjrOya|mq)%S@cO;P z<&m#h*wa5{;ZIBcsqL?Ea90E>|4n3VUzV^K+C1`ewCAY^Zw4NabaK1 zj;*yzj@FJVH$VShPrB5xW54+)v`5w({@srKzh(YEUGQ5Td9%{r=8>G& zmB4Rz*gLbY{t&U%@70Mwh!|gAjP3i9v46+h?k)B4hx|O4J8yAt8NQ!re9!vuFTK~< z?VWn(EN(Hm3imlukDP$=g!=-)$1TPm*6)$EDrXhxhUnoNQBSxZq+9yCQt2{uV@>{L z$j|yakgp1FGXI+px@PArwB4!CSu8g=Rqim~v9QY9Q*qAXCD)Q)+<$Ro=Pa`MbM5}Q zF3Ran#cOunLis4((UtPkx4#3q9lBKdSFUs^eyMEnWc)t-6NdBtt#~7t1y6czV!noB z+h^3@RAO?}FJD>Z8-$WDM_Y#FRYkX@LVxuOkbn4)zN4dr^8$l&X%(E^O@I88R^-dp z#g2TRVMi67)(T$YI{OSezsvT|we~x5?Y~XhFGLeRBfP$^vOJ>aim~qhIOCBn_2=VL zd9`!>E?-^`zLP8E#uUBL*z;H$`uj3HZ?kjyH)X#C<{=9Ib+!D!d&+%%jB-DayT|M2 z(BI%E@!uDl?k-CGc5iv_Txl*kZDz5VJLI}??2`5h)_HlH0q22k(RN2h)&IYHP~P;r z(cfy%0M^kYK9p0!Mf$$~A)JGo`O%pGEh^5OH;p?gi!=XTzQezDoNJFRRkrt6(w@Sfwf94!CknrBv6A5mW7R*){y2Uq4}4f(^XCG(0mhJS z3r%a07s9%Tc^!s;yPK@ar&g8y7 zZ)YLdH}dZRh49n@hY( zISs#inzSmvFh2ZVC+`1}a*}`MDFW=dSN_8TSZ7P)!|#K-yfgoSfR4ToJnWb7S*w39 zX#ND@;&(3CNSJRw^>x6X!mm56-~G!3FD|E~FZB=c^mOn`@5lks+wt!G@+Mp%omZUv zEaa?ik9JMGTk-ARQ(}E%z!4sq{%+Y5m`+ zbWC1(P~p7thx+dPnZDZ}Gx!Sv|ElIg5?pcrTj($`W4%(0Tev*Fd z$G?4)e5`O`+*ba9{0Gm#g0tBg9#8H)o?Xi0quzMZ zNYB6Jf1*9d56E1_uN&@EeHZBajymln?W(^C|E2i;pVzlwgX6bf>j}oCm38WIx$^I1 zQodLN>s=MpOFV~gE=bq8UN7wsPr=jW`ePl&r*n|NacLVapv&Wpd`3=Zdz&E#z8~1{ zwPJj4DT;1@K4cT!GnLv4*CK#tOj?KBZeJ_*SXgdNDT+Mb!&@9LXV9!jzl+TJZ$iEh zuC=lbxhK_s^Sd*7OgVSTDUmrHxz zkED4}`iXt35>I{4R{EQ7ly~Tl61_Ua-eQ~t+C;C~JdpkV8NWAa>kT+3CHjEz=ze;? z3&WQ}?nvJZ+6W`lIm%xZs~_ov*Uxc>{KRs!Pq%$GtAX{t8}^~wr`=6&ox#+2RPlpz z@P=ozLw6}&^Z0T79m?~ED9=;sp_u}IvPR`79=7&64+(y8FS@qhc~HVh`vHBo?w5BB z92*r6li7E_{xth*^v~Im3(7zs9-P-wyxytx@%uy__}QqvP+osP`^oCh>eGX>WAC*3 zVCRgpzPl}q*0$hh?0PYv=MvNFUu&;!pY{;$R}+3AUlfD;bTAK>c+4y1jeU<6USeV8 zv)+p0xvw=cK0YktP=E7*UjoG6i2X7c*!zCZK_1W9_qkdo+K9IRKO#@VhDXpznu5!|Dda-}MhWiKgyn2HEC5p7{?KaH0a~w$|2p~ zKO)_hd*C_Fh5q7jT%mu5^d-H1Nj*Glc;4ao-(&q!xYtVk%0yr|gse0q+{XXh9?-K*zcnVRX@Z2py z@r$g)&-k4k5)tBo_gnh-L%#dc8CY*vvt0S9V&zdS=XLmwwD41{9ij37z4$0gxV?>g zoh#6p8sD5XBwckVaqvWshd#GMwe6`<0^%LVKg7LJT-B7K!S|&Kr z4e=v(!Z3RUyBvBU)LY5+YQIEiKl~f`rFYll{*KJAwNBVM-k=k}Dfwo|;31#cczXuu zmie#Fkoh#v(J?2_(dk?Ddw;WzpJ6}u=Jr*U9^$pyjvSQuxH4|^-fQ8# z7S?g3x1xO2XZowZd7qu*8-1Mo(6?q!4c{q!lz&2abpED%7sl@qIF=Xgl< zE7Koh`iRvBW+a{64)Jk`e9?g{%>U`Ds^w#x`3=4>-*_%x7y1+1y^B5%4)w+to&mb- z?h^V_&RP{D{vF8l#btHl#h3Nkyz8QZR;^SRL*IYX6aiwAjeyM=QD>?DN*JpK33=|GL)x z6h1P0Gq(G>{rlI%|1|6Gu;73H6!^((;|uLs=Og0(;3-Fj z|Ldl}|J6r{|6Bi?@ZWbt`2Xh`{pWg_crHX2OM314;)twohV)^%_$byF|Mru}?{*;c zPAH!%ZoMBdpjY6>?O-^NH{tt@O7F@1Pah82$=264YyBoKv@^$1)s*%^&_4MwT<0J> ziTS4|von`+KH_#}y59MG4%^4H-uH)Mx9a$v_3sVRznb;E0DkUI3BU9H)+K63R;|C; zyg9C{G(VQwm6(THSnbItefknwxoys;C`WS z+_L8%GQ06|iSHd5ly|z$mD-P&i-V!BU+u)qzjm_VIj(4V z+@~zz%#Jkv*nm#p;ka_a0@{(^csj!&oMK0!)0{vu-&I5Che$c{1?A60`FImc(_Ybe z|5-FR@D!p8<(+J{`H|TRsU68lI-b;??A3BL_N48Dn%bUJ`z0RM_6YYWrvTnjZHIms z8UGFbaD2TD{)Nyk5jiuvB(z^{X1@Q`wWBtdT?47rz3&L%wr5a34Yq-h=T$?8qD)h`0OOjtu{^>fqn`o%PIMdLUnd z{|!cWABRBq4n#5k!ruh`?=*f3#=kR;2>!;UqztxoMr}_~`Uw=ND_0vl~oz!(XC{QvIy>5D-B#_Om5 zA{NDOa{crG_C>k9l<~{21rE1sWWN;oW5+Fz;uS519-;nVeV^EA zN$0q}`)!@Ef3JqO@6osI=Sw#4moWE%LN$tClJ#)EO%vXEJ)ieWl0Tn@dA#@I|F5g6 zUHjX-uDYE1`L|$Qbs08ZyFZhB)XnkR#%qQ@v7_3~p#8x3<7E8%pjhmj|J7S}i-&B! zaXJd%!TmTg|0qO168Yjf=`=}^KLd%)i;Kstm57k<-R}7u;9bS zUMqcD}CjO37a}U*DGI zukv5mc>(61Y8{Pq3;h=-05u_9WL^;1r<{lT`53oL+>Q?CF}H(0y(6}svP#)C^ z*SP2Vy61pAGBfIu(27>sH}BN#Gh{F5Mp}_O{KN26ctt zryu$AtiG;8yd9(+l=^QzAb7rY#|NYzy~7X6`_{@m^1iLLOXR+{@*WBIwO(v`K=*lo zpCnwad`QxJT6I5;`%Sq1NBZ>c+$!le0O{l>(t%HRL4Wu;iq(Log!t8ADJmEO~CXw?4$`?Zi~KElTRTU5}J_*Ow?pdF& zzfb-s_C;-@+%()5wN3OxxG!oY;F(H4hj`47AEN&@vRBYMAVH&ZQEi-uj@Y=dS`kr* zej)I1eVP14I#&C;k8%72msO3Qf&ahdu1v4i+lQj#makv7Oprb`{ol#nV&1Xc<|FrL znCnOrpULXy_{pA&)&76AOC*1lJ)!cQ ztWmk|+g`ixF)wE!{Po6D-S_Bnll_uZ&03Zu0S>yQv_0rf>T)mCtnl>lGGu|NL?ZC;h4~-GA=;903%!k z_u+o}>$JTpctxMuIsoo)=R^3Oy%6y3)^N=}5Az=~-yQfKO<14mQ|(Xak6f3_H$lB= z`hoSlf$1aG9`Ggl!|bPe{`R}CsFuHR)aU-b(69XVTt3d5{CuF>0iiv65BA95dz?c5 z#&UQXG*fl^gqQue1bRKh2jz(I&4_nCiid5zC*W_DH^rO#G1w31qa~zAfFI)7`NHwT zc3zyrGw~AQ`68z8GCYHO1;<*q#PtqIj_x^)vVDYMPl=z72*fovj18*5a{)TqV zYspSWyx*JhbE()PHor*ikylAQ)PpPQz*{rFFul(DUe5V(I=?uL-HmP?w)w?Setx0j zaW=mg68`7>fB^VDY2Qake@ONWM7=v~USak{w|?#!cIAi|ADl;&P+&DG>%jY(bF_3i zpJ>yt&nJ8xBHl45c5`{B%_{~KuD)iQR}3oLw>9g0+2;#M=eNcFPp;H?M$apcasJ@@ z70U`=XgByg;$w?Ak9f26lY09}nMbVo@0&+_|IfhJc5Vgd355^HPf$-)^NmiCv!BYo zgK*pty<+yKk8>>F{FfO&rglQp0boq+>~P*ee;!SjLUgm>wRcqcE8k8%KS8vq+TJCr zvi;*IufFaCJ`C;L6>S45XJ~XB`Sb16$eFFHv)=E}j!xz5Q&LakdA#3KtNu%|ivs`U z3816f*WJ-V$wxfR|NBhN>&*+*uGR5_`K$e`=C5gglJ)F}fG6kc>iTPfe!XxqJsafv zqYCDACik4*kzewBg7a;RuF+d=pND$*ls~84V)Ij9-ym~k&%lDY&z6`_E)LS}59l-q zdx`Uer6@;v`S#_o6Z*}6y++4l+6kdv@1FI>CeACudd2QKihZ_M^ZaPTeYU@^a394! z+naLd?1*ai=c1sUY#-{&w0@h1(hpZc%oFuj9mzi1zvK8-v(I*h_+@2C;F=@~2(R5$$bEW_8@2MU|5mSasUIk= z9DJ1N*?lbsEUfpn^j2D=d|&G|^6qc$`V|4L1Dn{s}*QIj%u_lt0;^Bv9cVEg3~NWH)=V`?bDbq7{`RqZ9MYvg!t$% zd@P3E$NiH+7tqb@9{oNN=qBN?UBa2I2iKm*p`Xmxe^Wm}u#eU0a5iqji+8KNNxag| zvnMzY_3eg!f-k}062e8iv;R8~e>D1>=O06Q5nu5x^J}hBh*?7_6fc+IaE6^ z>>u&O@)sqU{Y5y=M1_?9u1{w1-0yfeSXU#Q-#!oPkaqsu*NOY)&?->7LY&t$#d#Xc6lf1&2QdfQb}z7V}!D)fDkA-<{CSkFP$vs=fbJYV^|b-~G( zT76$`SRd)f`o1i1MS|a2xL#oO+zpAU9xq2}Z<(HFJ%2B7jf!5(!?ob#v#p-X6rS|_ z>0uj3d|a8Zu*KUteKH3P;K4p(T;O&6@APmxD1TqU4H(?1NLEA7v4uwW5~TDwqebdZ=6b(W&lRF! z=~qbi7U&z|w?h2deF25&tcLmCUzP8C$rszYIPL|>;psuelb!c1M5k!KhYXMH>R-wF zZ~D{xE`F~A31b!aPI6}P|>RHj>tF*q!*0Gmyo-*b7 z?YUCXvG|eSh59r9mJS@a&s5a(trhhr(_LLc3%%x7PW`;5zcW9`9`%KQz{yUz_rq>G5E&s(7*B^eLqmNsKs7(sSl`BN=W^%dQ!Y-F;?-!zv2%q6T zW=(Hzk#{DSvm{)Iz9jv|y+2lu@mTg~GA-c@);c)4E$@hKX+?U|j^;=xg^h`f$dNSAait%wFy4T=xJo-4`?f5w0 zczmJCdx{?)e?0v;l794jGidrm?Y)d|Y`;+JdP%S08?!UYc5bc^U1I%l_>~Wweue1u zl76J{<=gZ5UB*W`?l}MAew$&+Bl z=oO43h8L|Ty_crHMdHJKMt_d^c`@Qn>S}(Zz3ubXq+R_Kg!7Zz0Y9C1%x`*$@egsH z?|zL|omXf3lsYxP`6tqSO5jG~^Q;Evhy8wysm~903H|;2aJ(af_r0xvbGI}v_h`v{ z)Zlb^BK+SVU3OVMFptP%S;OHzrLX7cHv#&E`#`?R^rP_0{PfalypN+khb#2o{AVs- z7w8jDau3a8u<2lL3cV>uK!ZO6*?z&3YUu9#_~8!%j*1pJ4&^B~#M2)j-uW)Xm*}e$ zUrK+%&xhsSLplU_5&RlIxW9_|{xpYQ;v>ZG!?|?A>wMzlMu@k4z}r)OZrJZZ3ia|o z3jX&`f&Xa@@lQP0!~csJAMmN*U8l=(zu8*wMYcal=|H^BK0^F&$l*7S|Fj z0)BIU?FNRF|7Su!`aNF7<0nKiT(3F3C}%5?-}$-E^>u}{V7&tAr1#N`U)1A%zgakb z5rBI8ZmCx$^Q*t%Pa%)1Is~3Pe`5XPQ6{AO7vCepD_^y6 zoA6)X8uh0XqAv=Ze(r8+eqXKm)BAe9WBbG0-qw9rh3M*>9JN?GYR@O>xbYV0aOSUa zzp&=Ry^d1O{g#VipK`wjch9~SZy$dbmKATb+d=x8dmepXXw7|(74?4*-)EnM`dApx z>|A{hH)(>;3vRG>yuL#81t~|q3!Z^h%?BRm`gS2Y+4{d+-Wi^~pJ!=$N;maeIo%4; z73vqN(Mw+bxmw=$sRa8=#?gLyFWEYUF4T+j!H4Ys44v@oz@9uCDhN zm|Y9{SIsL@Kf}|I0zR_wmU#U(=C|p*af7zU`2S!${9Sw~zxWrq9Xb0RiH;uT2i@?v ze0Mj!Q%7Q*@}NHDSx~C9{8jAKFYVZK`%kR__+PS`u`sAQjW-o7q0xJ z09J?wbv(20dL*e|+VoBP@xqsVYi22b+B!=-r1~I9&)sW!a=MtMXye0z$G8%U-pBp_ z!f$b9z{0-1p?;P;{R!{S-rr#S&&T`t54#E9#V|N;QG2f3A$UmbyVVk`vNx#rsTT-2 z+x;KJUq$oLZXJ|yLGR7$Z;mFIFHBdv*3P{+|CyZnynYOP$cOb`I3MK$`%d`S?YmW3 zzVGY-9Kn1koY#l*&TlYZ0Ph6k$N8V_{V%2mc4;_HIlqQ>;x8_)?w{C`23MHxr^pvS ziRWk50?)oL!{^Q6`3(+8?9Z?9f9i8gw@o7^L%guxEdNlRe=NQi@xFc$mTNKo`ZeYc zh3HzT7kb_JSjS6@*A~|Cw0HLb35WG~`&-dYA^LrVZ?4iipD(ui>?FR>1VvA5*`smVPa?b%L~CCO?h(h3~S7K481Q$9|c9jLm+S zZFF!w{xH55$;b8f4Th)greBJ^l<%+aA7=g69aF!aEB#9QQ&v1R>Q5nhTmVegsNV7Z z`90XQ7sgRVJb#N+6vDfS{_21Z-&!!4-LOUQmVHNXlZBrmy8(2mTBiukF<09SQ{Q7s zyCLki=+6fBg3C#&4+Fd5I_!&rJnQ&1V(S#ZewEzK6LLUCG~Y~ z9mVN|$TCsGX*Y)Suk(RCZ>%1kKf2%$1>yr6(hwi3-;V=^Q zwEOp+ectl}k!xS??rHt0gcG~>rk-DH7=Ddn^g2kMFGKb4(BHAsHvE->#=ZyW?9IRm*iF`{ZCQ zAIEXGoBX^2{oZa@{0JBN#v?5v7aZ^E%eP*p5YpTE^1=6^{)*zs{hjRJ&5RH5BzP|y z-tBv??4R48cM<;qKEm~e5U;~Iyb=!~ULRz7Ku5vr2BV|dry*Yd<|4|K?b}HAN87#) z`(9hvzp4C#!Z&UYJOACO?T70PpAx*=ybSuk3h%3%q(C9Msz%Nn@2eZ&{dtTJ{QZLW zVQruD#kJ%I=l|flx=lxj|Gp{k|Hh-l|K_I>|MwW(>)`)A0sa@H_+Ho$-_HkL3(*OZ zo~_&3{4l+DB9if;5H$nSnRKj2>ZUb@)>lY9^J8(44Vc?ap3RyP3u zw2Z&;(APxIB<*YET^{3C*eJ2-N7-K3Q?nh_Iq)mco zFSGwYg!aeE8t?d+%KqoRQK$uf29kEQf3kVOYXmR(ezU*hb?_0+7d{{2Bi-L>^R_AR za&-D!L z8a}i$_%Qz;BY)~QL48$xlKOwO0QGkE42T~<EHh6~XG`H}f`-TyV9^|iYHOWV!Uhji%7=|hg^jBg^J)Y->R zyPfIphCP+>({$+k&cOiQBj}?AjXY_s4zRvh#vCI1UC(J&3hxOO>*S4G;x5e@`ivT5SRNuLt zOWIYx6{7b@dbSR*SNahfpW-`@60XNL-xIvZwL0m%*2i(`sR?ul`dai%7(XuYOKak{ zNPLIHyIx53efnK*)9>lHto;w+<2gC*FK!9!R`TmVKBHPcIiEj>emnwre}wjZ9?$%n z`JMAJBJucqJU$1D1$dJ7Q5`SNK}HGN_;-%+bG!M4&yi&0*YU{5|8(5Tf1kL;>hH38 zJFLEv*0UxmMI6#n{Ir}R3F-LQ(r#geCuvat(($pSQ_}mROXa;Lx>)M#kML0jJpFcF zu0MLUrN36*C@=h!w7k{Ax=xj}+-_mzzog|27FPaCT5gu`n&>VWxUkRK>e*!Z_F8z0 zg~u(d<0-xyYT-evXVmJMFZfSdK4ImIzgzys!aANOEq`WV<@coJA*<(eQqP*`2NLd& zzG?5T+51cO{=B?H{?hr5?oS$neDmS>Mwb%#W(5pW>cuL*Y3o{nm+`rM&1rn~{_%k{ zzIy$4lf+|vL-Epji-iwZc%_B+TUghZ!}*kauc%kRhMl4QYQp`lhpXr3;-A^7`NI8D zcQIc@<0hnLVwNMbNMF3|D$*b z^Sv#XuLSs<4q?9jT)yR!Pw^7w`-5D*0rq#5_Aku07Wr^K)A&NiP3V0KtG_3tEAgAH z``51b)4!ap51KsOY3)M)x;*q_!$!ROkhD`{FQj(VIU-46`#yht4)k*v?|S=(xpiTl z<0pL+?DHwe7p&2)+vlrS3SjZA3SU?s`J8&656e%yr@B4m+ibm=`NHz550(jEJ3gF0 z+^-p~H@^`kU+4!DKCUBYCzDSb_#H!jJ}JlV%6FMuw=g}B8{zjddjUA^(RauvXXf}x z_9*ozYK!W2onE_gba8sU9`RWJSNvD@NWIy)Q1yHGImi${Uhn%F)VoUR{pw-D zlj@K176xI@s-BBiOR!20xE{ffB7C}f3O&MnA${2|=YOZO&rjX{4E2cYgKES_rvHWC zNdG|otM;vI)P6AEyXx|h`mvb)&ZFd`p&Wk*9~oSszWD(1J(=e!LOtU8tsXy)2tQ7x zM>+&S_4wyy4fv-u7f(G>h*qfGlkQ7V`_%7U#5gNB- ze(Hw~^nvsHxl+%wte)j2FAj(AJ8ulfdAWYM9R3RHsje48_+5YAjq#^ePj^fE@Ow$W zGr86FU2bviTjj8#_h#e#nf2S@_kJt;%_eji3$ zQF#2m4EP!UiwI8aJG$BWwd1+V`m6mcM2|Kxzw4PX8}GOtRzgbBX?9f*Kf(GtZC)M3 zk4wDT%dyXwTL+b|+K`B6_SyRObE`ftO>Djz;)CZE^ZTjk$6S`1SHA#yuHO84XcT-= z*7jmvrj93R-=uWksQjF?4_KJmkm=?hGri>NG4ZN#NskvseGkNE>qc%E#3 zz*>PTN&Nwe$0YR!D4sKafYKo`e*opPYQEZXDZ8ipX2SE!Eicu0pr>lSI`DFhhdZ`v zzPjbr67PP7HL}Z`dQ9n;`4g0WnLk14m-!QvezpDtrAN}TN!m&EY0DN1D?O8zZ5CE~ zCoO{#UK5R)KSAl2`4g0WN$O8f`eptErQeh1Ptf^rJ%7T>ibwBHNH!0sp4q-h`LeQ7 z^d|11v+#`;UTNXw7FK^jU%&bfLVdt_im&sA@!U65Z(W#vIKK}pJTEp4nD56vehN@n z&z3s+hIRt;)BYHRKQ6SJsjuB`_W3jOt;2e7XjjoLOYNyuLUyU|^~_h%@MM0BTXOl< z3Le~#k@+Wja`~$L7^<%c-)opJw8scvS>f<=Tg>;0Tz&Lo#KAt)Zl;5M`5cKKW9^02 z_!fJtj$MCSF5g50KgP|ud?kTT@e?8fDC6eqc(?j5Ywa0wGuLkud57)0 z9Wpm(Z;;QSlh3J8wv*GOA&k{+`_Jfox z-1QjqrFN9@9r+(@7_4tTO*({iLc^=C3rtwJ@w&h-a&UWp9?8YKzvjj0e<6BE;dg&c zd4ga9PW7uyHs4}C;^nXJsm7Pe=~R9jv#*T)*?i0VIiSDSzjO}d=LqIo-=Ln#(arne z^AW=P^;|xcGnF5vf0gNho**B&o^Uurx%lY?weszLlrZ0aBHvRr-*Wxsc5Jwx?-w{| z7EgJPfLt$MJuaZ%#K+DY|2SX0E*I~1{G-s1zF(mb?GZXcKGaTXReb^Zu<#b)>yU0P zxA&v|Li7PEKW_Z5asfNW!YUW_%0G~U&*lExIsNYaxh|LA<^B%D*Xo@PX}=In7y02n z67GvBMDt7^nEjLXSM?>v>xTV(W3GLN>qUq!L<5S4R8GewJegmF^q_wgCZovdrBlc$ z^M&I#+jsq(j^pN!tmhZ`GI z#SU^kXXAc7zsTD~PFqASYWQuQ3=8Bhp?f`k?`Xh3|8*bm6zE0Tjg;$mKn{HWQ+}UE zA^MXavLURuo18{6ew8b>KhO5u6OV{zW zUVSGv=;yyQ=qK&ST70T}mdy|1`v>BR_S5B*`)xQt3(^H23fJ$qX-w^Yf;$awM=$^X znSFe&$0etGsOUQS5zXtiR=|So@9e=Q%F7V+#ORc}6`ZC== z(XaF=M6Z)}Qh4Vmydi#^&)@z*+V9$b@3?k_=6|xhwG=i8_3=ATs-rq=U)uocv$V#aDUw}==dpx8eS*uL~XgylHkG-272? z?}M)&#ASo0N%d;B|L{vv5B;=!e7&3g+-?6%4Wke7_n&8gKNo9wOx1A}za9erGvCec z=RL9NPwQ^NqAZ@?(eFw-A>NqZ<&Wh)0XfC|!}_J=2}ke@EJ*hW8(q%V)Iy{aGA}RV zVpeb{x{5bm*z|R5$MZ29g-^gDPyGgGWs;a zFYW`De)d+B-ndUd`Y{>Z?>s8HD?=nkcc)V!QoAoUdd54n-M-6~2t3LCC4Emp=R&0C zIVPj?L8J3?gwD#RzTVc|q;_Q3U;3FsK3^hqcK?*pyVx|-;FK4}cEx*gmxd{y80w=w zyT`m99Vc?_Tr6}{dCK;?EB@fW5xO`Z6{4R=xVQ3SjW@pX_6w2LGiGw+=aG<5+`%Hvjmm0kY z{}11m>B+F2?SSVI$<6XA|IGhi!S@ov{O>`2o(ErmGH#cJ=>@<&hVp#8-lCmj7*n)G zDPK&Yr^%1R!>4dQtXxt4b3I)i)$w35{(T5=xL%8gwEWTQY32V$dc@`0`x6hVK217r zQT}XQsqgk1l|L$q7uuV7d3z7~*_-zBxstJW_ZOvH-}VRPT|6F}fbkTMZxYEX$X89O z^>x19e;EnuRXuZS<)5X#+gjf*?{Y=k!Te3ay_K)XyRUVVyj^c3t%DNw@BYO$eque= z;@8W&*Ys~+>mCXBwGPPJ>5;VFE#W(Who$IGJY?+*8{TYui-!$==c}CIK0PVtdbRI< z!3bp2^WnwR^W_9B0%e}oTuHJx&F*A89hrk)7({GY?0MRP$ZF2obh-+F#^I@|H`?7!zbhaBuR={sGyi+TEn~WwLp#gp)Pv{ zQ_F4NruEHK`p|#Q=MhXVfX4K@!G-8HiTCqdHFnryNsf|vXb_L%Gv1|oDzEqAA?-(E zev@RCmMa*Y^7;KdveS7d?r|DGJM=&B9rkaW>qH=~zz-oTA)Vh7+Z5OZq{rnLhcV75 z9?U+BE8`ZvQSj*a=xvq%SzT3#F(N zpv>`v@aOsFBfCO=TO#@6A*ElrO}V(Ib&=FtZj&I^8^Fs6) z#f$M}h9SKRqAi3Xy(izFzuytk;!}KpPD#c)r@j zN&kGQ7ydhaZ=Y4u4*4S9rTuU@V7n&-`XRHUoFA2*wf$)%f3ZMT-mQA1`*;Wt9_j;f zj?2R%%0{5=?@M~V{#0H~|Lw#)>1LJ(zwjO6hx?HzuTnpnTY~g@^7=*a71qgf^15eo zdEF}D$#-i?_}NfiN0ra3*A1hAR9?4UBo!5+3*{ZcFY>xdqQ%bm6EI${-HTnEd8Ujw z$@WbGXRX}6K}jfKKYHdUza(}Z8~RlGsDM>x?Zp9PrjJk4c{9lMZrFfb|j<>>Y z$n#|;#~+aLAst!h2)C);rz z&BygjZq;sfde*|9lUu`c*pHIwqh7!n#?P|&9k4U8J}Gdzz0f_=GkCN!IXNG!mUDwItbYLgbGzn<$LrlI z1rPBqlYdp4(pUV+!7i^+Pz{ zxfmuh&W$OYJ{}Wsc*63H#^afk>y45Y!}*AY=^sG)g4?$lzUIq2 zX+5O+*S;4C|Br=roW*w&EUfaIv`$#qG3-wz-&o@6ykQ@{SB+h}hq|8+MhzH!f%(7Sh6Md@DA zdWc_^3-=fN8_MH*lajBy$>_R9^^5CMw|B~;J0zdmRmE8=rQ*C?_&D!!yc7Fe9zss) zS-wL(upaPm{hs)$r(Z{hXh#i5yWn$q`@9ZvqVd~RZzXFEOW6GttI^*Q>aDS(hOM3v zEzf&1f(LqZztpqfBKO~_UpIt1kH?>*f_QjT;TutW5-<4Y5561qEcuQ7)S7RX!t4I< z6?0XghwYI6^79s7C!m~MK>V2h+vj_W(J1j54{1Mr9+TXI0(cU?ufxUx@;91!ocfXQ z`uD~Qk^1{_4~D>7Gmk!9s!P|C(|dUg55BKy?0n6a?-$`e40+7+kFUEdu=!S4Za?5; zxgVq4SdZ3=`)=h&KHu0!;(*( M4InwtBfBg94-Ln)9 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 ZZT}^s)?>Gp_Or2Sk2oq>(), &committees.iter().map(|(_, pda)| *pda).collect::>(), + program_schedulecommit::ScheduleCommitType::Commit, ); let ephem_blockhash = ephem_client.get_latest_blockhash().unwrap(); @@ -125,6 +126,7 @@ fn test_committing_two_accounts() { .map(|(player, _)| player.pubkey()) .collect::>(), &committees.iter().map(|(_, pda)| *pda).collect::>(), + program_schedulecommit::ScheduleCommitType::Commit, ); let ephem_blockhash = ephem_client.get_latest_blockhash().unwrap(); @@ -321,10 +323,16 @@ fn schedule_commit_cpi_illegal_owner( let cpi_args = ScheduleCommitCpiArgs { players: players.to_vec(), modify_accounts: false, - undelegate: is_undelegate, commit_payer: true, has_magic_vault: false, }; - let ix = ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args); + let ix = ScheduleCommitInstruction::ScheduleCommitCpi( + cpi_args, + if is_undelegate { + ScheduleCommitType::CommitAndUndelegate + } else { + ScheduleCommitType::Commit + }, + ); Instruction::new_with_borsh(program_id, &ix, account_metas) } diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index aec3bdbfb..b8431ef5d 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -9,10 +9,10 @@ use program_schedulecommit::{ schedule_commit_and_undelegate_cpi_instruction, schedule_commit_and_undelegate_cpi_twice, schedule_commit_and_undelegate_cpi_with_mod_after_instruction, - schedule_commit_diff_instruction_for_order_book, set_count_instruction, + schedule_commit_instruction_for_order_book, set_count_instruction, update_order_book_instruction, UserSeeds, }, - BookUpdate, OrderLevel, FAIL_UNDELEGATION_COUNT, + BookUpdate, OrderLevel, ScheduleCommitType, FAIL_UNDELEGATION_COUNT, }; use rand::{RngCore, SeedableRng}; use schedulecommit_client::{ @@ -42,7 +42,10 @@ use utils::{ get_context_with_delegated_committees, }; -use crate::utils::assert_is_one_of_instruction_errors; +use crate::utils::{ + assert_is_one_of_instruction_errors, + assert_one_committee_account_was_not_undelegated_on_chain, +}; mod utils; @@ -111,8 +114,9 @@ fn commit_and_undelegate_one_account( (ctx, *sig, tx_res) } -fn commit_and_undelegate_order_book_account( +fn commit_order_book_account( update: BookUpdate, + commit_type: ScheduleCommitType, ) -> ( ScheduleCommitTestContext, Signature, @@ -131,11 +135,12 @@ fn commit_and_undelegate_order_book_account( let ixs = [ update_order_book_instruction(payer.pubkey(), committees[0].1, update), - schedule_commit_diff_instruction_for_order_book( + schedule_commit_instruction_for_order_book( payer.pubkey(), committees[0].1, magicblock_magic_program_api::id(), magicblock_magic_program_api::MAGIC_CONTEXT_PUBKEY, + commit_type, ), ]; @@ -296,7 +301,34 @@ fn test_committing_and_undelegating_one_account() { } #[test] -fn test_committing_and_undelegating_huge_order_book_account() { +fn test_commit_huge_order_book_account() { + run_test_for_commit_huge_order_book_account(ScheduleCommitType::Commit); +} + +#[test] +fn test_commit_and_undelegate_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitAndUndelegate, + ); +} + +#[test] +fn test_commit_finalize_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitFinalize, + ); +} + +#[test] +fn test_commit_finalize_and_undelegate_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitFinalizeAndUndelegate, + ); +} + +fn run_test_for_commit_huge_order_book_account( + commit_type: ScheduleCommitType, +) { run_test!({ let (rng_seed, update) = { use rand::{ @@ -322,8 +354,11 @@ fn test_committing_and_undelegating_huge_order_book_account() { (rng_seed, update) }; let (ctx, sig, tx_res) = - commit_and_undelegate_order_book_account(update.clone()); - info!("'{}' {:?}", sig, tx_res); + commit_order_book_account(update.clone(), commit_type); + println!( + "run_test_for_commit_huge_order_book_account: '{}' {:?}", + sig, tx_res + ); let res = verify::fetch_and_verify_order_book_commit_result_from_logs( &ctx, sig, @@ -355,7 +390,15 @@ fn test_committing_and_undelegating_huge_order_book_account() { ); assert_one_committee_was_committed(&ctx, &res, true); - assert_one_committee_account_was_undelegated_on_chain(&ctx); + match commit_type { + ScheduleCommitType::Commit | ScheduleCommitType::CommitFinalize => { + assert_one_committee_account_was_not_undelegated_on_chain(&ctx); + } + ScheduleCommitType::CommitAndUndelegate + | ScheduleCommitType::CommitFinalizeAndUndelegate => { + assert_one_committee_account_was_undelegated_on_chain(&ctx); + } + } }); } diff --git a/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs b/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs index ca63ce2b3..28e688ade 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs @@ -28,9 +28,13 @@ pub fn get_context_with_delegated_committees( let txhash = ctx.init_committees().unwrap(); println!("txhash (init_committees): {}", txhash); + ctx.dump_chain_logs(txhash); + let txhash = ctx.delegate_committees().unwrap(); println!("txhash (delegate_committees): {}", txhash); + ctx.dump_chain_logs(txhash); + ctx } @@ -51,6 +55,13 @@ pub fn assert_committee_was_committed( let commit = res.included.get(&pda); assert!(commit.is_some(), "should have committed pda"); + println!( + "PDA:{}, included: {:#?}, sigs: {:#?}", + pda, + res.included.keys(), + res.sigs + ); + // SingleStage Commit & Finalize result in 1 tx // TwoStage results in 2 signatures on base layer let sig_len = if is_single_stage { 1 } else { 2 }; @@ -204,6 +215,15 @@ pub fn assert_one_committee_account_was_undelegated_on_chain( assert_account_was_undelegated_on_chain(ctx, pda, id); } +#[allow(dead_code)] // used in 02_commit_and_undelegate.rs +pub fn assert_one_committee_account_was_not_undelegated_on_chain( + ctx: &ScheduleCommitTestContext, +) { + let pda = ctx.committees[0].1; + let id = program_schedulecommit::id(); + assert_account_was_not_undelegated_on_chain(ctx, pda, id); +} + #[allow(dead_code)] // used in 02_commit_and_undelegate.rs pub fn assert_two_committee_accounts_were_undelegated_on_chain( ctx: &ScheduleCommitTestContext, @@ -230,6 +250,25 @@ pub fn assert_account_was_undelegated_on_chain( assert_eq!(owner, new_owner, "{} has new owner", pda); } +#[allow(dead_code)] // used in 02_commit_and_undelegate.rs +pub fn assert_account_was_not_undelegated_on_chain( + ctx: &ScheduleCommitTestContext, + pda: Pubkey, + program_id: Pubkey, +) { + let owner = ctx.fetch_chain_account_owner(pda).unwrap(); + assert_ne!( + owner, program_id, + "{} should not be owned by {} as it is delegated", + pda, program_id + ); + assert_eq!( + owner, DELEGATION_PROGRAM_ID, + "{} should be owned by delegation program", + pda + ); +} + #[allow(dead_code)] // used in tests pub fn assert_is_instruction_error( tx_err: TransactionError, diff --git a/test-integration/schedulecommit/test-security/tests/01_invocations.rs b/test-integration/schedulecommit/test-security/tests/01_invocations.rs index a66f571a3..1f19d91a0 100644 --- a/test-integration/schedulecommit/test-security/tests/01_invocations.rs +++ b/test-integration/schedulecommit/test-security/tests/01_invocations.rs @@ -1,5 +1,8 @@ use dlp_api::dlp; -use program_schedulecommit::api::{schedule_commit_cpi_instruction, UserSeeds}; +use program_schedulecommit::{ + api::{schedule_commit_cpi_instruction, UserSeeds}, + ScheduleCommitType, +}; use schedulecommit_client::{ ScheduleCommitTestContext, ScheduleCommitTestContextFields, }; @@ -313,6 +316,7 @@ fn test_schedule_commit_via_direct_and_from_other_program_indirect_cpi_including None, players, pdas, + ScheduleCommitType::Commit, ); let nested_cpi_ix = diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 332022dfb..474bf0aab 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -19,6 +19,7 @@ use magicblock_program::magic_scheduled_base_intent::{ }; use magicblock_rpc_client::MagicblockRpcClient; use program_flexi_counter::state::FlexiCounter; +use program_schedulecommit::ScheduleCommitType; use solana_account::{Account, ReadableAccount}; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; @@ -67,62 +68,122 @@ fn expect_strategies( #[tokio::test] async fn test_ix_commit_single_account_100_bytes() { - commit_single_account(100, CommitStrategy::StateArgs, false).await; + commit_single_account( + 100, + CommitStrategy::StateArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_100_bytes_and_undelegate() { - commit_single_account(100, CommitStrategy::StateArgs, true).await; + commit_single_account( + 100, + CommitStrategy::StateArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_256_bytes() { - commit_single_account(256, CommitStrategy::StateArgs, false).await; + commit_single_account( + 256, + CommitStrategy::StateArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_257_bytes() { - commit_single_account(257, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 257, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_256_bytes_and_undelegate() { - commit_single_account(256, CommitStrategy::StateArgs, true).await; + commit_single_account( + 256, + CommitStrategy::StateArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_257_bytes_and_undelegate() { - commit_single_account(257, CommitStrategy::DiffArgs, true).await; + commit_single_account( + 257, + CommitStrategy::DiffArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_800_bytes() { - commit_single_account(800, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 800, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_800_bytes_and_undelegate() { - commit_single_account(800, CommitStrategy::DiffArgs, true).await; + commit_single_account( + 800, + CommitStrategy::DiffArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_one_kb() { - commit_single_account(1024, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 1024, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_ten_kb() { - commit_single_account(10 * 1024, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 10 * 1024, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_100_bytes() { - commit_book_order_account(100, CommitStrategy::DiffArgs, false).await; + commit_book_order_account( + 100, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_671_bytes() { - commit_book_order_account(671, CommitStrategy::DiffArgs, false).await; + commit_book_order_account( + 671, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] @@ -131,19 +192,38 @@ async fn test_ix_commit_order_book_change_681_bytes() { // of size 1644 (which is the max limit), but while the size of raw bytes for 680 is within // 1232 limit, the size for 681 exceeds by 1 (1233). That is why we used // 681 as changed_len where CommitStrategy goes from Args to FromBuffer. - commit_book_order_account(681, CommitStrategy::DiffBuffer, false).await; + commit_book_order_account( + 681, + CommitStrategy::DiffBuffer, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_10k_bytes() { - commit_book_order_account(10 * 1024, CommitStrategy::DiffBuffer, false) - .await; + commit_book_order_account( + 10 * 1024, + CommitStrategy::DiffBuffer, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_finalize_order_book_change_10k_bytes() { + commit_book_order_account( + 10 * 1024, + CommitStrategy::DiffBuffer, + ScheduleCommitType::CommitFinalize, + ) + .await; } async fn commit_single_account( bytes: usize, expected_strategy: CommitStrategy, - undelegate: bool, + commit_type: ScheduleCommitType, ) { init_logger!(); @@ -179,13 +259,27 @@ async fn commit_single_account( account, remote_slot: Default::default(), }; - let base_intent = if undelegate { - MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { - commit_action: CommitType::Standalone(vec![account]), - undelegate_action: UndelegateType::Standalone, - }) - } else { - MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + let base_intent = match commit_type { + ScheduleCommitType::Commit => { + MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + } + ScheduleCommitType::CommitAndUndelegate => { + MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } + ScheduleCommitType::CommitFinalize => { + MagicBaseIntent::CommitFinalize(CommitType::Standalone(vec![ + account, + ])) + } + ScheduleCommitType::CommitFinalizeAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } }; let intent = ScheduledIntentBundle { @@ -202,6 +296,7 @@ async fn commit_single_account( service, vec![intent], expect_strategies(&[(expected_strategy, 1)]), + program_flexi_counter::ID, ) .await; } @@ -209,7 +304,7 @@ async fn commit_single_account( async fn commit_book_order_account( changed_len: usize, expected_strategy: CommitStrategy, - undelegate: bool, + commit_type: ScheduleCommitType, ) { init_logger!(); @@ -243,13 +338,27 @@ async fn commit_book_order_account( account: order_book_ac, remote_slot: Default::default(), }; - let base_intent = if undelegate { - MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { - commit_action: CommitType::Standalone(vec![account]), - undelegate_action: UndelegateType::Standalone, - }) - } else { - MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + let base_intent = match commit_type { + ScheduleCommitType::Commit => { + MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + } + ScheduleCommitType::CommitAndUndelegate => { + MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } + ScheduleCommitType::CommitFinalize => { + MagicBaseIntent::CommitFinalize(CommitType::Standalone(vec![ + account, + ])) + } + ScheduleCommitType::CommitFinalizeAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } }; let intent = ScheduledIntentBundle { @@ -265,6 +374,7 @@ async fn commit_book_order_account( service, vec![intent], expect_strategies(&[(expected_strategy, 1)]), + program_schedulecommit::ID, ) .await; } @@ -622,7 +732,13 @@ async fn commit_multiple_accounts( }) .collect::>(); - ix_commit_local(service, intents, expected_strategies).await; + ix_commit_local( + service, + intents, + expected_strategies, + program_flexi_counter::ID, + ) + .await; } async fn execute_intent_bundle( @@ -668,7 +784,13 @@ async fn execute_intent_bundle( payer: Pubkey::new_unique(), intent_bundle, }; - ix_commit_local(service, vec![intent_bundle], expected_strategies).await; + ix_commit_local( + service, + vec![intent_bundle], + expected_strategies, + program_flexi_counter::id(), + ) + .await; } // TODO(thlorenz/snawaz): once delegation program supports larger commits add the following @@ -702,6 +824,7 @@ async fn ix_commit_local( service: CommittorServiceExt, intent_bundles: Vec, expected_strategies: ExpectedStrategies, + program_id: Pubkey, ) { let execution_outputs = service .schedule_intent_bundles_waiting(intent_bundles.clone()) @@ -752,16 +875,28 @@ async fn ix_commit_local( } let committed_accounts = base_intent.get_commit_intent_accounts(); + + let committed_finalize_accounts = + base_intent.get_commit_finalize_intent_accounts(); + let undelegated_accounts = base_intent.get_undelegate_intent_accounts(); - let mut committed_accounts: HashMap = - [(false, committed_accounts), (true, undelegated_accounts)] - .into_iter() - .flat_map(|(allow_undelegation, accounts)| { - accounts.into_iter().flatten().map(move |account| { - (account.pubkey, (allow_undelegation, account)) - }) - }) - .collect(); + + let commit_finalized_and_undelegated_accounts = + base_intent.get_commit_finalize_and_undelegate_intent_accounts(); + + let mut committed_accounts: HashMap = [ + (false, committed_accounts), + (true, undelegated_accounts), + (false, committed_finalize_accounts), + (true, commit_finalized_and_undelegated_accounts), + ] + .into_iter() + .flat_map(|(allow_undelegation, accounts)| { + accounts.into_iter().flatten().map(move |account| { + (account.pubkey, (allow_undelegation, account)) + }) + }) + .collect(); let statuses = service .get_commit_statuses(base_intent.id) @@ -778,17 +913,15 @@ async fn ix_commit_local( ); assert_eq!(statuses.len(), committed_accounts.len()); + for commit_status in statuses { let (is_undelegate, account) = committed_accounts .remove(&commit_status.pubkey) .expect("Account should be persisted"); // When we finalize it is possible to also undelegate the account - let expected_owner = if is_undelegate { - program_flexi_counter::id() - } else { - dlp_api::dlp::id() - }; + let expected_owner = + if is_undelegate { program_id } else { dlp::id() }; let lamports = account.account.lamports; get_account!( diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index b1f44e209..886c6ca8f 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -141,7 +141,9 @@ pub async fn tx_logs_contain( // in the logs when needle == CommitState. It's easier to make this little adjustment here than computing // the decision and passing either CommitState or CommitDiff from the tests themselves. if needle == "CommitState" { - log.contains(needle) || log.contains("CommitDiff") + log.contains(needle) + || log.contains("CommitDiff") + || log.contains("CommitFinalize") } else { log.contains(needle) } From 8e88e2786ed74df2d612c50e00f8f9ccb39a1d75 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 11 Mar 2026 15:37:36 +0530 Subject: [PATCH 02/10] re-implement CommitFinalize task conforming to the new task design --- .../src/tasks/commit_finalize_task.rs | 267 ++++++++++++++++++ magicblock-committor-service/src/tasks/mod.rs | 31 +- .../src/tasks/task_builder.rs | 33 ++- .../process_schedule_commit_finalize.rs | 4 +- 4 files changed, 301 insertions(+), 34 deletions(-) create mode 100644 magicblock-committor-service/src/tasks/commit_finalize_task.rs diff --git a/magicblock-committor-service/src/tasks/commit_finalize_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_task.rs new file mode 100644 index 000000000..fc6e3d43d --- /dev/null +++ b/magicblock-committor-service/src/tasks/commit_finalize_task.rs @@ -0,0 +1,267 @@ +use dlp::{ + args::CommitFinalizeArgs, + compute_diff, + instruction_builder::{commit_diff_size_budget, commit_size_budget}, + AccountSizeClass, +}; +use magicblock_committor_program::Chunks; +use magicblock_core::intent::CommittedAccount; +use solana_account::{Account, ReadableAccount}; +use solana_instruction::Instruction; +use solana_pubkey::Pubkey; + +use crate::{ + consts::MAX_WRITE_CHUNK_SIZE, + tasks::{ + commit_task::{CommitBufferStage, CommitDelivery}, + BaseTask, BaseTaskImpl, PreparationTask, + }, +}; + +/// A task that commits a delegated account's state to the base layer and finalizes it in the same +/// instruction. +/// +/// The delivery strategy ([`CommitDelivery`]) determines how the data reaches +/// the chain (inline args vs buffer, full state vs diff). +#[derive(Clone, Debug)] +pub struct CommitFinalizeTask { + pub commit_id: u64, + pub allow_undelegation: bool, + pub committed_account: CommittedAccount, + pub delivery: CommitDelivery, +} + +impl CommitFinalizeTask { + #[inline(always)] + fn commit_finalize_ix( + &self, + validator: &Pubkey, + base_account: Option<&Account>, + ) -> Instruction { + let (data, data_is_diff) = if let Some(base_account) = base_account { + ( + compute_diff( + base_account.data(), + self.committed_account.account.data(), + ) + .to_vec(), + true, + ) + } else { + (self.committed_account.account.data.clone(), false) + }; + + let mut args = CommitFinalizeArgs { + commit_id: self.commit_id, + lamports: self.committed_account.account.lamports, + data_is_diff: data_is_diff.into(), + allow_undelegation: self.allow_undelegation.into(), + bumps: Default::default(), + reserved_padding: Default::default(), + }; + + dlp::instruction_builder::commit_finalize( + *validator, + self.committed_account.pubkey, + &mut args, + &data, + ) + .0 + } + + #[inline(always)] + fn commit_finalize_from_buffer_ix( + &self, + validator: &Pubkey, + base_account: Option<&Account>, + ) -> Instruction { + let (data_buffer_pubkey, _) = + magicblock_committor_program::pdas::buffer_pda( + validator, + &self.committed_account.pubkey, + &self.commit_id.to_le_bytes(), + ); + + let mut args = CommitFinalizeArgs { + commit_id: self.commit_id, + lamports: self.committed_account.account.lamports, + data_is_diff: base_account.is_some().into(), + allow_undelegation: self.allow_undelegation.into(), + bumps: Default::default(), + reserved_padding: Default::default(), + }; + + dlp::instruction_builder::commit_finalize_from_buffer( + *validator, + self.committed_account.pubkey, + data_buffer_pubkey, + &mut args, + ) + .0 + } + + pub fn stage(&self) -> Option<&CommitBufferStage> { + match &self.delivery { + CommitDelivery::DiffInBuffer { + base_account: _, + stage, + } + | CommitDelivery::StateInBuffer { stage } => Some(stage), + CommitDelivery::StateInArgs | CommitDelivery::DiffInArgs { .. } => { + None + } + } + } + + pub fn stage_mut(&mut self) -> Option<&mut CommitBufferStage> { + match &mut self.delivery { + CommitDelivery::DiffInBuffer { + base_account: _, + stage, + } + | CommitDelivery::StateInBuffer { stage } => Some(stage), + CommitDelivery::StateInArgs | CommitDelivery::DiffInArgs { .. } => { + None + } + } + } + + pub fn is_buffer(&self) -> bool { + matches!( + self.delivery, + CommitDelivery::StateInBuffer { .. } + | CommitDelivery::DiffInBuffer { .. } + ) + } + + pub fn state_preparation_stage(&self) -> CommitBufferStage { + let data = self.committed_account.account.data.clone(); + self.preparation_stage(data) + } + + fn diff_preparation_stage(&self, base_data: &[u8]) -> CommitBufferStage { + let diff = + compute_diff(base_data, &self.committed_account.account.data) + .to_vec(); + self.preparation_stage(diff) + } + + fn preparation_stage(&self, committed_data: Vec) -> CommitBufferStage { + let chunks = Chunks::from_data_length( + committed_data.len(), + MAX_WRITE_CHUNK_SIZE, + ); + CommitBufferStage::Preparation(PreparationTask { + commit_id: self.commit_id, + pubkey: self.committed_account.pubkey, + committed_data, + chunks, + }) + } + + pub fn reset_commit_id(&mut self, commit_id: u64) { + self.commit_id = commit_id; + let new_stage = match &self.delivery { + CommitDelivery::StateInBuffer { .. } => { + self.state_preparation_stage() + } + CommitDelivery::DiffInBuffer { + base_account, + stage: _, + } => { + let slice = base_account.data.as_slice(); + self.diff_preparation_stage(slice) + } + _ => return, + }; + + match &mut self.delivery { + CommitDelivery::StateInBuffer { stage } => { + *stage = new_stage; + } + CommitDelivery::DiffInBuffer { + base_account: _, + stage, + } => { + *stage = new_stage; + } + _ => {} + } + } +} + +impl BaseTask for CommitFinalizeTask { + fn program_id(&self) -> Pubkey { + dlp::id() + } + + fn instruction(&self, validator: &Pubkey) -> Instruction { + match &self.delivery { + CommitDelivery::StateInArgs => { + self.commit_finalize_ix(validator, None) + } + CommitDelivery::StateInBuffer { .. } => { + self.commit_finalize_from_buffer_ix(validator, None) + } + CommitDelivery::DiffInArgs { base_account } => { + self.commit_finalize_ix(validator, Some(base_account)) + } + CommitDelivery::DiffInBuffer { base_account, .. } => self + .commit_finalize_from_buffer_ix(validator, Some(base_account)), + } + } + + fn try_optimize_tx_size(&mut self) -> bool { + let delivery = + std::mem::replace(&mut self.delivery, CommitDelivery::StateInArgs); + match delivery { + CommitDelivery::StateInArgs => { + let stage = self.state_preparation_stage(); + self.delivery = CommitDelivery::StateInBuffer { stage }; + true + } + CommitDelivery::DiffInArgs { base_account } => { + let stage = self.diff_preparation_stage(base_account.data()); + self.delivery = CommitDelivery::DiffInBuffer { + base_account, + stage, + }; + true + } + other @ (CommitDelivery::StateInBuffer { .. } + | CommitDelivery::DiffInBuffer { .. }) => { + self.delivery = other; + false + } + } + } + + fn compute_units(&self) -> u32 { + 70_000 + } + + fn accounts_size_budget(&self) -> u32 { + match &self.delivery { + CommitDelivery::StateInArgs => { + commit_size_budget(AccountSizeClass::Dynamic( + self.committed_account.account.data.len() as u32, + )) + } + CommitDelivery::StateInBuffer { .. } + | CommitDelivery::DiffInBuffer { .. } => { + commit_size_budget(AccountSizeClass::Huge) + } + CommitDelivery::DiffInArgs { .. } => { + commit_diff_size_budget(AccountSizeClass::Dynamic( + self.committed_account.account.data.len() as u32, + )) + } + } + } +} + +impl From for BaseTaskImpl { + fn from(value: CommitFinalizeTask) -> Self { + Self::CommitFinalize(value) + } +} diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 5998225bb..61f377643 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -10,13 +10,12 @@ use magicblock_committor_program::{ }, pdas, ChangesetChunks, Chunks, }; -use magicblock_core::intent::CommittedAccount; use magicblock_metrics::metrics::LabelValue; use magicblock_program::magic_scheduled_base_intent::BaseAction; -use solana_account::Account; use solana_instruction::{AccountMeta, Instruction}; use solana_pubkey::Pubkey; +pub mod commit_finalize_task; pub mod commit_task; pub mod task_builder; pub mod task_strategist; @@ -24,6 +23,7 @@ pub mod utils; pub use task_builder::TaskBuilderImpl; +use crate::tasks::commit_finalize_task::CommitFinalizeTask; use crate::tasks::commit_task::CommitTask; #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -44,6 +44,7 @@ pub enum TaskStrategy { #[derive(Clone, Debug)] pub enum BaseTaskImpl { Commit(CommitTask), + CommitFinalize(CommitFinalizeTask), Finalize(FinalizeTask), Undelegate(UndelegateTask), BaseAction(BaseActionTask), @@ -57,6 +58,7 @@ impl BaseTask for BaseTaskImpl { fn instruction(&self, validator: &Pubkey) -> Instruction { match self { Self::Commit(value) => value.instruction(validator), + Self::CommitFinalize(value) => value.instruction(validator), Self::Finalize(value) => value.instruction(validator), Self::Undelegate(value) => value.instruction(validator), Self::BaseAction(value) => value.instruction(validator), @@ -73,6 +75,7 @@ impl BaseTask for BaseTaskImpl { fn compute_units(&self) -> u32 { match self { Self::Commit(value) => value.compute_units(), + Self::CommitFinalize(value) => value.compute_units(), Self::BaseAction(value) => value.compute_units(), Self::Finalize(_) => 70_000, Self::Undelegate(_) => 70_000, @@ -82,6 +85,7 @@ impl BaseTask for BaseTaskImpl { fn accounts_size_budget(&self) -> u32 { match self { Self::Commit(value) => value.accounts_size_budget(), + Self::CommitFinalize(value) => value.accounts_size_budget(), Self::BaseAction(value) => value.accounts_size_budget(), Self::Finalize(_) => { dlp_api::instruction_builder::finalize_size_budget( @@ -116,6 +120,13 @@ impl LabelValue for BaseTaskImpl { "args_commit" } } + Self::CommitFinalize(task) => { + if task.is_buffer() { + "buffer_commit_finalize" + } else { + "args_commit_finalize" + } + } Self::Finalize(_) => "args_finalize", Self::Undelegate(_) => "args_undelegate", Self::BaseAction(BaseActionTask::V1(_)) => "args_action", @@ -155,22 +166,6 @@ pub trait BaseTask: Send + Sync + Clone { fn accounts_size_budget(&self) -> u32; } -#[derive(Clone, Debug)] -pub struct CommitDiffTask { - pub commit_id: u64, - pub allow_undelegation: bool, - pub committed_account: CommittedAccount, - pub base_account: Account, -} - -#[derive(Clone, Debug)] -pub struct CommitFinalizeTask { - pub commit_id: u64, - pub allow_undelegation: bool, - pub base_account: Option, // None implies commit-full-bytes else commit-diff - pub committed_account: CommittedAccount, -} - #[derive(Clone, Debug)] pub struct UndelegateTask { pub delegated_account: Pubkey, diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index f67ca49e6..36a6da3d6 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -3,8 +3,8 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ - BaseAction, CommitAndUndelegate, CommitType, CommittedAccount, - ScheduledIntentBundle, UndelegateType, + BaseAction, CommitAndUndelegate, CommitType, ScheduledIntentBundle, + UndelegateType, }; use solana_account::Account; use solana_pubkey::Pubkey; @@ -18,8 +18,8 @@ use crate::{ persist::IntentPersister, tasks::{ commit_task::{CommitDelivery, CommitTask}, - BaseActionTask, BaseActionTaskV1, BaseActionTaskV2, BaseTask, - BaseTaskImpl, CommitFinalizeTask, FinalizeTask, UndelegateTask, + BaseActionTask, BaseActionTaskV1, BaseActionTaskV2, BaseTaskImpl, + CommitFinalizeTask, FinalizeTask, UndelegateTask, }, }; @@ -134,7 +134,7 @@ impl TaskBuilderImpl { allow_undelegation: bool, account: CommittedAccount, base_account: Option, - ) -> ArgsTask { + ) -> CommitFinalizeTask { let base_account = if account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD { base_account @@ -142,13 +142,18 @@ impl TaskBuilderImpl { None }; - ArgsTaskType::CommitFinalize(CommitFinalizeTask { + let delivery_details = if let Some(base_account) = base_account { + CommitDelivery::DiffInArgs { base_account } + } else { + CommitDelivery::StateInArgs + }; + + CommitFinalizeTask { commit_id, allow_undelegation, committed_account: account, - base_account, - }) - .into() + delivery: delivery_details, + } } } @@ -239,11 +244,11 @@ impl TasksBuilder for TaskBuilderImpl { }); let base_account = base_accounts.remove(&account.pubkey); - if finalize { - Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account) + if finalize { + Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into() } else { - Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account) - }.into() + Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into() + } }, ); tasks.extend(commit_tasks_iter); @@ -301,7 +306,7 @@ impl TasksBuilder for TaskBuilderImpl { async fn create_undelegate_tasks( commit_and_undelegate: &CommitAndUndelegate, info_fetcher: &Arc, - ) -> TaskBuilderResult>> { + ) -> TaskBuilderResult> { // Get rent reimbursments for undelegated accounts let accounts = commit_and_undelegate.get_committed_accounts(); let mut min_context_slot = 0; diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs index 832cf63e3..1832b3693 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; +use magicblock_core::intent::CommittedAccount; // no direct token remap helpers needed here; handled in CommittedAccount builder use solana_account::{state_traits::StateMut, ReadableAccount}; use solana_instruction::error::InstructionError; @@ -10,8 +11,7 @@ use solana_pubkey::Pubkey; use crate::{ magic_scheduled_base_intent::{ validate_commit_schedule_permissions, CommitAndUndelegate, CommitType, - CommittedAccount, MagicBaseIntent, ScheduledIntentBundle, - UndelegateType, + MagicBaseIntent, ScheduledIntentBundle, UndelegateType, }, schedule_transactions::{self, ProcessScheduleCommitOptions}, utils::{ From 4d93a1e8d9a1c6db22e06ce0f3320e6b53ab09ef Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 11 Mar 2026 17:25:34 +0530 Subject: [PATCH 03/10] lint, format and fix tests --- magicblock-committor-service/src/tasks/mod.rs | 5 +++-- .../schedulecommit/test-scenarios/tests/03_commit_limit.rs | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 61f377643..382831bef 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -23,8 +23,9 @@ pub mod utils; pub use task_builder::TaskBuilderImpl; -use crate::tasks::commit_finalize_task::CommitFinalizeTask; -use crate::tasks::commit_task::CommitTask; +use crate::tasks::{ + commit_finalize_task::CommitFinalizeTask, commit_task::CommitTask, +}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum TaskType { diff --git a/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs b/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs index 0838a1cae..5816330fd 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs @@ -11,7 +11,8 @@ use program_schedulecommit::{ schedule_commit_cpi_with_vault_instruction, schedule_commit_with_vault_and_order_book_instruction, UserSeeds, }, - ScheduleCommitCpiWithVaultArgs, ScheduleCommitWithOrderBookArgs, + ScheduleCommitCpiWithVaultArgs, ScheduleCommitType, + ScheduleCommitWithOrderBookArgs, }; use schedulecommit_client::{ verify, ScheduleCommitTestContext, ScheduleCommitTestContextFields, @@ -71,6 +72,7 @@ fn get_prepared() -> &'static ScheduleCommitTestContext { None, &players, &pdas, + ScheduleCommitType::Commit, ); let blockhash = ephem_client.get_latest_blockhash().unwrap(); let tx = Transaction::new_signed_with_payer( @@ -129,6 +131,7 @@ fn test_schedule_commit_fails_at_commit_limit() { None, &[committee.0.pubkey()], &[committee.1], + ScheduleCommitType::Commit, ); let blockhash = ephem_client.get_latest_blockhash().unwrap(); let tx = Transaction::new_signed_with_payer( From 0380942b4a0ea720883292c68ad5da785227d750 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Mon, 23 Mar 2026 15:16:28 +0530 Subject: [PATCH 04/10] rebase fixes and adjustments --- Cargo.lock | 69 ++++-------- Cargo.toml | 2 +- magicblock-api/Cargo.toml | 2 +- magicblock-api/src/magic_validator.rs | 5 +- magicblock-chainlink/Cargo.toml | 2 +- magicblock-chainlink/src/accounts_bank.rs | 3 +- .../account_still_undelegating_on_chain.rs | 4 +- .../chainlink/fetch_cloner/ata_projection.rs | 2 +- .../src/chainlink/fetch_cloner/delegation.rs | 18 ++-- .../src/chainlink/fetch_cloner/mod.rs | 10 +- .../src/chainlink/fetch_cloner/pipeline.rs | 4 +- .../src/chainlink/fetch_cloner/tests.rs | 44 ++++---- magicblock-chainlink/src/chainlink/mod.rs | 2 +- .../chain_laser_actor/actor.rs | 2 +- .../chain_pubsub_actor.rs | 2 +- .../src/remote_account_provider/config.rs | 2 +- .../remote_account_provider/pubsub_common.rs | 4 +- .../remote_account_provider/remote_account.rs | 3 +- magicblock-chainlink/src/testing/deleg.rs | 12 +-- magicblock-chainlink/src/testing/eatas.rs | 2 +- magicblock-chainlink/src/testing/mod.rs | 6 +- .../tests/01_ensure-accounts.rs | 20 ++-- .../tests/03_deleg_after_sub.rs | 3 +- .../tests/04_redeleg_other_separate_slots.rs | 2 +- .../tests/05_redeleg_other_same_slot.rs | 2 +- .../tests/06_redeleg_us_separate_slots.rs | 2 +- .../tests/07_redeleg_us_same_slot.rs | 2 +- magicblock-chainlink/tests/basics.rs | 2 +- .../tests/utils/test_context.rs | 6 +- magicblock-committor-service/Cargo.toml | 2 +- .../src/intent_executor/error.rs | 13 +-- .../src/intent_executor/task_info_fetcher.rs | 4 +- .../src/pubkeys_provider.rs | 4 +- .../src/tasks/commit_finalize_task.rs | 10 +- .../src/tasks/commit_task.rs | 7 +- magicblock-committor-service/src/tasks/mod.rs | 4 +- .../src/tasks/utils.rs | 4 +- .../src/transactions.rs | 2 +- magicblock-validator-admin/Cargo.toml | 2 +- .../src/magic_scheduled_base_intent.rs | 2 + test-integration/Cargo.lock | 102 +++++++----------- test-integration/Cargo.toml | 2 +- .../programs/schedulecommit/Cargo.toml | 2 +- .../programs/schedulecommit/src/api.rs | 12 +-- .../programs/schedulecommit/src/lib.rs | 20 ++-- .../schedulecommit/client/Cargo.toml | 2 +- .../client/src/schedule_commit_context.rs | 2 +- .../schedulecommit/test-scenarios/Cargo.toml | 2 +- .../test-scenarios/tests/03_commit_limit.rs | 11 +- .../schedulecommit/test-security/Cargo.toml | 2 +- .../test-security/tests/01_invocations.rs | 3 +- test-integration/test-chainlink/Cargo.toml | 2 +- .../test-chainlink/src/ixtest_context.rs | 2 +- .../test-chainlink/src/test_context.rs | 6 +- test-integration/test-cloning/Cargo.toml | 2 +- .../10_post_delegation_token_transfer.rs | 8 +- .../test-committor-service/Cargo.toml | 2 +- .../test-committor-service/tests/common.rs | 4 +- .../tests/test_intent_executor.rs | 6 +- .../tests/test_ix_commit_local.rs | 7 +- .../test-ledger-restore/Cargo.toml | 2 +- .../test-ledger-restore/src/lib.rs | 6 +- .../tests/07_commit_delegated_account.rs | 7 +- .../test-magicblock-api/Cargo.toml | 2 +- .../tests/test_claim_fees.rs | 2 +- .../test-schedule-intent/Cargo.toml | 2 +- .../tests/test_schedule_intents.rs | 2 +- test-integration/test-tools/Cargo.toml | 2 +- .../test-tools/src/dlp_interface.rs | 10 +- .../src/integration_test_context.rs | 2 +- .../test-tools/src/loaded_accounts.rs | 6 +- 71 files changed, 230 insertions(+), 305 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2f54f2e6..50d665a0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,7 +182,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -193,7 +193,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1610,7 +1610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3435,14 +3435,16 @@ dependencies = [ ] [[package]] -name = "magicblock-delegation-program" -version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222#293e9222c2765c5405e2dfb4139cd71b86641d59" +name = "magicblock-delegation-program-api" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a413fd0a3ce67bba8c31b681f37088a897d47a3c39fd0d9303725882898ad78" dependencies = [ "bincode", "borsh 1.6.0", "bytemuck", "const-crypto", + "libsodium-rs", "num_enum", "pinocchio 0.10.2", "pinocchio-log", @@ -3451,30 +3453,15 @@ dependencies = [ "rkyv 0.7.46", "serde", "solana-address 2.2.0", - "solana-curve25519 3.1.10", "solana-instruction 3.2.0", "solana-program", + "solana-sdk", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", "thiserror 2.0.18", ] -[[package]] -name = "magicblock-delegation-program-api" -version = "0.1.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222#293e9222c2765c5405e2dfb4139cd71b86641d59" -dependencies = [ - "bincode", - "borsh 1.6.0", - "libsodium-rs", - "magicblock-delegation-program", - "serde", - "solana-program", - "solana-sdk", - "thiserror 2.0.18", -] - [[package]] name = "magicblock-ledger" version = "0.8.4" @@ -3950,7 +3937,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4572,7 +4559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", + "heck 0.5.0", "itertools 0.12.1", "log", "multimap", @@ -4592,7 +4579,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "itertools 0.14.0", "log", "multimap", @@ -5227,7 +5214,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5998,7 +5985,7 @@ dependencies = [ "solana-clock", "solana-compute-budget", "solana-cpi", - "solana-curve25519 2.2.1", + "solana-curve25519", "solana-feature-set", "solana-hash 2.2.1", "solana-instruction 2.2.1", @@ -6212,20 +6199,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "solana-curve25519" -version = "3.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d7e1177e6006823b91e0a930d94992ed74f8a6327d54ee50a9457ff72e625a" -dependencies = [ - "bytemuck", - "bytemuck_derive", - "curve25519-dalek 4.1.3", - "solana-define-syscall 3.0.0", - "subtle", - "thiserror 2.0.18", -] - [[package]] name = "solana-decode-error" version = "2.3.0" @@ -6241,12 +6214,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" -[[package]] -name = "solana-define-syscall" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9697086a4e102d28a156b8d6b521730335d6951bd39a5e766512bbe09007cee" - [[package]] name = "solana-define-syscall" version = "4.0.1" @@ -8434,7 +8401,7 @@ checksum = "170378693c5516090f6d37ae9bad2b9b6125069be68d9acd4865bbe9fc8499fd" dependencies = [ "base64 0.22.1", "bytemuck", - "solana-curve25519 2.2.1", + "solana-curve25519", "solana-zk-sdk", ] @@ -8445,7 +8412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eff2d6a445a147c9d6dd77b8301b1e116c8299601794b558eafa409b342faf96" dependencies = [ "bytemuck", - "solana-curve25519 2.2.1", + "solana-curve25519", "solana-program", "solana-zk-sdk", "spl-pod", @@ -8765,7 +8732,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix 1.1.2", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -9728,7 +9695,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 268275c8e..7a1b20f9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -dlp-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "293e9222", package = "magicblock-delegation-program-api" } +magicblock-delegation-program-api = { version = "0.1.1" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-api/Cargo.toml b/magicblock-api/Cargo.toml index 4ddde99a9..1c2bb001e 100644 --- a/magicblock-api/Cargo.toml +++ b/magicblock-api/Cargo.toml @@ -14,7 +14,7 @@ fd-lock = { workspace = true } tracing = { workspace = true } magic-domain-program = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-account-cloner = { workspace = true } magicblock-accounts = { workspace = true } magicblock-accounts-db = { workspace = true } diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 4307a16a1..39b67e1a5 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -8,7 +8,6 @@ use std::{ time::{Duration, Instant}, }; -use dlp_api::dlp; use magicblock_account_cloner::{ map_committor_request_result, ChainlinkCloner, }; @@ -671,9 +670,9 @@ impl MagicValidator { let validator_keypair = validator_authority(); let validator_pubkey = validator_keypair.pubkey(); let vault_pubkey = - dlp::pda::magic_fee_vault_pda_from_validator(&validator_pubkey); + dlp_api::pda::magic_fee_vault_pda_from_validator(&validator_pubkey); let delegation_record_pubkey = - dlp::pda::delegation_record_pda_from_delegated_account( + dlp_api::pda::delegation_record_pda_from_delegated_account( &vault_pubkey, ); diff --git a/magicblock-chainlink/Cargo.toml b/magicblock-chainlink/Cargo.toml index 9634b6363..1c4c4148f 100644 --- a/magicblock-chainlink/Cargo.toml +++ b/magicblock-chainlink/Cargo.toml @@ -18,7 +18,7 @@ magicblock-core = { workspace = true } parking_lot = { workspace = true } magicblock-magic-program-api = { workspace = true } magicblock-metrics = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } solana-account = { workspace = true } solana-account-decoder = { workspace = true } solana-account-decoder-client-types = { workspace = true } diff --git a/magicblock-chainlink/src/accounts_bank.rs b/magicblock-chainlink/src/accounts_bank.rs index c5d21d013..2403129a1 100644 --- a/magicblock-chainlink/src/accounts_bank.rs +++ b/magicblock-chainlink/src/accounts_bank.rs @@ -62,8 +62,7 @@ pub mod mock { // NOTE: that the validator will also have to set flip the delegated flag like // we do here. // See programs/magicblock/src/schedule_transactions/process_schedule_commit.rs :172 - self.set_owner(pubkey, dlp_api::dlp::id()) - .undelegate(pubkey); + self.set_owner(pubkey, dlp_api::id()).undelegate(pubkey); } pub fn set_undelegating( diff --git a/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs b/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs index 88c1b1bc3..1f4d135ec 100644 --- a/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs +++ b/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs @@ -1,4 +1,4 @@ -use dlp_api::dlp::state::DelegationRecord; +use dlp_api::state::DelegationRecord; use solana_pubkey::Pubkey; use tracing::*; @@ -83,7 +83,7 @@ pub(crate) fn account_still_undelegating_on_chain( #[cfg(test)] mod tests { - use dlp_api::dlp::state::DelegationRecord; + use dlp_api::state::DelegationRecord; use solana_pubkey::Pubkey; use super::*; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index 9ba7bb974..251281fec 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use dlp_api::dlp::state::DelegationRecord; +use dlp_api::state::DelegationRecord; use futures_util::future::join_all; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::try_derive_eata_address_and_bump; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 27898b4ee..9e726915c 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,10 +1,6 @@ use dlp_api::{ - decrypt::Decrypt, - dlp::{ - args::PostDelegationActions, - pda::delegation_record_pda_from_delegated_account, - state::DelegationRecord, - }, + args::PostDelegationActions, decrypt::Decrypt, + pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::{derive_eata, EATA_PROGRAM_ID}; @@ -237,7 +233,7 @@ where #[cfg(test)] mod tests { - use dlp_api::dlp::args::{ + use dlp_api::args::{ EncryptedBuffer, MaybeEncryptedAccountMeta, MaybeEncryptedInstruction, MaybeEncryptedIxData, MaybeEncryptedPubkey, PostDelegationActions, }; @@ -287,12 +283,12 @@ mod tests { program_id: 1, accounts: vec![ MaybeEncryptedAccountMeta::ClearText( - dlp_api::dlp::compact::AccountMeta::new_readonly( + dlp_api::compact::AccountMeta::new_readonly( 0, true, ), ), MaybeEncryptedAccountMeta::ClearText( - dlp_api::dlp::compact::AccountMeta::new(2, false), + dlp_api::compact::AccountMeta::new(2, false), ), ], data: MaybeEncryptedIxData { @@ -354,12 +350,12 @@ mod tests { program_id: 2, accounts: vec![ MaybeEncryptedAccountMeta::ClearText( - dlp_api::dlp::compact::AccountMeta::new_readonly( + dlp_api::compact::AccountMeta::new_readonly( 0, true, ), ), MaybeEncryptedAccountMeta::ClearText( - dlp_api::dlp::compact::AccountMeta::new(1, false), + dlp_api::compact::AccountMeta::new(1, false), ), ], data: MaybeEncryptedIxData { diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 795ae79f6..ff9964bfd 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -7,7 +7,7 @@ use std::{ time::Duration, }; -use dlp_api::dlp::{ +use dlp_api::{ pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use magicblock_accounts_db::traits::AccountsBank; @@ -360,7 +360,7 @@ where ) { return; } - } else if in_bank.owner().eq(&dlp_api::dlp::id()) { + } else if in_bank.owner().eq(&dlp_api::id()) { debug!( pubkey = %pubkey, "Received update for account owned by delegation program but not marked as undelegating" @@ -500,7 +500,7 @@ where return false; }; - if !account.owner().eq(&dlp_api::dlp::id()) { + if !account.owner().eq(&dlp_api::id()) { return false; } @@ -1447,7 +1447,7 @@ where ); return RefreshDecision::Yes; } - } else if in_bank.owner().eq(&dlp_api::dlp::id()) { + } else if in_bank.owner().eq(&dlp_api::id()) { debug!( "Account {pubkey} owned by deleg program not marked as undelegating" ); @@ -1502,7 +1502,7 @@ where if account_in_bank.undelegating() { undelegating_checks.push((**pubkey, account_in_bank)); } else { - if account_in_bank.owner().eq(&dlp_api::dlp::id()) { + if account_in_bank.owner().eq(&dlp_api::id()) { debug!( pubkey = %pubkey, "Account owned by deleg program not marked as undelegating" diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 0ac5cb586..9b584a4fa 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -1,6 +1,6 @@ use std::{collections::HashSet, sync::atomic::Ordering}; -use dlp_api::dlp::pda::delegation_record_pda_from_delegated_account; +use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::is_ata; use magicblock_metrics::metrics::AccountFetchOrigin; @@ -134,7 +134,7 @@ fn classify_single_account( ResolvedAccount::Fresh(account_shared_data) => { let slot = account_shared_data.remote_slot(); - if account_shared_data.owner().eq(&dlp_api::dlp::id()) { + if account_shared_data.owner().eq(&dlp_api::id()) { // Account owned by delegation program owned_by_deleg.push(( pubkey, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index bd6175dad..76e4d5582 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -194,7 +194,7 @@ fn create_non_raw_eata_owned_account( Account { lamports: 1_000_000, data, - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }, @@ -328,7 +328,7 @@ async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_rec let account = Account { lamports: 1_234, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -407,7 +407,7 @@ async fn test_fetch_and_clone_single_delegated_account_with_different_authority( let account = Account { lamports: 1_234, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -489,7 +489,7 @@ async fn test_fetch_and_clone_single_delegated_account_without_delegation_record let account = Account { lamports: 1_234, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -591,7 +591,7 @@ async fn test_fetch_and_clone_multiple_accounts_mixed_types() { let delegated_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -599,7 +599,7 @@ async fn test_fetch_and_clone_multiple_accounts_mixed_types() { let delegation_record_account = Account { lamports: 2_000_000, data: vec![100, 101, 102], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -667,7 +667,7 @@ async fn test_fetch_and_clone_multiple_accounts_mixed_types() { delegation_record_pubkey, delegation_record_account, CURRENT_SLOT, - dlp_api::dlp::id() + dlp_api::id() ); assert_subscribed_without_delegation_record!( @@ -695,7 +695,7 @@ async fn test_fetch_and_clone_valid_delegated_account_and_account_with_invalid_d let delegated_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -703,7 +703,7 @@ async fn test_fetch_and_clone_valid_delegated_account_and_account_with_invalid_d let invalid_delegated_account = Account { lamports: 500_000, data: vec![5, 6, 7, 8], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -777,7 +777,7 @@ async fn test_deleg_record_stale() { let account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -854,7 +854,7 @@ async fn test_account_stale() { let account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -929,7 +929,7 @@ async fn test_delegation_record_unsub_race_condition_prevention() { let account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -1087,7 +1087,7 @@ async fn test_undelegation_requested_subscription_behavior() { let account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -1158,7 +1158,7 @@ async fn test_delegated_authoritative_skip_unsubscribes_subscription() { let delegated_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -1461,7 +1461,7 @@ async fn test_confined_delegation_behavior() { let account1 = Account { lamports: 1_000_000, data: vec![1, 2, 3], - owner: dlp_api::dlp::id(), // Owned by DLP initially (as it is delegated) + owner: dlp_api::id(), // Owned by DLP initially (as it is delegated) executable: false, rent_epoch: 0, }; @@ -1471,7 +1471,7 @@ async fn test_confined_delegation_behavior() { let account2 = Account { lamports: 2_000_000, data: vec![4, 5, 6], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -1927,7 +1927,7 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_fetch() { let account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -2134,7 +2134,7 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_subscript let delegated_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -2377,7 +2377,7 @@ async fn test_discovered_dlp_owned_account_without_delegation_record_falls_back( let dlp_owned_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -2424,7 +2424,7 @@ async fn test_discovered_dlp_owned_account_without_delegation_record_falls_back( let cloned_account = accounts_bank .get_account(&account_pubkey) .expect("account should be cloned by fallback subscription path"); - assert_eq!(*cloned_account.owner(), dlp_api::dlp::id()); + assert_eq!(*cloned_account.owner(), dlp_api::id()); assert!(!cloned_account.delegated()); assert_eq!(cloned_account.remote_slot(), CURRENT_SLOT); } @@ -2441,7 +2441,7 @@ async fn test_discovered_dlp_owned_account_delegated_elsewhere_is_ignored() { let delegated_account = Account { lamports: 1_000_000, data: vec![1, 2, 3, 4], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; @@ -2585,7 +2585,7 @@ async fn test_subscription_update_with_delegation_actions_clones_dependencies() let delegated_account = Account { lamports: 1_000_000, data: vec![], - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }; diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index 0b5d80c5f..67063c3f3 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -6,7 +6,7 @@ use std::{ }, }; -use dlp_api::dlp::pda::ephemeral_balance_pda_from_payer; +use dlp_api::pda::ephemeral_balance_pda_from_payer; use errors::ChainlinkResult; use fetch_cloner::FetchCloner; use magicblock_accounts_db::{traits::AccountsBank, AccountsDbResult}; diff --git a/magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs b/magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs index b10757a56..ae313df42 100644 --- a/magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs +++ b/magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs @@ -736,7 +736,7 @@ impl> ChainLaserActor { let should_forward = self.stream_manager.is_subscribed(&pubkey) || matches!(source, AccountUpdateSource::Program) - && owner.eq(&dlp_api::dlp::id()) + && owner.eq(&dlp_api::id()) && !is_internal_dlp_account_data(&account.data); if !should_forward { return; diff --git a/magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs b/magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs index 3e6c9cc11..f42c4eedd 100644 --- a/magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs +++ b/magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs @@ -719,7 +719,7 @@ impl ChainPubsubActor { rpc_response, )); let should_forward = is_directly_subscribed - || program_pubkey.eq(&dlp_api::dlp::id()) + || program_pubkey.eq(&dlp_api::id()) && sub_update.account.as_ref().is_some_and( |account| { !is_internal_dlp_account_data( diff --git a/magicblock-chainlink/src/remote_account_provider/config.rs b/magicblock-chainlink/src/remote_account_provider/config.rs index 1176a8e2f..6df2fd9f3 100644 --- a/magicblock-chainlink/src/remote_account_provider/config.rs +++ b/magicblock-chainlink/src/remote_account_provider/config.rs @@ -122,7 +122,7 @@ impl Default for RemoteAccountProviderConfig { subscribed_accounts_lru_capacity: DEFAULT_MAX_MONITORED_ACCOUNTS, lifecycle_mode: LifecycleMode::default(), enable_subscription_metrics: true, - program_subs: vec![dlp_api::dlp::id()].into_iter().collect(), + program_subs: vec![dlp_api::id()].into_iter().collect(), resubscription_delay: std::time::Duration::from_millis( DEFAULT_RESUBSCRIPTION_DELAY_MS, ), diff --git a/magicblock-chainlink/src/remote_account_provider/pubsub_common.rs b/magicblock-chainlink/src/remote_account_provider/pubsub_common.rs index 6eefb9b22..405694cef 100644 --- a/magicblock-chainlink/src/remote_account_provider/pubsub_common.rs +++ b/magicblock-chainlink/src/remote_account_provider/pubsub_common.rs @@ -1,6 +1,6 @@ use std::{collections::HashSet, fmt}; -use dlp_api::dlp::state::{ +use dlp_api::state::{ CommitRecord, DelegationMetadata, DelegationRecord, ProgramConfig, }; use solana_account::Account; @@ -79,7 +79,7 @@ pub(crate) fn is_internal_dlp_account_data(data: &[u8]) -> bool { #[cfg(test)] mod tests { - use dlp_api::dlp::{ + use dlp_api::{ args::{ EncryptedBuffer, MaybeEncryptedInstruction, MaybeEncryptedIxData, PostDelegationActions, diff --git a/magicblock-chainlink/src/remote_account_provider/remote_account.rs b/magicblock-chainlink/src/remote_account_provider/remote_account.rs index e91c6da5e..fd79aea26 100644 --- a/magicblock-chainlink/src/remote_account_provider/remote_account.rs +++ b/magicblock-chainlink/src/remote_account_provider/remote_account.rs @@ -262,7 +262,6 @@ impl RemoteAccount { } pub fn is_owned_by_delegation_program(&self) -> bool { - self.owner() - .is_some_and(|owner| owner.eq(&dlp_api::dlp::id())) + self.owner().is_some_and(|owner| owner.eq(&dlp_api::id())) } } diff --git a/magicblock-chainlink/src/testing/deleg.rs b/magicblock-chainlink/src/testing/deleg.rs index 1578209d4..59f8df4cc 100644 --- a/magicblock-chainlink/src/testing/deleg.rs +++ b/magicblock-chainlink/src/testing/deleg.rs @@ -1,12 +1,12 @@ #[cfg(any(test, feature = "dev-context"))] -use dlp_api::dlp::args::{ +use dlp_api::args::{ EncryptedBuffer, MaybeEncryptedInstruction, MaybeEncryptedIxData, PostDelegationActions, }; #[cfg(any(test, feature = "dev-context"))] -use dlp_api::dlp::pda::delegation_record_pda_from_delegated_account; +use dlp_api::pda::delegation_record_pda_from_delegated_account; #[cfg(any(test, feature = "dev-context"))] -use dlp_api::dlp::state::DelegationRecord; +use dlp_api::state::DelegationRecord; #[cfg(any(test, feature = "dev-context"))] use solana_account::Account; #[cfg(any(test, feature = "dev-context"))] @@ -42,7 +42,7 @@ pub fn add_delegation_record_for( rpc_client.add_account( deleg_record_pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data: delegation_record_to_vec(&deleg_record), ..Default::default() }, @@ -86,7 +86,7 @@ pub fn add_delegation_record_with_actions_for( rpc_client.add_account( deleg_record_pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data, ..Default::default() }, @@ -106,7 +106,7 @@ pub fn add_invalid_delegation_record_for( rpc_client.add_account( deleg_record_pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data: invalid_data, ..Default::default() }, diff --git a/magicblock-chainlink/src/testing/eatas.rs b/magicblock-chainlink/src/testing/eatas.rs index efe4d4c69..ebf9e22b2 100644 --- a/magicblock-chainlink/src/testing/eatas.rs +++ b/magicblock-chainlink/src/testing/eatas.rs @@ -50,7 +50,7 @@ pub fn create_eata_account( let lamports = Rent::default().minimum_balance(data.len()); let account_owner = if delegate { - dlp_api::dlp::id() + dlp_api::id() } else { EATA_PROGRAM_ID }; diff --git a/magicblock-chainlink/src/testing/mod.rs b/magicblock-chainlink/src/testing/mod.rs index 04b2ea3b5..3b62b616d 100644 --- a/magicblock-chainlink/src/testing/mod.rs +++ b/magicblock-chainlink/src/testing/mod.rs @@ -47,7 +47,7 @@ macro_rules! assert_subscribed_without_delegation_record { ($provider:expr, $pubkeys:expr) => {{ for pubkey in $pubkeys { let deleg_record_pubkey = - ::dlp_api::dlp::pda::delegation_record_pda_from_delegated_account(pubkey); + ::dlp_api::pda::delegation_record_pda_from_delegated_account(pubkey); assert!( $provider.is_watching(pubkey), "Expected {} to be subscribed", @@ -363,7 +363,7 @@ macro_rules! assert_not_undelegating { ); assert_ne!( account.owner(), - &dlp_api::dlp::id(), + &dlp_api::id(), "Expected account {} to not be owned by the delegation program", pubkey, ); @@ -393,7 +393,7 @@ macro_rules! assert_remain_undelegating { ); assert_eq!( account.owner(), - &dlp_api::dlp::id(), + &dlp_api::id(), "Expected account {} to remain owned by the delegation program", pubkey, ); diff --git a/magicblock-chainlink/tests/01_ensure-accounts.rs b/magicblock-chainlink/tests/01_ensure-accounts.rs index f82953781..ada3afe24 100644 --- a/magicblock-chainlink/tests/01_ensure-accounts.rs +++ b/magicblock-chainlink/tests/01_ensure-accounts.rs @@ -1,5 +1,5 @@ use assert_matches::assert_matches; -use dlp_api::dlp::pda::delegation_record_pda_from_delegated_account; +use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_cloned, assert_not_found, assert_not_subscribed, @@ -99,7 +99,7 @@ async fn test_existing_account_missing_delegation_record() { rpc_client.add_account( pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), ..Default::default() }, ); @@ -137,7 +137,7 @@ async fn test_write_existing_account_valid_delegation_record() { let owner = Pubkey::new_unique(); let acc = Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), lamports: 1_234, ..Default::default() }; @@ -182,7 +182,7 @@ async fn test_write_existing_account_other_authority() { let pubkey = Pubkey::new_unique(); let account = Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), ..Default::default() }; rpc_client.add_account(pubkey, account); @@ -229,7 +229,7 @@ async fn test_write_undelegating_account_undelegated_to_other_validator() { // The account was re-delegated to other validator on chain let account = Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), ..Default::default() }; let owner = Pubkey::new_unique(); @@ -240,7 +240,7 @@ async fn test_write_undelegating_account_undelegated_to_other_validator() { // The same account is already marked as undelegated in the bank // (set the owner to the delegation program and mark it as _undelegating_) let mut shared_data = AccountSharedData::from(Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data: vec![0; 100], ..Default::default() }); @@ -278,7 +278,7 @@ async fn test_write_undelegating_account_still_being_undelegated() { // The account is still delegated to us on chain let account = Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), ..Default::default() }; let owner = Pubkey::new_unique(); @@ -289,7 +289,7 @@ async fn test_write_undelegating_account_still_being_undelegated() { // The same account is already marked as undelegated in the bank // (setting the owner to the delegation program marks it as _undelegating_) let mut shared_data = AccountSharedData::from(Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data: vec![0; 100], ..Default::default() }); @@ -327,7 +327,7 @@ async fn test_write_existing_account_invalid_delegation_record() { rpc_client.add_account( pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), ..Default::default() }, ); @@ -336,7 +336,7 @@ async fn test_write_existing_account_invalid_delegation_record() { rpc_client.add_account( deleg_record_pubkey, Account { - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), data: vec![1, 2, 3], ..Default::default() }, diff --git a/magicblock-chainlink/tests/03_deleg_after_sub.rs b/magicblock-chainlink/tests/03_deleg_after_sub.rs index 2cb774f3b..81baba293 100644 --- a/magicblock-chainlink/tests/03_deleg_after_sub.rs +++ b/magicblock-chainlink/tests/03_deleg_after_sub.rs @@ -104,8 +104,7 @@ async fn test_deleg_after_subscribe_case2() { info!("3. Delegate account to us"); slot = rpc_client.set_slot(slot + 11); - let acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + let acc = account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); let delegation_record = add_delegation_record_for( &rpc_client, pubkey, diff --git a/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs b/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs index 769abdf46..835726338 100644 --- a/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs +++ b/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs @@ -52,7 +52,7 @@ async fn test_undelegate_redelegate_to_other_in_separate_slot() { slot = rpc_client.set_slot(slot + 11); let delegated_acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); rpc_client.add_account(pubkey, delegated_acc.clone().into()); let delegation_record = add_delegation_record_for( &rpc_client, diff --git a/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs b/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs index 73c567516..664c9e940 100644 --- a/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs +++ b/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs @@ -51,7 +51,7 @@ async fn test_undelegate_redelegate_to_other_in_same_slot() { slot = rpc_client.set_slot(slot + 11); let delegated_acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); rpc_client.add_account(pubkey, delegated_acc.clone().into()); let delegation_record = add_delegation_record_for( &rpc_client, diff --git a/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs b/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs index 242aafc3b..e26956f1b 100644 --- a/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs +++ b/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs @@ -50,7 +50,7 @@ async fn test_undelegate_redelegate_to_us_in_separate_slots() { slot = rpc_client.set_slot(slot + 11); let delegated_acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); rpc_client.add_account(pubkey, delegated_acc.clone().into()); let delegation_record = add_delegation_record_for( diff --git a/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs b/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs index 3ff42bacf..911dd3004 100644 --- a/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs +++ b/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs @@ -55,7 +55,7 @@ async fn test_undelegate_redelegate_to_us_in_same_slot() { slot = rpc_client.set_slot(slot + 11); let delegated_acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); rpc_client.add_account(pubkey, delegated_acc.clone().into()); let delegation_record = add_delegation_record_for( diff --git a/magicblock-chainlink/tests/basics.rs b/magicblock-chainlink/tests/basics.rs index 74240e0e9..420100d69 100644 --- a/magicblock-chainlink/tests/basics.rs +++ b/magicblock-chainlink/tests/basics.rs @@ -95,7 +95,7 @@ async fn test_remote_slot_of_ensure_accounts_from_bank() { ..Default::default() }; let delegated_acc = - account_shared_with_owner_and_slot(&acc, dlp_api::dlp::id(), slot); + account_shared_with_owner_and_slot(&acc, dlp_api::id(), slot); rpc_client.add_account(pubkey, delegated_acc.into()); add_delegation_record_for(&rpc_client, pubkey, ctx.validator_pubkey, owner); diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index 4d6996dcd..6d7746016 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -248,9 +248,7 @@ impl TestContext { self.rpc_client.get_slot(), ); let delegation_record_pubkey = - dlp_api::dlp::pda::delegation_record_pda_from_delegated_account( - pubkey, - ); + dlp_api::pda::delegation_record_pda_from_delegated_account(pubkey); self.rpc_client.remove_account(&delegation_record_pubkey); let updated = self .send_and_receive_account_update( @@ -282,7 +280,7 @@ impl TestContext { // Update account to be delegated on chain and send a sub update let acc = self.rpc_client.get_account_at_slot(pubkey).unwrap(); let delegated_acc = - account_shared_with_owner(&acc.account, dlp_api::dlp::id()); + account_shared_with_owner(&acc.account, dlp_api::id()); let updated = self .send_and_receive_account_update( *pubkey, diff --git a/magicblock-committor-service/Cargo.toml b/magicblock-committor-service/Cargo.toml index 358ec48c2..60a68d2a1 100644 --- a/magicblock-committor-service/Cargo.toml +++ b/magicblock-committor-service/Cargo.toml @@ -23,7 +23,7 @@ magicblock-committor-program = { workspace = true, features = [ "no-entrypoint", ] } magicblock-core = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-metrics = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } diff --git a/magicblock-committor-service/src/intent_executor/error.rs b/magicblock-committor-service/src/intent_executor/error.rs index 9350e5df3..1ca4fd9f9 100644 --- a/magicblock-committor-service/src/intent_executor/error.rs +++ b/magicblock-committor-service/src/intent_executor/error.rs @@ -221,19 +221,16 @@ impl TransactionStrategyExecutionError { ) -> Result { // Commit Nonce order error const NONCE_OUT_OF_ORDER: u32 = - dlp_api::dlp::error::DlpError::NonceOutOfOrder as u32; + dlp_api::error::DlpError::NonceOutOfOrder as u32; // Errors when commit state already exists const COMMIT_STATE_INVALID_ACCOUNT_OWNER: u32 = - dlp_api::dlp::error::DlpError::CommitStateInvalidAccountOwner - as u32; + dlp_api::error::DlpError::CommitStateInvalidAccountOwner as u32; const COMMIT_STATE_ALREADY_INITIALIZED: u32 = - dlp_api::dlp::error::DlpError::CommitStateAlreadyInitialized as u32; + dlp_api::error::DlpError::CommitStateAlreadyInitialized as u32; const COMMIT_RECORD_INVALID_ACCOUNT_OWNER: u32 = - dlp_api::dlp::error::DlpError::CommitRecordInvalidAccountOwner - as u32; + dlp_api::error::DlpError::CommitRecordInvalidAccountOwner as u32; const COMMIT_RECORD_ALREADY_INITIALIZED: u32 = - dlp_api::dlp::error::DlpError::CommitRecordAlreadyInitialized - as u32; + dlp_api::error::DlpError::CommitRecordAlreadyInitialized as u32; match err { // Some tx may use too much CPIs and we can handle it in certain cases diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index f3d317e49..0e4607c02 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -7,7 +7,7 @@ use std::{ }; use async_trait::async_trait; -use dlp_api::dlp::{ +use dlp_api::{ delegation_metadata_seeds_from_delegated_account, state::DelegationMetadata, }; use lru::LruCache; @@ -92,7 +92,7 @@ impl RpcTaskInfoFetcher { delegation_metadata_seeds_from_delegated_account!( delegated_account ), - &dlp_api::dlp::id(), + &dlp_api::id(), ) .0 }) diff --git a/magicblock-committor-service/src/pubkeys_provider.rs b/magicblock-committor-service/src/pubkeys_provider.rs index 21e397cd9..9995c174e 100644 --- a/magicblock-committor-service/src/pubkeys_provider.rs +++ b/magicblock-committor-service/src/pubkeys_provider.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use dlp_api::dlp::pda; +use dlp_api::pda; use solana_pubkey::Pubkey; use solana_system_program::id as system_program_id; use tracing::*; @@ -41,7 +41,7 @@ pub fn provide_committee_pubkeys( pub fn provide_common_pubkeys(validator: &Pubkey) -> HashSet { let mut set = HashSet::new(); - let deleg_program = dlp_api::dlp::id(); + let deleg_program = dlp_api::id(); let protocol_fees_vault = pda::fees_vault_pda(); let validator_fees_vault = pda::validator_fees_vault_pda_from_validator(validator); diff --git a/magicblock-committor-service/src/tasks/commit_finalize_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_task.rs index fc6e3d43d..df1f84267 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_task.rs @@ -1,6 +1,6 @@ -use dlp::{ +use dlp_api::{ args::CommitFinalizeArgs, - compute_diff, + diff::compute_diff, instruction_builder::{commit_diff_size_budget, commit_size_budget}, AccountSizeClass, }; @@ -60,7 +60,7 @@ impl CommitFinalizeTask { reserved_padding: Default::default(), }; - dlp::instruction_builder::commit_finalize( + dlp_api::instruction_builder::commit_finalize( *validator, self.committed_account.pubkey, &mut args, @@ -91,7 +91,7 @@ impl CommitFinalizeTask { reserved_padding: Default::default(), }; - dlp::instruction_builder::commit_finalize_from_buffer( + dlp_api::instruction_builder::commit_finalize_from_buffer( *validator, self.committed_account.pubkey, data_buffer_pubkey, @@ -192,7 +192,7 @@ impl CommitFinalizeTask { impl BaseTask for CommitFinalizeTask { fn program_id(&self) -> Pubkey { - dlp::id() + dlp_api::id() } fn instruction(&self, validator: &Pubkey) -> Instruction { diff --git a/magicblock-committor-service/src/tasks/commit_task.rs b/magicblock-committor-service/src/tasks/commit_task.rs index 5deee03d1..e40ea7441 100644 --- a/magicblock-committor-service/src/tasks/commit_task.rs +++ b/magicblock-committor-service/src/tasks/commit_task.rs @@ -1,6 +1,7 @@ -use dlp_api::dlp::{ +use dlp_api::{ args::{CommitDiffArgs, CommitStateArgs, CommitStateFromBufferArgs}, - compute_diff, AccountSizeClass, + diff::compute_diff, + AccountSizeClass, }; use magicblock_committor_program::Chunks; use magicblock_core::intent::CommittedAccount; @@ -229,7 +230,7 @@ impl CommitTask { impl BaseTask for CommitTask { fn program_id(&self) -> Pubkey { - dlp_api::dlp::id() + dlp_api::id() } fn instruction(&self, validator: &Pubkey) -> Instruction { diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 382831bef..1be2dd82b 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -1,4 +1,4 @@ -use dlp_api::dlp::{args::CallHandlerArgs, AccountSizeClass}; +use dlp_api::{args::CallHandlerArgs, AccountSizeClass}; use magicblock_committor_program::{ instruction_builder::{ close_buffer::{create_close_ix, CreateCloseIxArgs}, @@ -53,7 +53,7 @@ pub enum BaseTaskImpl { impl BaseTask for BaseTaskImpl { fn program_id(&self) -> Pubkey { - dlp_api::dlp::id() + dlp_api::id() } fn instruction(&self, validator: &Pubkey) -> Instruction { diff --git a/magicblock-committor-service/src/tasks/utils.rs b/magicblock-committor-service/src/tasks/utils.rs index dc9f8fcbc..e38008bed 100644 --- a/magicblock-committor-service/src/tasks/utils.rs +++ b/magicblock-committor-service/src/tasks/utils.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use dlp_api::dlp::DLP_PROGRAM_DATA_SIZE_CLASS; +use dlp_api::DLP_PROGRAM_DATA_SIZE_CLASS; use solana_compute_budget_interface::ComputeBudgetInstruction; use solana_hash::Hash; use solana_instruction::Instruction; @@ -141,7 +141,7 @@ impl TransactionUtils { let dlp_task_count: u32 = tasks .iter() - .filter(|task| task.program_id() == dlp_api::dlp::id()) + .filter(|task| task.program_id() == dlp_api::id()) .count() as u32; if dlp_task_count > 0 { diff --git a/magicblock-committor-service/src/transactions.rs b/magicblock-committor-service/src/transactions.rs index 4b2e81419..84bf3180c 100644 --- a/magicblock-committor-service/src/transactions.rs +++ b/magicblock-committor-service/src/transactions.rs @@ -78,7 +78,7 @@ pub fn serialize_and_encode_base64( mod test { use std::collections::HashSet; - use dlp_api::dlp::args::{CommitStateArgs, CommitStateFromBufferArgs}; + use dlp_api::args::{CommitStateArgs, CommitStateFromBufferArgs}; use lazy_static::lazy_static; use magicblock_committor_program::instruction_builder::close_buffer::{ create_close_ix, CreateCloseIxArgs, diff --git a/magicblock-validator-admin/Cargo.toml b/magicblock-validator-admin/Cargo.toml index 4e782ad7d..8f191e8c5 100644 --- a/magicblock-validator-admin/Cargo.toml +++ b/magicblock-validator-admin/Cargo.toml @@ -10,7 +10,7 @@ edition.workspace = true [dependencies] tracing = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 6e685adec..677261492 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -1247,6 +1247,8 @@ mod tests { make_base_action(100_000), ]), }), + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![make_base_action(50_000)], }, }; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 7948cd171..1e4726d63 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1769,7 +1769,7 @@ dependencies = [ "ephemeral-rollups-sdk-attribute-ephemeral", "ephemeral-rollups-sdk-attribute-ephemeral-accounts", "getrandom 0.2.16", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=abf340536e88740c290b2b3af4e3d1ff38240f63)", + "magicblock-delegation-program-api 0.1.0", "magicblock-magic-program-api 0.8.2", "solana-account", "solana-account-info", @@ -2983,7 +2983,7 @@ dependencies = [ "color-backtrace", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "rand 0.8.5", "rayon", "serde", @@ -3560,7 +3560,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-ledger", "magicblock-magic-program-api 0.8.4", "magicblock-metrics", @@ -3614,7 +3614,7 @@ dependencies = [ "magicblock-accounts-db", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-magic-program-api 0.8.4", "magicblock-metrics", "parking_lot", @@ -3680,7 +3680,7 @@ dependencies = [ "lru", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3759,21 +3759,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program" version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222#293e9222c2765c5405e2dfb4139cd71b86641d59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e25f9e37194cc27c0f1d3dbc00e83795f7f4012f1a99c20bc557bdeb62e13e" -dependencies = [ - "borsh 1.6.0", - "bytemuck", - "num_enum", - "solana-program", - "static_assertions", -] - -[[package]] -name = "magicblock-delegation-program" -version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer#1347f31982a57762bd9321c91a021a3d32bebe05" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=abf340536e88740c290b2b3af4e3d1ff38240f63#abf340536e88740c290b2b3af4e3d1ff38240f63" dependencies = [ "bincode", "borsh 1.6.0", @@ -3790,7 +3776,6 @@ dependencies = [ "solana-curve25519", "solana-instruction 3.2.0", "solana-program", - "solana-security-txt", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", @@ -3798,14 +3783,29 @@ dependencies = [ ] [[package]] -name = "magicblock-delegation-program" -version = "1.1.3" +name = "magicblock-delegation-program-api" +version = "0.1.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=abf340536e88740c290b2b3af4e3d1ff38240f63#abf340536e88740c290b2b3af4e3d1ff38240f63" +dependencies = [ + "bincode", + "borsh 1.6.0", + "magicblock-delegation-program", + "serde", + "solana-program", + "thiserror 2.0.18", +] + +[[package]] +name = "magicblock-delegation-program-api" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a413fd0a3ce67bba8c31b681f37088a897d47a3c39fd0d9303725882898ad78" dependencies = [ "bincode", "borsh 1.6.0", "bytemuck", "const-crypto", + "libsodium-rs", "num_enum", "pinocchio 0.10.2", "pinocchio-log", @@ -3814,43 +3814,15 @@ dependencies = [ "rkyv 0.7.45", "serde", "solana-address", - "solana-curve25519", "solana-instruction 3.2.0", "solana-program", + "solana-sdk", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", "thiserror 2.0.18", ] -[[package]] -name = "magicblock-delegation-program-api" -version = "0.1.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222#293e9222c2765c5405e2dfb4139cd71b86641d59" -dependencies = [ - "bincode", - "borsh 1.6.0", - "libsodium-rs", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", - "serde", - "solana-program", - "solana-sdk", - "thiserror 2.0.18", -] - -[[package]] -name = "magicblock-delegation-program-api" -version = "0.1.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=abf340536e88740c290b2b3af4e3d1ff38240f63#abf340536e88740c290b2b3af4e3d1ff38240f63" -dependencies = [ - "bincode", - "borsh 1.6.0", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=abf340536e88740c290b2b3af4e3d1ff38240f63)", - "serde", - "solana-program", - "thiserror 2.0.18", -] - [[package]] name = "magicblock-ledger" version = "0.8.4" @@ -4074,7 +4046,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.4" dependencies = [ - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -5025,7 +4997,7 @@ version = "0.0.0" dependencies = [ "borsh 1.6.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-magic-program-api 0.8.4", "rkyv 0.7.45", "solana-program", @@ -5116,7 +5088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", + "heck 0.5.0", "itertools 0.12.1", "log", "multimap", @@ -5136,7 +5108,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "itertools 0.12.1", "log", "multimap", @@ -6012,7 +5984,7 @@ dependencies = [ "borsh 1.6.0", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "program-schedulecommit", "solana-program", "solana-rpc-client", @@ -6031,7 +6003,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -6056,7 +6028,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-magic-program-api 0.8.4", "magicblock-program", "program-schedulecommit", @@ -6077,7 +6049,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-magic-program-api 0.8.4", "program-schedulecommit", "program-schedulecommit-security", @@ -10361,7 +10333,7 @@ dependencies = [ "integration-test-tools", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "program-flexi-counter", "program-mini", "solana-account", @@ -10384,7 +10356,7 @@ name = "test-cloning" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "program-flexi-counter", "program-mini", "solana-loader-v4-interface", @@ -10448,7 +10420,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "program-flexi-counter", "solana-rpc-client", "solana-sdk", @@ -10469,7 +10441,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "magicblock-program", "magicblock-validator-admin", "solana-rpc-client", @@ -10509,7 +10481,7 @@ name = "test-schedule-intent" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 0.1.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=293e9222)", + "magicblock-delegation-program-api 0.1.1", "program-flexi-counter", "solana-rpc-client-api", "solana-sdk", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 0f3606495..e860fe05a 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -60,7 +60,7 @@ magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain- "modular-sdk", ] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -dlp-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "293e9222", package = "magicblock-delegation-program-api", default-features = false } +magicblock-delegation-program-api = { version = "0.1.1", default-features = false } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } magicblock-table-mania = { path = "../magicblock-table-mania" } diff --git a/test-integration/programs/schedulecommit/Cargo.toml b/test-integration/programs/schedulecommit/Cargo.toml index d62ff9b24..26b1a47fc 100644 --- a/test-integration/programs/schedulecommit/Cargo.toml +++ b/test-integration/programs/schedulecommit/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true borsh = { workspace = true } ephemeral-rollups-sdk = { workspace = true } solana-program = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock_magic_program_api = { workspace = true } rkyv = { workspace = true } static_assertions = { workspace = true } diff --git a/test-integration/programs/schedulecommit/src/api.rs b/test-integration/programs/schedulecommit/src/api.rs index b88047d4c..d8b5996df 100644 --- a/test-integration/programs/schedulecommit/src/api.rs +++ b/test-integration/programs/schedulecommit/src/api.rs @@ -1,7 +1,4 @@ -use dlp_api::{ - dlp, - dlp::args::{DelegateArgs, DelegateEphemeralBalanceArgs}, -}; +use dlp_api::args::{DelegateArgs, DelegateEphemeralBalanceArgs}; use ephemeral_rollups_sdk::delegate_args::{ DelegateAccountMetas, DelegateAccounts, }; @@ -223,7 +220,9 @@ pub fn schedule_commit_cpi_with_vault_instruction( ]; if args.has_magic_vault { account_metas.push(AccountMeta { - pubkey: dlp::pda::magic_fee_vault_pda_from_validator(&validator), + pubkey: dlp_api::pda::magic_fee_vault_pda_from_validator( + &validator, + ), is_writable: true, is_signer: false, }) @@ -257,7 +256,7 @@ pub fn schedule_commit_with_vault_and_order_book_instruction( ) -> Instruction { let program_id = crate::id(); let magic_fee_vault = - dlp::pda::magic_fee_vault_pda_from_validator(&validator); + dlp_api::pda::magic_fee_vault_pda_from_validator(&validator); let mut account_metas = vec![ AccountMeta::new(payer, true), AccountMeta::new(magic_context_id, false), @@ -354,6 +353,7 @@ pub fn schedule_commit_and_undelegate_cpi_instruction( ) } +#[allow(clippy::too_many_arguments)] fn schedule_commit_cpi_instruction_impl( payer: Pubkey, magic_program_id: Pubkey, diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index cd278496c..71830e1ef 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -186,9 +186,6 @@ pub enum ScheduleCommitInstruction { /// Update order book UpdateOrderBook(BookUpdate), - /// ScheduleCommitDiffCpi - ScheduleCommitForOrderBook, - /// Commit accounts via MagicIntentBundleBuilder with fee vault and a /// post-commit UpdateOrderBook action. /// @@ -219,17 +216,23 @@ impl ScheduleCommitType { accounts: Vec<&'a AccountInfo<'info>>, magic_context: &'a AccountInfo<'info>, magic_program: &'a AccountInfo<'info>, + magic_fee_vault: Option<&'a AccountInfo<'info>>, ) -> ProgramResult { match self { - ScheduleCommitType::Commit => { - commit_accounts(payer, accounts, magic_context, magic_program) - } + ScheduleCommitType::Commit => commit_accounts( + payer, + accounts, + magic_context, + magic_program, + magic_fee_vault, + ), ScheduleCommitType::CommitAndUndelegate => { commit_and_undelegate_accounts( payer, accounts, magic_context, magic_program, + magic_fee_vault, ) } ScheduleCommitType::CommitFinalize => commit_finalize_accounts( @@ -665,10 +668,6 @@ pub fn process_schedulecommit_cpi( } } - // Then request the PDA accounts to be committed - let mut account_infos = vec![payer, magic_context]; - account_infos.extend(remaining.iter()); - let mut committees = remaining.iter().collect::>(); if args.commit_payer { msg!("Commiting payer"); @@ -685,6 +684,7 @@ pub fn process_schedulecommit_cpi( committees, magic_context, magic_program, + magic_fee_vault, )?; Ok(()) diff --git a/test-integration/schedulecommit/client/Cargo.toml b/test-integration/schedulecommit/client/Cargo.toml index b72af6f11..27ccc7a11 100644 --- a/test-integration/schedulecommit/client/Cargo.toml +++ b/test-integration/schedulecommit/client/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } anyhow = { workspace = true } borsh = { workspace = true } integration-test-tools = { workspace = true } diff --git a/test-integration/schedulecommit/client/src/schedule_commit_context.rs b/test-integration/schedulecommit/client/src/schedule_commit_context.rs index 25f322b26..ca69a7d55 100644 --- a/test-integration/schedulecommit/client/src/schedule_commit_context.rs +++ b/test-integration/schedulecommit/client/src/schedule_commit_context.rs @@ -134,7 +134,7 @@ impl ScheduleCommitTestContext { .with_context(|| "Failed to fetch ephemeral payer account")?; trace!("Payer Ephem Account: {:#?}", payer_ephem_on_chain); assert!(payer_ephem_on_chain.lamports >= lamports / 2,); - assert_eq!(payer_ephem_on_chain.owner, dlp_api::dlp::id()); + assert_eq!(payer_ephem_on_chain.owner, dlp_api::id()); let payer_chain_on_ephem = ictx.fetch_ephem_account(payer_chain.pubkey())?; diff --git a/test-integration/schedulecommit/test-scenarios/Cargo.toml b/test-integration/schedulecommit/test-scenarios/Cargo.toml index ef903a5d3..82266c3f4 100644 --- a/test-integration/schedulecommit/test-scenarios/Cargo.toml +++ b/test-integration/schedulecommit/test-scenarios/Cargo.toml @@ -12,7 +12,7 @@ schedulecommit-client = { workspace = true } magicblock-core = { workspace = true } magicblock-program = { workspace = true } magicblock_magic_program_api = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } solana-program = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs b/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs index 5816330fd..0331de5b2 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/03_commit_limit.rs @@ -1,6 +1,5 @@ use std::sync::OnceLock; -use dlp_api::dlp; use integration_test_tools::run_test; use magicblock_program::magic_sys::{COMMIT_LIMIT, COMMIT_LIMIT_ERR}; use program_schedulecommit::{ @@ -448,8 +447,9 @@ fn test_fee_charged_and_vault_credited_after_actual_commit_limit() { } = ctx.fields(); let committee = &committees[IDX_OVER_LIMIT]; - let magic_fee_vault = - dlp::pda::magic_fee_vault_pda_from_validator(validator_identity); + let magic_fee_vault = dlp_api::pda::magic_fee_vault_pda_from_validator( + validator_identity, + ); let payer_balance_before = ctx.fetch_ephem_account_balance(&payer.pubkey()).unwrap(); @@ -539,8 +539,9 @@ fn test_schedule_commit_with_vault_and_order_book_action() { } = ctx.fields(); let committee = &committees[IDX_OVER_LIMIT]; - let magic_fee_vault = - dlp::pda::magic_fee_vault_pda_from_validator(validator_identity); + let magic_fee_vault = dlp_api::pda::magic_fee_vault_pda_from_validator( + validator_identity, + ); let payer_balance_before = ctx.fetch_ephem_account_balance(&payer.pubkey()).unwrap(); diff --git a/test-integration/schedulecommit/test-security/Cargo.toml b/test-integration/schedulecommit/test-security/Cargo.toml index 79e83801c..4838bb11b 100644 --- a/test-integration/schedulecommit/test-security/Cargo.toml +++ b/test-integration/schedulecommit/test-security/Cargo.toml @@ -11,7 +11,7 @@ program-schedulecommit-security = { workspace = true, features = [ schedulecommit-client = { workspace = true } magicblock-core = { workspace = true } magicblock_magic_program_api = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } solana-rpc-client-api = { workspace = true } solana-sdk = { workspace = true } integration-test-tools = { workspace = true } diff --git a/test-integration/schedulecommit/test-security/tests/01_invocations.rs b/test-integration/schedulecommit/test-security/tests/01_invocations.rs index 1f19d91a0..17dc1bd25 100644 --- a/test-integration/schedulecommit/test-security/tests/01_invocations.rs +++ b/test-integration/schedulecommit/test-security/tests/01_invocations.rs @@ -1,4 +1,3 @@ -use dlp_api::dlp; use program_schedulecommit::{ api::{schedule_commit_cpi_instruction, UserSeeds}, ScheduleCommitType, @@ -77,7 +76,7 @@ fn create_schedule_commit_ix( } fn magic_fee_vault(ctx: &ScheduleCommitTestContext) -> Pubkey { - dlp::pda::magic_fee_vault_pda_from_validator( + dlp_api::pda::magic_fee_vault_pda_from_validator( &ctx.ephem_validator_identity().unwrap(), ) } diff --git a/test-integration/test-chainlink/Cargo.toml b/test-integration/test-chainlink/Cargo.toml index 900bdbc69..5b9cbe600 100644 --- a/test-integration/test-chainlink/Cargo.toml +++ b/test-integration/test-chainlink/Cargo.toml @@ -9,7 +9,7 @@ futures = { workspace = true } tracing = { workspace = true } magicblock-chainlink = { workspace = true } magicblock-config = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } program-mini = { workspace = true, features = ["no-entrypoint"] } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-account = { workspace = true } diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 4b83018ec..6fad665e6 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -309,7 +309,7 @@ impl IxtestContext { self.validator_kp.pubkey(), counter_pda, program_flexi_counter::id(), - dlp_api::dlp::args::CommitStateArgs { + dlp_api::args::CommitStateArgs { nonce: 1, lamports: 1_000_000, allow_undelegation: true, diff --git a/test-integration/test-chainlink/src/test_context.rs b/test-integration/test-chainlink/src/test_context.rs index 28476c0ee..71128cc06 100644 --- a/test-integration/test-chainlink/src/test_context.rs +++ b/test-integration/test-chainlink/src/test_context.rs @@ -252,9 +252,7 @@ impl TestContext { self.rpc_client.get_slot(), ); let delegation_record_pubkey = - dlp_api::dlp::pda::delegation_record_pda_from_delegated_account( - pubkey, - ); + dlp_api::pda::delegation_record_pda_from_delegated_account(pubkey); self.rpc_client.remove_account(&delegation_record_pubkey); let updated = self .send_and_receive_account_update( @@ -286,7 +284,7 @@ impl TestContext { // Update account to be delegated on chain and send a sub update let acc = self.rpc_client.get_account_at_slot(pubkey).unwrap(); let delegated_acc = - account_shared_with_owner(&acc.account, dlp_api::dlp::id()); + account_shared_with_owner(&acc.account, dlp_api::id()); let updated = self .send_and_receive_account_update( *pubkey, diff --git a/test-integration/test-cloning/Cargo.toml b/test-integration/test-cloning/Cargo.toml index 15c5383c3..b347a464f 100644 --- a/test-integration/test-cloning/Cargo.toml +++ b/test-integration/test-cloning/Cargo.toml @@ -9,7 +9,7 @@ program-mini = { workspace = true, features = ["no-entrypoint"] } integration-test-tools = { workspace = true } tracing = { workspace = true } test-chainlink = { workspace = true } -dlp-api = { workspace = true, features = ["encryption"] } +magicblock-delegation-program-api = { workspace = true, features = ["encryption"] } solana-loader-v4-interface = { workspace = true, features = ["serde"] } solana-sdk = { workspace = true } spl-token = { workspace = true } diff --git a/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs b/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs index 8a6403894..7d96119df 100644 --- a/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs +++ b/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs @@ -1,7 +1,7 @@ use std::{thread::sleep, time::Duration}; use dlp_api::{ - dlp::args::DelegateArgs, + args::DelegateArgs, instruction_builder::{ delegate_with_actions, Encryptable, PostDelegationInstruction, }, @@ -178,10 +178,8 @@ fn test_post_delegation_action_executes_spl_token_transfer_100() { post_actions, ); - let assign_ix = system_instruction::assign( - &delegated_account.pubkey(), - &dlp_api::dlp::id(), - ); + let assign_ix = + system_instruction::assign(&delegated_account.pubkey(), &dlp_api::id()); let mut assign_tx = Transaction::new_with_payer(&[assign_ix], Some(&fee_payer.pubkey())); let (_sig, confirmed) = ctx diff --git a/test-integration/test-committor-service/Cargo.toml b/test-integration/test-committor-service/Cargo.toml index 97d9e7452..65ead70d8 100644 --- a/test-integration/test-committor-service/Cargo.toml +++ b/test-integration/test-committor-service/Cargo.toml @@ -15,7 +15,7 @@ magicblock-committor-program = { workspace = true, features = [ magicblock-committor-service = { workspace = true, features = [ "dev-context-only-utils", ] } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } magicblock-table-mania = { workspace = true, features = [ diff --git a/test-integration/test-committor-service/tests/common.rs b/test-integration/test-committor-service/tests/common.rs index 7bea5c12d..c406d7681 100644 --- a/test-integration/test-committor-service/tests/common.rs +++ b/test-integration/test-committor-service/tests/common.rs @@ -108,7 +108,7 @@ pub fn create_commit_task(data: &[u8]) -> CommitTask { account: Account { lamports: 1000, data: data.to_vec(), - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }, @@ -135,7 +135,7 @@ pub fn create_committed_account(data: &[u8]) -> CommittedAccount { account: Account { lamports: 1000, data: data.to_vec(), - owner: dlp_api::dlp::id(), + owner: dlp_api::id(), executable: false, rent_epoch: 0, }, diff --git a/test-integration/test-committor-service/tests/test_intent_executor.rs b/test-integration/test-committor-service/tests/test_intent_executor.rs index 083830382..517358f9d 100644 --- a/test-integration/test-committor-service/tests/test_intent_executor.rs +++ b/test-integration/test-committor-service/tests/test_intent_executor.rs @@ -10,9 +10,7 @@ use std::{ }; use borsh::to_vec; -use dlp_api::dlp::{ - args::CommitStateArgs, pda::ephemeral_balance_pda_from_payer, -}; +use dlp_api::{args::CommitStateArgs, pda::ephemeral_balance_pda_from_payer}; use futures::future::join_all; use magicblock_committor_program::pdas; use magicblock_committor_service::{ @@ -173,7 +171,7 @@ async fn test_commit_id_error_parsing() { TransactionError::InstructionError( _, InstructionError::Custom( - 0xc, // dlp_api::dlp::DlpError::NonceOutOfOrder: commit id/nonce is out of order + 0xc, // dlp_api::DlpError::NonceOutOfOrder: commit id/nonce is out of order ) ), _ diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 474bf0aab..19677d02c 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -920,8 +920,11 @@ async fn ix_commit_local( .expect("Account should be persisted"); // When we finalize it is possible to also undelegate the account - let expected_owner = - if is_undelegate { program_id } else { dlp::id() }; + let expected_owner = if is_undelegate { + program_id + } else { + dlp_api::id() + }; let lamports = account.account.lamports; get_account!( diff --git a/test-integration/test-ledger-restore/Cargo.toml b/test-integration/test-ledger-restore/Cargo.toml index 610c160f1..fbf3d674f 100644 --- a/test-integration/test-ledger-restore/Cargo.toml +++ b/test-integration/test-ledger-restore/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } anyhow = { workspace = true } cleanass = { workspace = true } integration-test-tools = { workspace = true } diff --git a/test-integration/test-ledger-restore/src/lib.rs b/test-integration/test-ledger-restore/src/lib.rs index b8df998fd..df18ce0ef 100644 --- a/test-integration/test-ledger-restore/src/lib.rs +++ b/test-integration/test-ledger-restore/src/lib.rs @@ -198,7 +198,7 @@ pub fn init_validator_fees_vault( chain_ctx: &IntegrationTestContext, validator_identity: &Keypair, ) { - let vault_pda = dlp_api::dlp::pda::validator_fees_vault_pda_from_validator( + let vault_pda = dlp_api::pda::validator_fees_vault_pda_from_validator( &validator_identity.pubkey(), ); if chain_ctx.fetch_chain_account(vault_pda).is_ok() { @@ -268,11 +268,11 @@ pub fn init_and_delegate_counter_and_payer( cleanup(validator) ); let owner = fetch_counter_owner_chain(&payer.pubkey(), validator); - assert_eq!(owner, dlp_api::dlp::id(), cleanup(validator)); + assert_eq!(owner, dlp_api::id(), cleanup(validator)); let payer_chain = expect!(ctx.fetch_chain_account(payer.pubkey()), validator); - assert_eq!(payer_chain.owner, dlp_api::dlp::id(), cleanup(validator)); + assert_eq!(payer_chain.owner, dlp_api::id(), cleanup(validator)); assert!(payer_chain.lamports > LAMPORTS_PER_SOL, cleanup(validator)); debug!( diff --git a/test-integration/test-ledger-restore/tests/07_commit_delegated_account.rs b/test-integration/test-ledger-restore/tests/07_commit_delegated_account.rs index 61f15029d..ba63e09bc 100644 --- a/test-integration/test-ledger-restore/tests/07_commit_delegated_account.rs +++ b/test-integration/test-ledger-restore/tests/07_commit_delegated_account.rs @@ -97,10 +97,9 @@ fn write(ledger_path: &Path) -> (Child, u64, Keypair) { let validator_identity = expect!(ctx.ephem_validator_identity.ok_or(()), validator); - let megic_fee_vault = - dlp_api::dlp::pda::magic_fee_vault_pda_from_validator( - &validator_identity, - ); + let megic_fee_vault = dlp_api::pda::magic_fee_vault_pda_from_validator( + &validator_identity, + ); let ix = create_add_and_schedule_commit_ix( payer.pubkey(), 4, diff --git a/test-integration/test-magicblock-api/Cargo.toml b/test-integration/test-magicblock-api/Cargo.toml index cebe7315d..e652e065a 100644 --- a/test-integration/test-magicblock-api/Cargo.toml +++ b/test-integration/test-magicblock-api/Cargo.toml @@ -10,7 +10,7 @@ tracing = { workspace = true } cleanass = { workspace = true } magicblock-api = { workspace = true } magicblock-config = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-program = { path = "../../programs/magicblock" } magicblock-validator-admin = { path = "../../magicblock-validator-admin" } magic-domain-program = { workspace = true } diff --git a/test-integration/test-magicblock-api/tests/test_claim_fees.rs b/test-integration/test-magicblock-api/tests/test_claim_fees.rs index c3a05fea4..b48b104b7 100644 --- a/test-integration/test-magicblock-api/tests/test_claim_fees.rs +++ b/test-integration/test-magicblock-api/tests/test_claim_fees.rs @@ -52,7 +52,7 @@ fn test_claim_fees_instruction() { ); assert_eq!( instruction.program_id, - dlp_api::dlp::id(), + dlp_api::id(), "Instruction should target delegation program" ); diff --git a/test-integration/test-schedule-intent/Cargo.toml b/test-integration/test-schedule-intent/Cargo.toml index 4d908d8f1..178ade1c7 100644 --- a/test-integration/test-schedule-intent/Cargo.toml +++ b/test-integration/test-schedule-intent/Cargo.toml @@ -8,7 +8,7 @@ edition.workspace = true [dev-dependencies] tracing = { workspace = true } integration-test-tools = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-sdk = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs index 3a6b53a26..674d7b9e4 100644 --- a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs +++ b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs @@ -1,4 +1,4 @@ -use dlp_api::dlp::pda::ephemeral_balance_pda_from_payer; +use dlp_api::pda::ephemeral_balance_pda_from_payer; use integration_test_tools::IntegrationTestContext; use program_flexi_counter::{ delegation_program_id, diff --git a/test-integration/test-tools/Cargo.toml b/test-integration/test-tools/Cargo.toml index 7feadcd9f..060e8111e 100644 --- a/test-integration/test-tools/Cargo.toml +++ b/test-integration/test-tools/Cargo.toml @@ -15,7 +15,7 @@ ureq = { workspace = true } url = { workspace = true } magicblock-core = { workspace = true } magicblock-config = { workspace = true } -dlp-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-tools/src/dlp_interface.rs b/test-integration/test-tools/src/dlp_interface.rs index cc7a61077..b5df8a490 100644 --- a/test-integration/test-tools/src/dlp_interface.rs +++ b/test-integration/test-tools/src/dlp_interface.rs @@ -1,5 +1,5 @@ use anyhow::Context; -use dlp_api::dlp::args::{DelegateArgs, DelegateEphemeralBalanceArgs}; +use dlp_api::args::{DelegateArgs, DelegateEphemeralBalanceArgs}; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; use solana_rpc_client_api::config::RpcSendTransactionConfig; @@ -50,7 +50,7 @@ pub fn create_delegate_ixs( validator: Option, ) -> Vec { let change_owner_ix = - system_instruction::assign(&delegatee, &dlp_api::dlp::id()); + system_instruction::assign(&delegatee, &dlp_api::id()); let delegate_ix = dlp_api::instruction_builder::delegate( payer, delegatee, @@ -70,7 +70,7 @@ pub fn create_delegate_to_any_ixs( validator: Option, ) -> Vec { let change_owner_ix = - system_instruction::assign(&delegatee, &dlp_api::dlp::id()); + system_instruction::assign(&delegatee, &dlp_api::id()); let delegate_ix = dlp_api::instruction_builder::delegate_with_any_validator( payer, delegatee, @@ -115,11 +115,11 @@ pub fn escrow_pdas(payer: &Pubkey) -> (Pubkey, Pubkey) { } pub fn delegation_record_pubkey(pubkey: &Pubkey) -> Pubkey { - dlp_api::dlp::pda::delegation_record_pda_from_delegated_account(pubkey) + dlp_api::pda::delegation_record_pda_from_delegated_account(pubkey) } pub fn ephemeral_balance_pda_from_payer_pubkey(payer: &Pubkey) -> Pubkey { - dlp_api::dlp::pda::ephemeral_balance_pda_from_payer(payer, 0) + dlp_api::pda::ephemeral_balance_pda_from_payer(payer, 0) } // ----------------- diff --git a/test-integration/test-tools/src/integration_test_context.rs b/test-integration/test-tools/src/integration_test_context.rs index c1cd7b723..67765b7f3 100644 --- a/test-integration/test-tools/src/integration_test_context.rs +++ b/test-integration/test-tools/src/integration_test_context.rs @@ -578,7 +578,7 @@ impl IntegrationTestContext { // 2.Delegate the ephem payer let delegated_already = self .fetch_chain_account_owner(payer_ephem.pubkey()) - .map(|owner| owner.eq(&dlp_api::dlp::id())) + .map(|owner| owner.eq(&dlp_api::id())) .unwrap_or(false); let deleg_sig = if !delegated_already { let (deleg_sig, confirmed) = diff --git a/test-integration/test-tools/src/loaded_accounts.rs b/test-integration/test-tools/src/loaded_accounts.rs index 1e1008cbf..7a2d86c28 100644 --- a/test-integration/test-tools/src/loaded_accounts.rs +++ b/test-integration/test-tools/src/loaded_accounts.rs @@ -85,17 +85,17 @@ impl LoadedAccounts { } pub fn validator_fees_vault(&self) -> Pubkey { - dlp_api::dlp::pda::validator_fees_vault_pda_from_validator( + dlp_api::pda::validator_fees_vault_pda_from_validator( &self.validator_authority(), ) } pub fn protocol_fees_vault(&self) -> Pubkey { - dlp_api::dlp::pda::fees_vault_pda() + dlp_api::pda::fees_vault_pda() } pub fn magic_fee_vault(&self) -> Pubkey { - dlp_api::dlp::pda::magic_fee_vault_pda_from_validator( + dlp_api::pda::magic_fee_vault_pda_from_validator( &self.validator_authority(), ) } From a55654689f005072778e1aecef0310d0e20ad2fe Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Mon, 23 Mar 2026 15:43:56 +0530 Subject: [PATCH 05/10] address Edwin's feedbacks --- .../src/tasks/task_builder.rs | 2 +- magicblock-committor-service/src/types.rs | 42 --------------- .../src/magic_scheduled_base_intent.rs | 5 +- .../process_schedule_commit_finalize.rs | 54 ++++++++++++++++--- 4 files changed, 50 insertions(+), 53 deletions(-) delete mode 100644 magicblock-committor-service/src/types.rs diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 36a6da3d6..bfb7dd546 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -159,7 +159,7 @@ impl TaskBuilderImpl { #[async_trait] impl TasksBuilder for TaskBuilderImpl { - /// Returns []s for Commit stage + /// Returns [`BaseTaskImpl`]s for Commit stage async fn commit_tasks( task_info_fetcher: &Arc, intent_bundle: &ScheduledIntentBundle, diff --git a/magicblock-committor-service/src/types.rs b/magicblock-committor-service/src/types.rs deleted file mode 100644 index 4a72a2242..000000000 --- a/magicblock-committor-service/src/types.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::ops::Deref; - -use magicblock_metrics::metrics; -use magicblock_program::magic_scheduled_base_intent::{ - MagicBaseIntent, ScheduledBaseIntent, -}; - -// TODO: should be removed once cranks are supported -// Ideally even now OffChain/"Manual" commits should be triggered via Tx -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum TriggerType { - OnChain, - OffChain, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ScheduledBaseIntentWrapper { - pub inner: ScheduledBaseIntent, - pub trigger_type: TriggerType, -} - -impl metrics::LabelValue for ScheduledBaseIntentWrapper { - fn value(&self) -> &str { - match &self.inner.base_intent { - MagicBaseIntent::BaseActions(_) => "actions", - MagicBaseIntent::Commit(_) => "commit", - MagicBaseIntent::CommitAndUndelegate(_) => "commit_and_undelegate", - MagicBaseIntent::CommitFinalize(_) => "commit_finalize", - MagicBaseIntent::CommitFinalizeAndUndelegate(_) => { - "commit_finalize_and_undelegate" - } - } - } -} - -impl Deref for ScheduledBaseIntentWrapper { - type Target = ScheduledBaseIntent; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 677261492..546f44780 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -380,10 +380,7 @@ impl MagicIntentBundle { pub fn has_undelegate_intent(&self) -> bool { self.commit_and_undelegate.is_some() - - // TODO (snawaz): we need to add this as well? - // || - // self.commit_finalize_and_undelegate.is_some() + || self.commit_finalize_and_undelegate.is_some() } pub fn has_committed_accounts(&self) -> bool { diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs index 1832b3693..ab8cc6a08 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -10,16 +10,22 @@ use solana_pubkey::Pubkey; use crate::{ magic_scheduled_base_intent::{ - validate_commit_schedule_permissions, CommitAndUndelegate, CommitType, - MagicBaseIntent, ScheduledIntentBundle, UndelegateType, + calculate_commit_fee, validate_commit_schedule_permissions, + CommitAndUndelegate, CommitType, MagicBaseIntent, + ScheduledIntentBundle, UndelegateType, + }, + magic_sys::fetch_current_commit_nonces, + schedule_transactions::{ + self, check_commit_limits, try_get_fee_vault, + ProcessScheduleCommitOptions, }, - schedule_transactions::{self, ProcessScheduleCommitOptions}, utils::{ account_actions::mark_account_as_undelegated, accounts::{ get_instruction_account_with_idx, get_instruction_pubkey_with_idx, get_writable_with_idx, }, + charge_delegated_payer, instruction_utils::InstructionUtils, }, MagicContext, @@ -54,8 +60,34 @@ pub(crate) fn process_schedule_commit_finalize( InstructionError::UnsupportedProgramId })?; + // Assert Payer is signer + let payer_pubkey = + get_instruction_pubkey_with_idx(transaction_context, PAYER_IDX)?; + if !signers.contains(payer_pubkey) { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: payer pubkey {} not in signers", + payer_pubkey + ); + return Err(InstructionError::MissingRequiredSignature); + } + + let payer_account = + get_instruction_account_with_idx(transaction_context, PAYER_IDX)?; + let magic_fee_vault = try_get_fee_vault( + transaction_context, + invoke_context, + PAYER_IDX, + MAGIC_CONTEXT_IDX + 1, + )?; + let committees_start = if magic_fee_vault.is_some() { + COMMITTEES_START + 1 + } else { + COMMITTEES_START + }; + // Assert enough accounts - if ix_accs_len <= COMMITTEES_START { + if ix_accs_len <= committees_start { ic_msg!( invoke_context, "ScheduleCommit ERR: not enough accounts to schedule commit ({}), need payer, signing program an account for each pubkey to be committed", @@ -91,7 +123,7 @@ pub(crate) fn process_schedule_commit_finalize( let first_committee_owner = { *get_instruction_account_with_idx( transaction_context, - COMMITTEES_START as u16, + committees_start as u16, )? .borrow() .owner() @@ -121,7 +153,7 @@ pub(crate) fn process_schedule_commit_finalize( // program owning the PDAs invoked us directly via CPI is sufficient // Thus we can be `invoke`d unsigned and no seeds need to be provided let mut committed_accounts: Vec = Vec::new(); - for idx in COMMITTEES_START..ix_accs_len { + for idx in committees_start..ix_accs_len { let acc_pubkey = get_instruction_pubkey_with_idx(transaction_context, idx as u16)?; let acc = @@ -211,6 +243,16 @@ pub(crate) fn process_schedule_commit_finalize( } } + if let Some(fee_vault) = magic_fee_vault { + let nonces = fetch_current_commit_nonces(&committed_accounts)?; + let fee = calculate_commit_fee(&committed_accounts, &nonces)?; + charge_delegated_payer(payer_account, fee_vault, fee)?; + } else if !opts.request_undelegation { + // We validate commit nonces only for plain commits. + // If accounts are undelegated we don't want to fail. + check_commit_limits(&committed_accounts, invoke_context)?; + } + // NOTE: this is only protected by all the above checks however if the // instruction fails for other reasons detected afterward then the commit // stays scheduled From 1099cd98a255fd614d598f434465bf99bbabd4ba Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 24 Mar 2026 13:20:31 +0530 Subject: [PATCH 06/10] add tests, following Edwin's feedbacks --- .../programs/schedulecommit/Cargo.toml | 2 +- .../tests/test_ix_commit_local.rs | 35 ++++++++++++++++++- test-integration/test-tools/Cargo.toml | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/test-integration/programs/schedulecommit/Cargo.toml b/test-integration/programs/schedulecommit/Cargo.toml index 26b1a47fc..55ad20846 100644 --- a/test-integration/programs/schedulecommit/Cargo.toml +++ b/test-integration/programs/schedulecommit/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true borsh = { workspace = true } ephemeral-rollups-sdk = { workspace = true } solana-program = { workspace = true } -magicblock-delegation-program-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true, features = ["instruction"] } magicblock_magic_program_api = { workspace = true } rkyv = { workspace = true } static_assertions = { workspace = true } diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 19677d02c..75a7aacd2 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -585,6 +585,7 @@ async fn test_ix_execute_intent_bundle_commit_and_cau_simultaneously_union_of_ac ) { execute_intent_bundle( &[1024, 2048], + &[], &[1024, 2048], expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), ) @@ -595,6 +596,7 @@ async fn test_ix_execute_intent_bundle_commit_and_cau_simultaneously_union_of_ac async fn test_ix_execute_intent_bundle_commit_three_accounts_cau_one_account() { execute_intent_bundle( &[512, 512, 512], + &[], &[512], expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), ) @@ -605,12 +607,35 @@ async fn test_ix_execute_intent_bundle_commit_three_accounts_cau_one_account() { async fn test_ix_execute_intent_bundle_mixed_fits_in_args() { execute_intent_bundle( &[10, 20, 10], + &[], &[20], expect_strategies(&[(CommitStrategy::StateArgs, 4)]), ) .await; } +#[tokio::test] +async fn test_ix_execute_intent_bundle_commit_finalize_only() { + execute_intent_bundle( + &[], + &[10, 20], + &[], + expect_strategies(&[(CommitStrategy::StateArgs, 2)]), + ) + .await; +} + +#[tokio::test] +async fn test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed() { + execute_intent_bundle( + &[1024, 2048], + &[1024, 2048], + &[], + expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), + ) + .await; +} + async fn commit_5_accounts_1kb( bundle_size: usize, expected_strategies: ExpectedStrategies, @@ -743,6 +768,7 @@ async fn commit_multiple_accounts( async fn execute_intent_bundle( bytess_to_commit: &[usize], + bytess_to_commit_finalize: &[usize], bytes_to_undelegate: &[usize], expected_strategies: ExpectedStrategies, ) { @@ -761,13 +787,20 @@ async fn execute_intent_bundle( // Create bundles of committed accounts let to_commit = create_and_delegate_accounts(bytess_to_commit); + let to_commit_finalize = + create_and_delegate_accounts(bytess_to_commit_finalize); let to_undelegate = create_and_delegate_accounts(bytes_to_undelegate); - let (committees, undelegetees) = tokio::join!(to_commit, to_undelegate); + let (committees, commit_finalize_committees, undelegetees) = + tokio::join!(to_commit, to_commit_finalize, to_undelegate); let mut intent_bundle = MagicIntentBundle::default(); if !committees.is_empty() { intent_bundle.commit = Some(CommitType::Standalone(committees)); } + if !commit_finalize_committees.is_empty() { + intent_bundle.commit_finalize = + Some(CommitType::Standalone(commit_finalize_committees)); + } if !undelegetees.is_empty() { intent_bundle.commit_and_undelegate = Some(CommitAndUndelegate { commit_action: CommitType::Standalone(undelegetees), diff --git a/test-integration/test-tools/Cargo.toml b/test-integration/test-tools/Cargo.toml index 060e8111e..8071b41e4 100644 --- a/test-integration/test-tools/Cargo.toml +++ b/test-integration/test-tools/Cargo.toml @@ -15,7 +15,7 @@ ureq = { workspace = true } url = { workspace = true } magicblock-core = { workspace = true } magicblock-config = { workspace = true } -magicblock-delegation-program-api = { workspace = true } +magicblock-delegation-program-api = { workspace = true, features = ["instruction"] } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } From 5a33d5ba68d8e36afeb212a8eba6896ddc4395db Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 24 Mar 2026 15:06:16 +0530 Subject: [PATCH 07/10] add one test in test-schedule-intent --- test-integration/Cargo.lock | 2 + .../test-schedule-intent/Cargo.toml | 2 + .../tests/test_schedule_intents.rs | 125 +++++++++++++++++- 3 files changed, 127 insertions(+), 2 deletions(-) diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 1e4726d63..26fa5d3da 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -10480,8 +10480,10 @@ dependencies = [ name = "test-schedule-intent" version = "0.0.0" dependencies = [ + "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-delegation-program-api 0.1.1", + "magicblock-magic-program-api 0.8.4", "program-flexi-counter", "solana-rpc-client-api", "solana-sdk", diff --git a/test-integration/test-schedule-intent/Cargo.toml b/test-integration/test-schedule-intent/Cargo.toml index 178ade1c7..6faed2846 100644 --- a/test-integration/test-schedule-intent/Cargo.toml +++ b/test-integration/test-schedule-intent/Cargo.toml @@ -7,8 +7,10 @@ edition.workspace = true [dev-dependencies] tracing = { workspace = true } +ephemeral-rollups-sdk = { workspace = true } integration-test-tools = { workspace = true } magicblock-delegation-program-api = { workspace = true } +magicblock_magic_program_api = { workspace = true } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-sdk = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs index 674d7b9e4..657e6dc3f 100644 --- a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs +++ b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs @@ -1,5 +1,10 @@ use dlp_api::pda::ephemeral_balance_pda_from_payer; +use ephemeral_rollups_sdk::consts::{MAGIC_CONTEXT_ID, MAGIC_PROGRAM_ID}; use integration_test_tools::IntegrationTestContext; +use magicblock_magic_program_api::{ + args::{CommitTypeArgs, MagicIntentBundleArgs}, + instruction::MagicBlockInstruction, +}; use program_flexi_counter::{ delegation_program_id, instruction::{ @@ -9,8 +14,13 @@ use program_flexi_counter::{ state::FlexiCounter, }; use solana_sdk::{ - native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, rent::Rent, - signature::Keypair, signer::Signer, transaction::Transaction, + instruction::{AccountMeta, Instruction}, + native_token::LAMPORTS_PER_SOL, + pubkey::Pubkey, + rent::Rent, + signature::Keypair, + signer::Signer, + transaction::Transaction, }; use test_kit::init_logger; use tracing::*; @@ -507,6 +517,57 @@ fn test_intent_bundle_undelegate_only() { ); } +#[test] +fn test_intent_bundle_commit_and_commit_finalize() { + init_logger!(); + + let ctx = IntegrationTestContext::try_new().unwrap(); + + let commit_payer = setup_payer(&ctx); + let commit_finalize_payer = setup_payer(&ctx); + + init_counter(&ctx, &commit_payer); + delegate_counter(&ctx, &commit_payer); + add_to_counter(&ctx, &commit_payer, 31); + + init_counter(&ctx, &commit_finalize_payer); + delegate_counter(&ctx, &commit_finalize_payer); + add_to_counter(&ctx, &commit_finalize_payer, 47); + + schedule_intent_bundle_commit_and_finalize( + &ctx, + &commit_payer, + vec![FlexiCounter::pda(&commit_payer.pubkey()).0], + vec![FlexiCounter::pda(&commit_finalize_payer.pubkey()).0], + ); + + assert_counters( + &ctx, + &[ + ExpectedCounter { + pda: FlexiCounter::pda(&commit_payer.pubkey()).0, + expected: 31, + }, + ExpectedCounter { + pda: FlexiCounter::pda(&commit_finalize_payer.pubkey()).0, + expected: 47, + }, + ], + true, + ); + + let owner_commit = ctx + .fetch_chain_account_owner(FlexiCounter::pda(&commit_payer.pubkey()).0) + .unwrap(); + let owner_finalize = ctx + .fetch_chain_account_owner( + FlexiCounter::pda(&commit_finalize_payer.pubkey()).0, + ) + .unwrap(); + assert_eq!(owner_commit, delegation_program_id()); + assert_eq!(owner_finalize, delegation_program_id()); +} + fn setup_payer(ctx: &IntegrationTestContext) -> Keypair { // Airdrop to payer on chain let payer = Keypair::new(); @@ -736,6 +797,66 @@ fn schedule_intent_bundle( assert_eq!(transfer_destination_balance, expected_balance); } +fn schedule_intent_bundle_commit_and_finalize( + ctx: &IntegrationTestContext, + payer: &Keypair, + commit_accounts: Vec, + commit_finalize_accounts: Vec, +) { + ctx.wait_for_next_slot_ephem().unwrap(); + + let mut all_accounts = Vec::new(); + all_accounts.extend(commit_accounts.iter().copied()); + all_accounts.extend(commit_finalize_accounts.iter().copied()); + all_accounts.sort(); + all_accounts.dedup(); + + let mut metas = vec![ + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new(MAGIC_CONTEXT_ID, false), + ]; + metas.extend( + all_accounts + .iter() + .map(|pubkey| AccountMeta::new(*pubkey, false)), + ); + + let account_index = |pubkey: &Pubkey| -> u8 { + (2 + all_accounts.iter().position(|k| k == pubkey).unwrap()) as u8 + }; + + let args = MagicIntentBundleArgs { + commit: Some(CommitTypeArgs::Standalone( + commit_accounts.iter().map(account_index).collect(), + )), + commit_and_undelegate: None, + commit_finalize: Some(CommitTypeArgs::Standalone( + commit_finalize_accounts.iter().map(account_index).collect(), + )), + commit_finalize_and_undelegate: None, + standalone_actions: vec![], + }; + + let ix = Instruction::new_with_bincode( + MAGIC_PROGRAM_ID, + &MagicBlockInstruction::ScheduleIntentBundle(args), + metas, + ); + + let mut tx = Transaction::new_with_payer(&[ix], Some(&payer.pubkey())); + let (sig, confirmed) = ctx + .send_and_confirm_transaction_ephem(&mut tx, &[payer]) + .unwrap(); + assert!(confirmed); + + let commit_result = ctx + .fetch_schedule_commit_result::(sig) + .unwrap(); + commit_result + .confirm_commit_transactions_on_chain(ctx) + .unwrap(); +} + fn verify_undelegation_in_ephem_via_owner( pubkeys: &[Pubkey], ctx: &IntegrationTestContext, From 21744b47f49b56d39c2f9752b1a6a7ff2a3f368e Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 24 Mar 2026 20:23:30 +0530 Subject: [PATCH 08/10] fixing tests --- Cargo.lock | 5 +- Cargo.toml | 2 +- .../src/tasks/commit_finalize_task.rs | 10 +- .../src/tasks/commit_task.rs | 11 +- magicblock-committor-service/src/tasks/mod.rs | 12 +- .../src/tasks/task_strategist.rs | 34 +++-- .../delivery_preparator.rs | 20 ++- .../src/transaction_preparator/mod.rs | 3 + test-integration/Cargo.lock | 5 +- test-integration/Cargo.toml | 2 +- .../programs/flexi-counter/src/instruction.rs | 45 +++++++ .../programs/flexi-counter/src/processor.rs | 9 ++ .../src/processor/schedule_intent.rs | 99 +++++++++++++++ test-integration/schedulecommit/elfs/dlp.so | Bin 451128 -> 453720 bytes .../tests/test_ix_commit_local.rs | 34 ++++- test-integration/test-runner/bin/run_tests.rs | 45 +++++-- .../tests/test_schedule_intents.rs | 117 ++++++++++-------- 17 files changed, 347 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50d665a0c..e1ae5464d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3437,8 +3437,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a413fd0a3ce67bba8c31b681f37088a897d47a3c39fd0d9303725882898ad78" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=09e0102df4ff69dfe9795cdf3b642943a3bbdf59#09e0102df4ff69dfe9795cdf3b642943a3bbdf59" dependencies = [ "bincode", "borsh 1.6.0", @@ -3459,7 +3458,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 2.0.18", + "thiserror 1.0.69", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7a1b20f9d..edad27dbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { version = "0.1.1" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "09e0102df4ff69dfe9795cdf3b642943a3bbdf59" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-committor-service/src/tasks/commit_finalize_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_task.rs index df1f84267..b2fc99628 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_task.rs @@ -146,15 +146,13 @@ impl CommitFinalizeTask { self.preparation_stage(diff) } - fn preparation_stage(&self, committed_data: Vec) -> CommitBufferStage { - let chunks = Chunks::from_data_length( - committed_data.len(), - MAX_WRITE_CHUNK_SIZE, - ); + fn preparation_stage(&self, buffer_data: Vec) -> CommitBufferStage { + let chunks = + Chunks::from_data_length(buffer_data.len(), MAX_WRITE_CHUNK_SIZE); CommitBufferStage::Preparation(PreparationTask { commit_id: self.commit_id, pubkey: self.committed_account.pubkey, - committed_data, + buffer_data, chunks, }) } diff --git a/magicblock-committor-service/src/tasks/commit_task.rs b/magicblock-committor-service/src/tasks/commit_task.rs index e40ea7441..760823263 100644 --- a/magicblock-committor-service/src/tasks/commit_task.rs +++ b/magicblock-committor-service/src/tasks/commit_task.rs @@ -109,6 +109,7 @@ impl CommitTask { .to_vec(), allow_undelegation: self.allow_undelegation, }; + dlp_api::instruction_builder::commit_diff( *validator, self.committed_account.pubkey, @@ -184,15 +185,13 @@ impl CommitTask { self.preparation_stage(diff) } - fn preparation_stage(&self, committed_data: Vec) -> CommitBufferStage { - let chunks = Chunks::from_data_length( - committed_data.len(), - MAX_WRITE_CHUNK_SIZE, - ); + fn preparation_stage(&self, buffer_data: Vec) -> CommitBufferStage { + let chunks = + Chunks::from_data_length(buffer_data.len(), MAX_WRITE_CHUNK_SIZE); CommitBufferStage::Preparation(PreparationTask { commit_id: self.commit_id, pubkey: self.committed_account.pubkey, - committed_data, + buffer_data, chunks, }) } diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 1be2dd82b..752e3bc02 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -69,6 +69,7 @@ impl BaseTask for BaseTaskImpl { fn try_optimize_tx_size(&mut self) -> bool { match self { Self::Commit(value) => value.try_optimize_tx_size(), + Self::CommitFinalize(value) => value.try_optimize_tx_size(), _ => false, } } @@ -106,6 +107,9 @@ impl BaseTaskImpl { pub fn strategy(&self) -> TaskStrategy { match self { Self::Commit(task) if task.is_buffer() => TaskStrategy::Buffer, + Self::CommitFinalize(task) if task.is_buffer() => { + TaskStrategy::Buffer + } _ => TaskStrategy::Args, } } @@ -373,7 +377,7 @@ pub struct PreparationTask { pub chunks: Chunks, // TODO(edwin): replace with reference once done - pub committed_data: Vec, + pub buffer_data: Vec, } impl PreparationTask { @@ -386,7 +390,7 @@ impl PreparationTask { // // https://github.com/near/borsh-rs/blob/f1b75a6b50740bfb6231b7d0b1bd93ea58ca5452/borsh/src/ser/helpers.rs#L59 let chunks_account_size = borsh::object_length(&self.chunks).unwrap() as u64; - let buffer_account_size = self.committed_data.len() as u64; + let buffer_account_size = self.buffer_data.len() as u64; let (instruction, _, _) = create_init_ix(CreateInitIxArgs { authority: *authority, @@ -409,7 +413,7 @@ impl PreparationTask { /// Returns realloc instruction required for Buffer preparation #[allow(clippy::let_and_return)] pub fn realloc_instructions(&self, authority: &Pubkey) -> Vec { - let buffer_account_size = self.committed_data.len() as u64; + let buffer_account_size = self.buffer_data.len() as u64; let realloc_instructions = create_realloc_buffer_ixs(CreateReallocBufferIxArgs { authority: *authority, @@ -431,7 +435,7 @@ impl PreparationTask { pub fn write_instructions(&self, authority: &Pubkey) -> Vec { let chunks_iter = ChangesetChunks::new(&self.chunks, self.chunks.chunk_size()) - .iter(&self.committed_data); + .iter(&self.buffer_data); let write_instructions = chunks_iter .map(|chunk| { create_write_ix(CreateWriteIxArgs { diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index d625c106c..cf9d7443b 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -265,11 +265,8 @@ impl TaskStrategist { tasks: &[BaseTaskImpl], uses_lookup_tables: bool, ) { - for task in tasks { - let BaseTaskImpl::Commit(commit_task) = task else { - continue; - }; - let commit_strategy = match &commit_task.delivery_details { + let commit_strategy_from_delivery = + |delivery: &CommitDelivery| match delivery { CommitDelivery::StateInArgs => { if uses_lookup_tables { CommitStrategy::StateArgsWithLookupTable @@ -299,14 +296,33 @@ impl TaskStrategist { } } }; + + for task in tasks { + let (commit_id, pubkey, commit_strategy) = match task { + BaseTaskImpl::Commit(commit_task) => ( + commit_task.commit_id, + commit_task.committed_account.pubkey, + commit_strategy_from_delivery( + &commit_task.delivery_details, + ), + ), + BaseTaskImpl::CommitFinalize(commit_finalize_task) => ( + commit_finalize_task.commit_id, + commit_finalize_task.committed_account.pubkey, + commit_strategy_from_delivery( + &commit_finalize_task.delivery, + ), + ), + _ => continue, + }; if let Err(err) = persistor.set_commit_strategy( - commit_task.commit_id, - &commit_task.committed_account.pubkey, + commit_id, + &pubkey, commit_strategy, ) { error!( - commit_id = %commit_task.commit_id, - pubkey = %commit_task.committed_account.pubkey, + commit_id = %commit_id, + pubkey = %pubkey, strategy = commit_strategy.as_str(), error = ?err, "Failed to persist commit strategy" diff --git a/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs b/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs index a7f9f9990..6add62858 100644 --- a/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs +++ b/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs @@ -98,10 +98,14 @@ impl DeliveryPreparator { task: &mut BaseTaskImpl, persister: &Option

, ) -> DeliveryPreparatorResult<(), InternalError> { - let BaseTaskImpl::Commit(commit_task) = task else { - return Ok(()); + let stage = match task { + BaseTaskImpl::Commit(commit_task) => commit_task.stage_mut(), + BaseTaskImpl::CommitFinalize(commit_finalize_task) => { + commit_finalize_task.stage_mut() + } + _ => None, }; - let Some(stage) = commit_task.stage_mut() else { + let Some(stage) = stage else { return Ok(()); }; let CommitBufferStage::Preparation(preparation_task) = stage else { @@ -170,10 +174,14 @@ impl DeliveryPreparator { } // Prepare cleanup task - set stage to Cleanup before calling cleanup - let BaseTaskImpl::Commit(commit_task) = task else { - return Ok(()); + let stage = match task { + BaseTaskImpl::Commit(commit_task) => commit_task.stage_mut(), + BaseTaskImpl::CommitFinalize(commit_finalize_task) => { + commit_finalize_task.stage_mut() + } + _ => None, }; - let Some(stage) = commit_task.stage_mut() else { + let Some(stage) = stage else { return Ok(()); }; let CommitBufferStage::Preparation(preparation_task) = stage else { diff --git a/magicblock-committor-service/src/transaction_preparator/mod.rs b/magicblock-committor-service/src/transaction_preparator/mod.rs index 07760606a..c351393e2 100644 --- a/magicblock-committor-service/src/transaction_preparator/mod.rs +++ b/magicblock-committor-service/src/transaction_preparator/mod.rs @@ -120,6 +120,9 @@ impl TransactionPreparator for TransactionPreparatorImpl { .iter() .filter_map(|task| match task { BaseTaskImpl::Commit(commit_task) => commit_task.stage(), + BaseTaskImpl::CommitFinalize(commit_finalize_task) => { + commit_finalize_task.stage() + } _ => None, }) .filter_map(|stage| match stage { diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 26fa5d3da..4a2c82ca7 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3798,8 +3798,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a413fd0a3ce67bba8c31b681f37088a897d47a3c39fd0d9303725882898ad78" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=09e0102df4ff69dfe9795cdf3b642943a3bbdf59#09e0102df4ff69dfe9795cdf3b642943a3bbdf59" dependencies = [ "bincode", "borsh 1.6.0", @@ -3820,7 +3819,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 2.0.18", + "thiserror 1.0.69", ] [[package]] diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index e860fe05a..05e77ecb7 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -60,7 +60,7 @@ magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain- "modular-sdk", ] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -magicblock-delegation-program-api = { version = "0.1.1", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "09e0102df4ff69dfe9795cdf3b642943a3bbdf59", default-features = false } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } magicblock-table-mania = { path = "../magicblock-table-mania" } diff --git a/test-integration/programs/flexi-counter/src/instruction.rs b/test-integration/programs/flexi-counter/src/instruction.rs index c7d00f162..4d800bb30 100644 --- a/test-integration/programs/flexi-counter/src/instruction.rs +++ b/test-integration/programs/flexi-counter/src/instruction.rs @@ -222,6 +222,19 @@ pub enum FlexiCounterInstruction { counter_diffs: Vec, compute_units: u32, }, + + /// Creates an intent bundle that contains Commit + CommitFinalize intents. + /// + /// Accounts: + /// 0. `[write]` MagicContext + /// 1. `[]` MagicBlock Program + /// 2. `[signer]` Payer (escrow authority) + /// 3. `[write]` Commit counters + /// .. `[write]` CommitFinalize counters + CreateIntentBundleCommitAndFinalize { + num_commit: u8, + num_commit_finalize: u8, + }, } pub fn create_init_ix(payer: Pubkey, label: String) -> Instruction { @@ -574,3 +587,35 @@ pub fn create_intent_bundle_ix( accounts, ) } + +pub fn create_intent_bundle_commit_and_finalize_ix( + payer: Pubkey, + commit_accounts: Vec, + commit_finalize_accounts: Vec, +) -> Instruction { + let program_id = &crate::id(); + let mut accounts = vec![ + AccountMeta::new(MAGIC_CONTEXT_ID, false), + AccountMeta::new_readonly(MAGIC_PROGRAM_ID, false), + AccountMeta::new_readonly(payer, true), + ]; + accounts.extend( + commit_accounts + .iter() + .map(|pubkey| AccountMeta::new(*pubkey, false)), + ); + accounts.extend( + commit_finalize_accounts + .iter() + .map(|pubkey| AccountMeta::new(*pubkey, false)), + ); + + Instruction::new_with_borsh( + *program_id, + &FlexiCounterInstruction::CreateIntentBundleCommitAndFinalize { + num_commit: commit_accounts.len() as u8, + num_commit_finalize: commit_finalize_accounts.len() as u8, + }, + accounts, + ) +} diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index 1fdc74557..9ffc2bc8c 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -37,6 +37,7 @@ use crate::{ }, schedule_intent::{ process_create_intent, process_create_intent_bundle, + process_create_intent_bundle_commit_and_finalize, }, }, state::{FlexiCounter, FAIL_UNDELEGATION_CODE, FAIL_UNDELEGATION_LABEL}, @@ -115,6 +116,14 @@ pub fn process( counter_diffs, compute_units, ), + CreateIntentBundleCommitAndFinalize { + num_commit, + num_commit_finalize, + } => process_create_intent_bundle_commit_and_finalize( + accounts, + num_commit, + num_commit_finalize, + ), }?; Ok(()) } diff --git a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs index 4e8b5d9b0..763884b1f 100644 --- a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs +++ b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs @@ -6,10 +6,16 @@ use ephemeral_rollups_sdk::{ }, ActionArgs, ShortAccountMeta, }; +use magicblock_magic_program_api::{ + args::{CommitTypeArgs, MagicIntentBundleArgs}, + instruction::MagicBlockInstruction, +}; use solana_program::{ account_info::{next_account_info, next_account_infos, AccountInfo}, entrypoint::ProgramResult, + instruction::{AccountMeta, Instruction}, msg, + program::invoke, program_error::ProgramError, }; @@ -322,3 +328,96 @@ pub fn process_create_intent_bundle( // Build and invoke the intent bundle builder.build_and_invoke() } + +pub fn process_create_intent_bundle_commit_and_finalize( + accounts: &[AccountInfo], + num_commit: u8, + num_commit_finalize: u8, +) -> ProgramResult { + let num_commit = num_commit as usize; + let num_commit_finalize = num_commit_finalize as usize; + + let expected_accounts = 3 + num_commit + num_commit_finalize; + if accounts.len() != expected_accounts { + msg!( + "Invalid number of accounts expected: {}, got: {}", + expected_accounts, + accounts.len() + ); + return Err(ProgramError::NotEnoughAccountKeys); + } + + let account_info_iter = &mut accounts.iter(); + let magic_context = next_account_info(account_info_iter)?; + let magic_program = next_account_info(account_info_iter)?; + let payer = next_account_info(account_info_iter)?; + let commit_accounts = next_account_infos(account_info_iter, num_commit)?; + let commit_finalize_accounts = + next_account_infos(account_info_iter, num_commit_finalize)?; + + let mut all_accounts = Vec::new(); + all_accounts.extend(commit_accounts.iter().cloned()); + all_accounts.extend(commit_finalize_accounts.iter().cloned()); + + let mut dedup_keys = Vec::new(); + for account in &all_accounts { + if !dedup_keys.iter().any(|key| key == account.key) { + dedup_keys.push(*account.key); + } + } + + let account_index = |pubkey: &solana_program::pubkey::Pubkey| -> u8 { + dedup_keys + .iter() + .position(|key| key == pubkey) + // ScheduleIntentBundle account indices are over instruction metas: + // [0]=payer, [1]=magic_context, [2..]=committed accounts... + .map(|index| (2 + index) as u8) + .unwrap() + }; + + let args = MagicIntentBundleArgs { + commit: Some(CommitTypeArgs::Standalone( + commit_accounts + .iter() + .map(|account| account_index(account.key)) + .collect(), + )), + commit_and_undelegate: None, + commit_finalize: Some(CommitTypeArgs::Standalone( + commit_finalize_accounts + .iter() + .map(|account| account_index(account.key)) + .collect(), + )), + commit_finalize_and_undelegate: None, + standalone_actions: vec![], + }; + + let mut metas = vec![ + AccountMeta::new(*payer.key, true), + AccountMeta::new(*magic_context.key, false), + ]; + metas.extend( + dedup_keys + .iter() + .map(|pubkey| AccountMeta::new(*pubkey, false)), + ); + + let mut cpi_accounts = + vec![magic_program.clone(), payer.clone(), magic_context.clone()]; + cpi_accounts.extend(dedup_keys.iter().filter_map(|pubkey| { + all_accounts + .iter() + .find(|account| account.key == pubkey) + .cloned() + })); + + let ix = Instruction::new_with_bincode( + *magic_program.key, + &MagicBlockInstruction::ScheduleIntentBundle(args), + metas, + ); + + invoke(&ix, &cpi_accounts) +} diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index caf607a72d135b520cc94d5c7b45f53cf97817d4..248510aaa65c31c46d6cd116e7b95278962204eb 100755 GIT binary patch delta 72196 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

E)~) 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
    K@cC~piWqSl3t-Q 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 HznT3%9f0ik diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 75a7aacd2..432c65ca3 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -7,7 +7,7 @@ use std::{ use borsh::to_vec; use magicblock_committor_service::{ config::ChainConfig, - intent_executor::ExecutionOutput, + intent_executor::{error::IntentExecutorError, ExecutionOutput}, persist::CommitStrategy, service_ext::{BaseIntentCommittorExt, CommittorServiceExt}, BaseIntentCommittor, CommittorService, ComputeBudgetConfig, @@ -30,7 +30,7 @@ use solana_sdk::{ use test_kit::init_logger; use tokio::task::JoinSet; use tracing::*; -use utils::transactions::tx_logs_contain; +use utils::transactions::{print_tx_logs, tx_logs_contain}; use self::utils::transactions::init_and_delegate_order_book_on_chain; use crate::utils::{ @@ -631,7 +631,7 @@ async fn test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed() { &[1024, 2048], &[1024, 2048], &[], - expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), + expect_strategies(&[(CommitStrategy::DiffArgs, 4)]), ) .await; } @@ -876,7 +876,33 @@ async fn ix_commit_local( .into_iter() .zip(intent_bundles.into_iter()) { - let output = execution_result.inner.unwrap(); + let output = match execution_result.inner { + Ok(output) => output, + Err(err) => { + match &*err { + IntentExecutorError::FailedToFinalizeError { + commit_signature, + finalize_signature, + .. + } => { + if let Some(commit_sig) = commit_signature { + print_tx_logs(&rpc_client, commit_sig).await; + } + if let Some(finalize_sig) = finalize_signature { + print_tx_logs(&rpc_client, finalize_sig).await; + } + } + IntentExecutorError::FailedToCommitError { + signature: Some(signature), + .. + } => { + print_tx_logs(&rpc_client, signature).await; + } + _ => {} + } + panic!("Intent execution failed: {err:?}"); + } + }; let (commit_signature, finalize_signature) = match output { ExecutionOutput::SingleStage(signature) => (signature, signature), ExecutionOutput::TwoStage { diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 9a095cac8..63e4b97be 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -282,7 +282,18 @@ fn run_table_mania_and_committor_tests( let test_committor_dir = format!("{}/../{}", manifest_dir, "test-committor-service"); eprintln!("Running committor tests in {}", test_committor_dir); - match run_test(test_committor_dir, Default::default()) { + match run_test( + test_committor_dir, + RunTestConfig::default(), + // RunTestConfig { + // package: Some("schedulecommit-committor-service"), + // test_file: Some("test_ix_commit_local"), + // test_fn_name: Some( + // "test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed", + // //"test_ix_execute_intent_bundle_commit_and_cau_simultaneously_union_of_accounts", + // ), + // }, + ) { Ok(output) => output, Err(err) => { eprintln!("Failed to run committor: {:?}", err); @@ -461,10 +472,12 @@ fn run_cloning_tests( eprintln!("Running cloning tests in {}", test_cloning_dir); let output = match run_test( test_cloning_dir, - RunTestConfig { - package: Some("test-cloning"), - test: Some("10_post_delegation_token_transfer"), - }, + RunTestConfig::default(), + // RunTestConfig { + // package: Some("test-cloning"), + // test_file: Some("10_post_delegation_token_transfer"), + // test_fn_name: None, + // }, ) { Ok(output) => output, Err(err) => { @@ -688,7 +701,17 @@ fn run_schedule_intents_tests( let test_intents_dir = format!("{}/../{}", manifest_dir, "test-schedule-intent"); eprintln!("Running schedule intents tests in {}", test_intents_dir); - let test_output = match run_test(test_intents_dir, Default::default()) { + let test_output = match run_test( + test_intents_dir, + RunTestConfig::default(), + // RunTestConfig { + // package: Some("test-schedule-intent"), + // test_file: Some("test_schedule_intents"), + // test_fn_name: Some( + // "test_intent_bundle_commit_and_commit_finalize", + // ), + // }, + ) { Ok(output) => output, Err(err) => { eprintln!("Failed to run issues: {:?}", err); @@ -777,7 +800,8 @@ fn assert_cargo_tests_passed(output: process::Output, test_name: &str) { #[derive(Default)] struct RunTestConfig<'a> { package: Option<&'a str>, - test: Option<&'a str>, + test_file: Option<&'a str>, + test_fn_name: Option<&'a str>, } fn run_test( @@ -793,8 +817,11 @@ fn run_test( if let Some(package) = config.package { cmd.arg("-p").arg(package); } - if let Some(test) = config.test { - cmd.arg("--test").arg(test); + if let Some(test_file) = config.test_file { + cmd.arg("--test").arg(test_file); + } + if let Some(test_fn_name) = config.test_fn_name { + cmd.arg(test_fn_name); } cmd.arg("--").arg("--test-threads=1").arg("--nocapture"); cmd.current_dir(manifest_dir.clone()); diff --git a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs index 657e6dc3f..5833561ea 100644 --- a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs +++ b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs @@ -1,26 +1,20 @@ use dlp_api::pda::ephemeral_balance_pda_from_payer; -use ephemeral_rollups_sdk::consts::{MAGIC_CONTEXT_ID, MAGIC_PROGRAM_ID}; -use integration_test_tools::IntegrationTestContext; -use magicblock_magic_program_api::{ - args::{CommitTypeArgs, MagicIntentBundleArgs}, - instruction::MagicBlockInstruction, +use integration_test_tools::{ + conversions::stringify_simulation_result, IntegrationTestContext, }; use program_flexi_counter::{ delegation_program_id, instruction::{ create_add_ix, create_delegate_ix, create_init_ix, - create_intent_bundle_ix, create_intent_ix, + create_intent_bundle_commit_and_finalize_ix, create_intent_bundle_ix, + create_intent_ix, }, state::FlexiCounter, }; +use solana_rpc_client_api::config::RpcSimulateTransactionConfig; use solana_sdk::{ - instruction::{AccountMeta, Instruction}, - native_token::LAMPORTS_PER_SOL, - pubkey::Pubkey, - rent::Rent, - signature::Keypair, - signer::Signer, - transaction::Transaction, + native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, rent::Rent, + signature::Keypair, signer::Signer, transaction::Transaction, }; use test_kit::init_logger; use tracing::*; @@ -804,50 +798,33 @@ fn schedule_intent_bundle_commit_and_finalize( commit_finalize_accounts: Vec, ) { ctx.wait_for_next_slot_ephem().unwrap(); - - let mut all_accounts = Vec::new(); - all_accounts.extend(commit_accounts.iter().copied()); - all_accounts.extend(commit_finalize_accounts.iter().copied()); - all_accounts.sort(); - all_accounts.dedup(); - - let mut metas = vec![ - AccountMeta::new(payer.pubkey(), true), - AccountMeta::new(MAGIC_CONTEXT_ID, false), - ]; - metas.extend( - all_accounts - .iter() - .map(|pubkey| AccountMeta::new(*pubkey, false)), - ); - - let account_index = |pubkey: &Pubkey| -> u8 { - (2 + all_accounts.iter().position(|k| k == pubkey).unwrap()) as u8 - }; - - let args = MagicIntentBundleArgs { - commit: Some(CommitTypeArgs::Standalone( - commit_accounts.iter().map(account_index).collect(), - )), - commit_and_undelegate: None, - commit_finalize: Some(CommitTypeArgs::Standalone( - commit_finalize_accounts.iter().map(account_index).collect(), - )), - commit_finalize_and_undelegate: None, - standalone_actions: vec![], - }; - - let ix = Instruction::new_with_bincode( - MAGIC_PROGRAM_ID, - &MagicBlockInstruction::ScheduleIntentBundle(args), - metas, + let ix = create_intent_bundle_commit_and_finalize_ix( + payer.pubkey(), + commit_accounts, + commit_finalize_accounts, ); let mut tx = Transaction::new_with_payer(&[ix], Some(&payer.pubkey())); - let (sig, confirmed) = ctx - .send_and_confirm_transaction_ephem(&mut tx, &[payer]) - .unwrap(); - assert!(confirmed); + let (sig, confirmed) = + match ctx.send_and_confirm_transaction_ephem(&mut tx, &[payer]) { + Ok(res) => res, + Err(err) => { + dump_ephem_simulation( + ctx, + &tx, + "schedule_intent_bundle_commit_and_finalize", + ); + panic!("Failed to send/confirm ephem tx: {err:#}"); + } + }; + if !confirmed { + dump_ephem_simulation( + ctx, + &tx, + "schedule_intent_bundle_commit_and_finalize", + ); + panic!("Ephem tx not confirmed: {sig}"); + } let commit_result = ctx .fetch_schedule_commit_result::(sig) @@ -857,6 +834,38 @@ fn schedule_intent_bundle_commit_and_finalize( .unwrap(); } +fn dump_ephem_simulation( + ctx: &IntegrationTestContext, + tx: &Transaction, + label: &str, +) { + let Ok(client) = ctx.try_ephem_client() else { + eprintln!("[{label}] failed to get ephem client for simulation"); + return; + }; + + let sig = tx.signatures.first().cloned().unwrap_or_default(); + + match client.simulate_transaction_with_config( + tx, + RpcSimulateTransactionConfig { + sig_verify: false, + replace_recent_blockhash: true, + ..Default::default() + }, + ) { + Ok(res) => { + eprintln!( + "[{label}] {}", + stringify_simulation_result(res.value, &sig) + ); + } + Err(err) => { + eprintln!("[{label}] simulation request failed: {err:?}"); + } + } +} + fn verify_undelegation_in_ephem_via_owner( pubkeys: &[Pubkey], ctx: &IntegrationTestContext, From bdde1e923af92e080b51f1537c1cb6962028b9b2 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 26 Mar 2026 13:29:34 +0530 Subject: [PATCH 09/10] create tasks in async, following Edwin's feedback --- .../src/tasks/task_builder.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index bfb7dd546..55e7051e7 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -1,6 +1,7 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; +use futures_util::future::try_join_all; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, CommitAndUndelegate, CommitType, ScheduledIntentBundle, @@ -340,6 +341,7 @@ impl TasksBuilder for TaskBuilderImpl { } let mut tasks = Vec::new(); + let mut futures = Vec::with_capacity(2); if let Some(ref value) = intent_bundle.intent_bundle.commit { tasks.extend(create_finalize_tasks(value)); @@ -349,14 +351,16 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle.intent_bundle.commit_and_undelegate { tasks.extend(create_finalize_tasks(&value.commit_action)); - tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); - }; + futures.push(create_undelegate_tasks(value, info_fetcher)); + } if let Some(ref value) = intent_bundle.intent_bundle.commit_finalize_and_undelegate { - tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); - }; + futures.push(create_undelegate_tasks(value, info_fetcher)); + } + + tasks.extend(try_join_all(futures).await?.into_iter().flatten()); Ok(tasks) } From fe0bd0e28e2111b5ff06e61e49fad4a7d3bdbf38 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 26 Mar 2026 20:48:26 +0530 Subject: [PATCH 10/10] Update Cargo.toml to dlp-ap 0.2.0 --- Cargo.lock | 7 ++++--- Cargo.toml | 2 +- test-integration/Cargo.lock | 37 +++++++++++++++++++------------------ test-integration/Cargo.toml | 2 +- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1ae5464d..c8b35e035 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3436,8 +3436,9 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "0.1.1" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=09e0102df4ff69dfe9795cdf3b642943a3bbdf59#09e0102df4ff69dfe9795cdf3b642943a3bbdf59" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5611f6531116831ac425882640ec21848c67446c2cab58364cab1e82a7ccdee" dependencies = [ "bincode", "borsh 1.6.0", @@ -3458,7 +3459,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index edad27dbf..0ea448c7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "09e0102df4ff69dfe9795cdf3b642943a3bbdf59" } +magicblock-delegation-program-api = { version = "0.2.0" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 4a2c82ca7..cf8fcdcc5 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -2983,7 +2983,7 @@ dependencies = [ "color-backtrace", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "rand 0.8.5", "rayon", "serde", @@ -3560,7 +3560,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-ledger", "magicblock-magic-program-api 0.8.4", "magicblock-metrics", @@ -3614,7 +3614,7 @@ dependencies = [ "magicblock-accounts-db", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-magic-program-api 0.8.4", "magicblock-metrics", "parking_lot", @@ -3680,7 +3680,7 @@ dependencies = [ "lru", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3797,8 +3797,9 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "0.1.1" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=09e0102df4ff69dfe9795cdf3b642943a3bbdf59#09e0102df4ff69dfe9795cdf3b642943a3bbdf59" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5611f6531116831ac425882640ec21848c67446c2cab58364cab1e82a7ccdee" dependencies = [ "bincode", "borsh 1.6.0", @@ -3819,7 +3820,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -4045,7 +4046,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.4" dependencies = [ - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4996,7 +4997,7 @@ version = "0.0.0" dependencies = [ "borsh 1.6.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-magic-program-api 0.8.4", "rkyv 0.7.45", "solana-program", @@ -5983,7 +5984,7 @@ dependencies = [ "borsh 1.6.0", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "program-schedulecommit", "solana-program", "solana-rpc-client", @@ -6002,7 +6003,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -6027,7 +6028,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-magic-program-api 0.8.4", "magicblock-program", "program-schedulecommit", @@ -6048,7 +6049,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-magic-program-api 0.8.4", "program-schedulecommit", "program-schedulecommit-security", @@ -10332,7 +10333,7 @@ dependencies = [ "integration-test-tools", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "program-flexi-counter", "program-mini", "solana-account", @@ -10355,7 +10356,7 @@ name = "test-cloning" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "program-flexi-counter", "program-mini", "solana-loader-v4-interface", @@ -10419,7 +10420,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "program-flexi-counter", "solana-rpc-client", "solana-sdk", @@ -10440,7 +10441,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-program", "magicblock-validator-admin", "solana-rpc-client", @@ -10481,7 +10482,7 @@ version = "0.0.0" dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", - "magicblock-delegation-program-api 0.1.1", + "magicblock-delegation-program-api 0.2.0", "magicblock-magic-program-api 0.8.4", "program-flexi-counter", "solana-rpc-client-api", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 05e77ecb7..baa6d6cc5 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -60,7 +60,7 @@ magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain- "modular-sdk", ] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "09e0102df4ff69dfe9795cdf3b642943a3bbdf59", default-features = false } +magicblock-delegation-program-api = { version = "0.2.0", default-features = false } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } magicblock-table-mania = { path = "../magicblock-table-mania" }