diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs index 2aab63508..88808cc18 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -4,7 +4,7 @@ use std::{ }; use async_trait::async_trait; -use log::{debug, error, info, warn}; +use log::{debug, error, info}; use magicblock_account_cloner::ChainlinkCloner; use magicblock_accounts_db::AccountsDb; use magicblock_chainlink::{ @@ -16,9 +16,7 @@ use magicblock_chainlink::{ Chainlink, }; use magicblock_committor_service::{ - intent_execution_manager::{ - BroadcastedIntentExecutionResult, ExecutionOutputWrapper, - }, + intent_execution_manager::BroadcastedIntentExecutionResult, intent_executor::ExecutionOutput, types::{ScheduledBaseIntentWrapper, TriggerType}, BaseIntentCommittor, CommittorService, @@ -235,79 +233,56 @@ impl ScheduledCommitsProcessorImpl { continue; }; - match execution_result { - Ok(value) => { - Self::process_intent_result( - intent_id, - &internal_transaction_scheduler, - value, - intent_meta, - ) - .await; - } - Err((_, _, err)) => { - match err.as_ref() { - &magicblock_committor_service::intent_executor::error::IntentExecutorError::EmptyIntentError => { - warn!("Empty intent was scheduled!"); - Self::process_empty_intent( - intent_id, - &internal_transaction_scheduler, - intent_meta - ).await; - } - _ => { - error!( - "Failed to commit in slot: {}, blockhash: {}. {:?}", - intent_meta.slot, intent_meta.blockhash, err - ); - } - } - } - } + Self::process_intent_result( + intent_id, + &internal_transaction_scheduler, + execution_result, + intent_meta, + ) + .await; } } async fn process_intent_result( intent_id: u64, internal_transaction_scheduler: &TransactionSchedulerHandle, - execution_outcome: ExecutionOutputWrapper, + result: BroadcastedIntentExecutionResult, mut intent_meta: ScheduledBaseIntentMeta, ) { - let chain_signatures = match execution_outcome.output { - ExecutionOutput::SingleStage(signature) => vec![signature], - ExecutionOutput::TwoStage { - commit_signature, - finalize_signature, - } => vec![commit_signature, finalize_signature], - }; - let intent_sent_transaction = - std::mem::take(&mut intent_meta.intent_sent_transaction); - let sent_commit = - Self::build_sent_commit(intent_id, chain_signatures, intent_meta); - register_scheduled_commit_sent(sent_commit); - match internal_transaction_scheduler - .execute(intent_sent_transaction) - .await - { - Ok(signature) => debug!( - "Signaled sent commit with internal signature: {:?}", - signature - ), - Err(err) => { - error!("Failed to signal sent commit via transaction: {}", err); + let error_message = result + .as_ref() + .err() + .map(|(_, _, err)| format!("{:?}", err)); + let chain_signatures = match result { + Ok(execution_outcome) => match execution_outcome.output { + ExecutionOutput::SingleStage(signature) => vec![signature], + ExecutionOutput::TwoStage { + commit_signature, + finalize_signature, + } => vec![commit_signature, finalize_signature], + }, + Err((_, _, err)) => { + error!( + "Failed to commit in slot: {}, blockhash: {}. {:?}", + intent_meta.slot, intent_meta.blockhash, err + ); + err.signatures() + .map(|(commit, finalize)| { + finalize + .map(|finalize| vec![commit, finalize]) + .unwrap_or(vec![commit]) + }) + .unwrap_or(vec![]) } - } - } - - async fn process_empty_intent( - intent_id: u64, - internal_transaction_scheduler: &TransactionSchedulerHandle, - mut intent_meta: ScheduledBaseIntentMeta, - ) { + }; let intent_sent_transaction = std::mem::take(&mut intent_meta.intent_sent_transaction); - let sent_commit = - Self::build_sent_commit(intent_id, vec![], intent_meta); + let sent_commit = Self::build_sent_commit( + intent_id, + chain_signatures, + intent_meta, + error_message, + ); register_scheduled_commit_sent(sent_commit); match internal_transaction_scheduler .execute(intent_sent_transaction) @@ -327,6 +302,7 @@ impl ScheduledCommitsProcessorImpl { intent_id: u64, chain_signatures: Vec, intent_meta: ScheduledBaseIntentMeta, + error_message: Option, ) -> SentCommit { SentCommit { message_id: intent_id, @@ -337,6 +313,7 @@ impl ScheduledCommitsProcessorImpl { included_pubkeys: intent_meta.included_pubkeys, excluded_pubkeys: vec![], requested_undelegation: intent_meta.requested_undelegation, + error_message, } } } diff --git a/magicblock-committor-service/src/intent_executor/error.rs b/magicblock-committor-service/src/intent_executor/error.rs index e17eda365..f89a3fbe1 100644 --- a/magicblock-committor-service/src/intent_executor/error.rs +++ b/magicblock-committor-service/src/intent_executor/error.rs @@ -105,6 +105,33 @@ impl IntentExecutorError { } } } + + pub fn signatures(&self) -> Option<(Signature, Option)> { + match self { + IntentExecutorError::CpiLimitError(_, signature) + | IntentExecutorError::ActionsError(_, signature) + | IntentExecutorError::CommitIDError(_, signature) + | IntentExecutorError::UndelegationError(_, signature) + | IntentExecutorError::FailedToCommitError { signature, err: _ } => { + signature.map(|el| (el, None)) + } + IntentExecutorError::FailedCommitPreparationError(err) + | IntentExecutorError::FailedFinalizePreparationError(err) => { + err.signature().map(|el| (el, None)) + } + IntentExecutorError::TaskBuilderError(err) => { + err.signature().map(|el| (el, None)) + } + IntentExecutorError::FailedToFinalizeError { + err: _, + commit_signature, + finalize_signature, + } => commit_signature.map(|el| (el, *finalize_signature)), + IntentExecutorError::EmptyIntentError + | IntentExecutorError::FailedToFitError + | IntentExecutorError::SignerError(_) => None, + } + } } impl metrics::LabelValue for IntentExecutorError { 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 2928d2f33..6ec16fd95 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -11,6 +11,7 @@ use lru::LruCache; use magicblock_metrics::metrics; use magicblock_rpc_client::{MagicBlockRpcClientError, MagicblockRpcClient}; use solana_pubkey::Pubkey; +use solana_sdk::signature::Signature; const NUM_FETCH_RETRIES: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(5) }; @@ -276,4 +277,14 @@ pub enum TaskInfoFetcherError { MagicBlockRpcClientError(#[from] MagicBlockRpcClientError), } +impl TaskInfoFetcherError { + pub fn signature(&self) -> Option { + match self { + Self::MetadataNotFoundError(_) => None, + Self::InvalidAccountDataError(_) => None, + Self::MagicBlockRpcClientError(err) => err.signature(), + } + } +} + pub type TaskInfoFetcherResult = Result; diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 36c7315eb..076c98b8f 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -7,6 +7,7 @@ use magicblock_program::magic_scheduled_base_intent::{ UndelegateType, }; use solana_pubkey::Pubkey; +use solana_sdk::signature::Signature; use crate::{ intent_executor::task_info_fetcher::{ @@ -206,4 +207,13 @@ pub enum TaskBuilderError { FinalizedTasksBuildError(#[source] TaskInfoFetcherError), } +impl TaskBuilderError { + pub fn signature(&self) -> Option { + match self { + Self::CommitTasksBuildError(err) => err.signature(), + Self::FinalizedTasksBuildError(err) => err.signature(), + } + } +} + pub type TaskBuilderResult = Result; diff --git a/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs b/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs index 94da08628..53005c92c 100644 --- a/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs +++ b/magicblock-committor-service/src/transaction_preparator/delivery_preparator.rs @@ -95,8 +95,9 @@ impl DeliveryPreparator { let (res1, res2) = join(task_preparations, alts_preparations).await; res1.into_iter() .collect::, _>>() - .map_err(Error::FailedToPrepareBufferAccounts)?; - let lookup_tables = res2.map_err(Error::FailedToCreateALTError)?; + .map_err(DeliveryPreparatorError::FailedToPrepareBufferAccounts)?; + let lookup_tables = + res2.map_err(DeliveryPreparatorError::FailedToCreateALTError)?; Ok(lookup_tables) } @@ -547,12 +548,31 @@ pub enum InternalError { BaseTaskError(#[from] BaseTaskError), } +impl InternalError { + pub fn signature(&self) -> Option { + match self { + Self::MagicBlockRpcClientError(err) => err.signature(), + _ => None, + } + } +} + #[derive(thiserror::Error, Debug)] -pub enum Error { +pub enum DeliveryPreparatorError { #[error("FailedToPrepareBufferAccounts: {0}")] FailedToPrepareBufferAccounts(#[source] InternalError), #[error("FailedToCreateALTError: {0}")] FailedToCreateALTError(#[source] InternalError), } -pub type DeliveryPreparatorResult = Result; +impl DeliveryPreparatorError { + pub fn signature(&self) -> Option { + match self { + Self::FailedToCreateALTError(err) + | Self::FailedToPrepareBufferAccounts(err) => err.signature(), + } + } +} + +pub type DeliveryPreparatorResult = + Result; diff --git a/magicblock-committor-service/src/transaction_preparator/error.rs b/magicblock-committor-service/src/transaction_preparator/error.rs index 72ceb7380..75772daca 100644 --- a/magicblock-committor-service/src/transaction_preparator/error.rs +++ b/magicblock-committor-service/src/transaction_preparator/error.rs @@ -1,7 +1,10 @@ -use solana_sdk::signer::SignerError; +use solana_sdk::{signature::Signature, signer::SignerError}; use thiserror::Error; -use crate::tasks::task_strategist::TaskStrategistError; +use crate::{ + tasks::task_strategist::TaskStrategistError, + transaction_preparator::delivery_preparator::DeliveryPreparatorError, +}; #[derive(Error, Debug)] pub enum TransactionPreparatorError { @@ -10,9 +13,16 @@ pub enum TransactionPreparatorError { #[error("SignerError: {0}")] SignerError(#[from] SignerError), #[error("DeliveryPreparationError: {0}")] - DeliveryPreparationError( - #[from] crate::transaction_preparator::delivery_preparator::Error, - ), + DeliveryPreparationError(#[from] DeliveryPreparatorError), +} + +impl TransactionPreparatorError { + pub fn signature(&self) -> Option { + match self { + Self::DeliveryPreparationError(err) => err.signature(), + _ => None, + } + } } impl From for TransactionPreparatorError { diff --git a/programs/magicblock/src/schedule_transactions/process_scheduled_commit_sent.rs b/programs/magicblock/src/schedule_transactions/process_scheduled_commit_sent.rs index 7bb293d8a..02712422a 100644 --- a/programs/magicblock/src/schedule_transactions/process_scheduled_commit_sent.rs +++ b/programs/magicblock/src/schedule_transactions/process_scheduled_commit_sent.rs @@ -26,6 +26,7 @@ pub struct SentCommit { pub included_pubkeys: Vec, pub excluded_pubkeys: Vec, pub requested_undelegation: bool, + pub error_message: Option, } /// This is a printable version of the SentCommit struct. @@ -40,6 +41,7 @@ struct SentCommitPrintable { included_pubkeys: String, excluded_pubkeys: String, requested_undelegation: bool, + error_message: Option, } impl From for SentCommitPrintable { @@ -67,6 +69,7 @@ impl From for SentCommitPrintable { .collect::>() .join(", "), requested_undelegation: commit.requested_undelegation, + error_message: commit.error_message, } } } @@ -210,6 +213,14 @@ pub fn process_scheduled_commit_sent( ic_msg!(invoke_context, "ScheduledCommitSent requested undelegation",); } + if let Some(error_message) = commit.error_message { + ic_msg!( + invoke_context, + "ScheduledCommitSent error message: {}", + error_message + ); + } + Ok(()) } @@ -245,6 +256,7 @@ mod tests { included_pubkeys: vec![acc], excluded_pubkeys: Default::default(), requested_undelegation: false, + error_message: None, } }