-
Notifications
You must be signed in to change notification settings - Fork 49
feat: fail intent if it will hit MaxInstructionTraceLengthExceeded on Solana #1162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c0b97fa
901562e
baa08bd
4c27d7e
76f4b0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,6 +40,11 @@ pub const COMMIT_FEE_LAMPORTS: u64 = 100_000; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// denominated in micro-lamports per CU (mirrors Solana's priority fee model). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub const COMPUTE_UNIT_PRICE_MICRO_LAMPORTS: u64 = 50_000; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Number of CPIS limited to 64 on Solana | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub const CPI_LIMIT: usize = 64; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Fixed base CPIs per tx stage (SetComputeUnitLimit + SetComputeUnitPrice). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const BASE_STAGE_CPIS: usize = 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Context necessary for construction of Schedule Action | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct ConstructionContext<'a, 'ic> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parent_program_id: Option<Pubkey>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -277,7 +282,7 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| commit_finalize_and_undelegate, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| standalone_actions: actions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.post_validation(context)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.post_validation(&context.invoke_context)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(this) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -286,7 +291,7 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 1. Set of committed accounts shall not overlap with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// set of undelegated accounts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 2. None for now :) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn validate( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn validate( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args: &MagicIntentBundleArgs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context: &ConstructionContext<'_, '_>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<(), InstructionError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -321,13 +326,13 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Post cross intent validation: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 1. Validates that all committed accounts across the entire intent bundle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// are globally unique by pubkey. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn post_validation( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn post_validation( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context: &ConstructionContext<'_, '_>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invoke_context: &&mut InvokeContext<'_>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<(), InstructionError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ic_msg!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context.invoke_context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invoke_context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ScheduleCommit ERR: intent bundle must not be empty.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(InstructionError::InvalidInstructionData); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -339,7 +344,7 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for el in accounts { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !seen.insert(el.pubkey) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ic_msg!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context.invoke_context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invoke_context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ScheduleCommit ERR: duplicate committed account pubkey across bundle: {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| el.pubkey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -364,7 +369,25 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| check(commit_finalize_and_undelegate.get_committed_accounts())?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.validate_cpi_budget(invoke_context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn validate_cpi_budget( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invoke_context: &&mut InvokeContext<'_>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<(), InstructionError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let (commit_stage_cpis, finalize_stage_cpis) = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (self.commit_stage_cpis(), self.finalize_stage_cpis()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if commit_stage_cpis >= CPI_LIMIT || finalize_stage_cpis >= CPI_LIMIT { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ic_msg!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| invoke_context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "ScheduleCommit ERR: too many committed accounts.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Err(InstructionError::MaxAccountsExceeded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+375
to
391
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Diagnostic: include which stage overflowed and by how much. The log currently only says "too many committed accounts"; it doesn't tell operators whether the commit stage or the finalize stage tripped, nor the estimated CPI count vs ✏️ Proposed change pub fn validate_cpi_budget(
&self,
invoke_context: &&mut InvokeContext<'_>,
) -> Result<(), InstructionError> {
let (commit_stage_cpis, finalize_stage_cpis) =
(self.commit_stage_cpis(), self.finalize_stage_cpis());
- if commit_stage_cpis >= CPI_LIMIT || finalize_stage_cpis >= CPI_LIMIT {
+ if commit_stage_cpis >= CPI_LIMIT {
ic_msg!(
invoke_context,
- "ScheduleCommit ERR: too many committed accounts.",
+ "ScheduleCommit ERR: commit-stage CPI estimate {} >= limit {}",
+ commit_stage_cpis, CPI_LIMIT,
);
-
- Err(InstructionError::MaxAccountsExceeded)
- } else {
- Ok(())
+ return Err(InstructionError::MaxAccountsExceeded);
}
+ if finalize_stage_cpis >= CPI_LIMIT {
+ ic_msg!(
+ invoke_context,
+ "ScheduleCommit ERR: finalize-stage CPI estimate {} >= limit {}",
+ finalize_stage_cpis, CPI_LIMIT,
+ );
+ return Err(InstructionError::MaxAccountsExceeded);
+ }
+ Ok(())
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn calculate_fee( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -584,6 +607,46 @@ impl MagicIntentBundle { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.standalone_actions.get_mut(index.checked_sub(offset)?) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn commit_stage_cpis(&self) -> usize { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const COMMIT_CPIS: usize = 3; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const COMMIT_FINALIZE_CPIS: usize = 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut cpis = BASE_STAGE_CPIS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(c) = &self.commit { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += COMMIT_CPIS * c.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(cau) = &self.commit_and_undelegate { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += COMMIT_CPIS * cau.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(cf) = &self.commit_finalize { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += COMMIT_FINALIZE_CPIS * cf.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(cfau) = &self.commit_finalize_and_undelegate { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += COMMIT_FINALIZE_CPIS * cfau.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn finalize_stage_cpis(&self) -> usize { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const FINALIZE_CPIS: usize = 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const UNDELEGATE_CPIS: usize = 5; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut cpis = BASE_STAGE_CPIS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(c) = &self.commit { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += FINALIZE_CPIS * c.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(cau) = &self.commit_and_undelegate { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += (FINALIZE_CPIS + UNDELEGATE_CPIS) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * cau.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(cfau) = &self.commit_finalize_and_undelegate { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis += UNDELEGATE_CPIS * cfau.get_committed_accounts().len(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cpis | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl MagicBaseIntent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ use solana_sdk::{ | |
| commitment_config::CommitmentConfig, | ||
| compute_budget::ComputeBudgetInstruction, | ||
| hash::Hash, | ||
| instruction::Instruction, | ||
| native_token::LAMPORTS_PER_SOL, | ||
| pubkey::Pubkey, | ||
| signature::{Keypair, Signature}, | ||
|
|
@@ -162,82 +163,74 @@ impl ScheduleCommitTestContext { | |
| // ----------------- | ||
| // Schedule Commit specific Transactions | ||
| // ----------------- | ||
| pub fn init_committees(&self) -> Result<Signature> { | ||
| fn init_committee_ixs( | ||
| &self, | ||
| chunk: &[(Keypair, Pubkey)], | ||
| ) -> Vec<Instruction> { | ||
| let mut ixs = vec![ | ||
| ComputeBudgetInstruction::set_compute_unit_limit(1_400_000), | ||
| ComputeBudgetInstruction::set_compute_unit_price(10_000), | ||
| ]; | ||
| match self.user_seed { | ||
| UserSeeds::MagicScheduleCommit => { | ||
| ixs.extend(self.committees.iter().map( | ||
| |(player, committee)| { | ||
| init_account_instruction( | ||
| self.payer_chain.pubkey(), | ||
| player.pubkey(), | ||
| *committee, | ||
| ) | ||
| }, | ||
| )); | ||
| ixs.extend(chunk.iter().map(|(player, committee)| { | ||
| init_account_instruction( | ||
| self.payer_chain.pubkey(), | ||
| player.pubkey(), | ||
| *committee, | ||
| ) | ||
| })); | ||
| } | ||
| UserSeeds::OrderBook => { | ||
| ixs.extend(self.committees.iter().map( | ||
| |(book_manager, committee)| { | ||
| init_order_book_instruction( | ||
| self.payer_chain.pubkey(), | ||
| book_manager.pubkey(), | ||
| *committee, | ||
| ) | ||
| }, | ||
| )); | ||
|
|
||
| //// TODO (snawaz): currently the size of delegatable-account cannot be | ||
| //// more than 10K, else delegation will fail. So Let's revisit this when | ||
| //// we relax the limit on the account size, then we can use larger | ||
| //// account, say even 10 MB, and execute CommitDiff. | ||
| // | ||
| // ixs.extend(self.committees.iter().flat_map( | ||
| // |(payer, committee)| { | ||
| // [grow_order_book_instruction( | ||
| // payer.pubkey(), | ||
| // *committee, | ||
| // 10 * 1024 | ||
| // )] | ||
| // }, | ||
| // )); | ||
| ixs.extend(chunk.iter().map(|(book_manager, committee)| { | ||
| init_order_book_instruction( | ||
| self.payer_chain.pubkey(), | ||
| book_manager.pubkey(), | ||
| *committee, | ||
| ) | ||
| })); | ||
| } | ||
| }; | ||
| ixs | ||
| } | ||
|
|
||
| let mut signers = self | ||
| .committees | ||
| .iter() | ||
| .map(|(payer, _)| payer) | ||
| .collect::<Vec<_>>(); | ||
| signers.push(&self.payer_chain); | ||
|
|
||
| let tx = Transaction::new_signed_with_payer( | ||
| &ixs, | ||
| Some(&self.payer_chain.pubkey()), | ||
| &signers, | ||
| self.try_chain_blockhash()?, | ||
| ); | ||
| let sig = self.try_chain_client()? | ||
| .send_and_confirm_transaction_with_spinner_and_config( | ||
| &tx, | ||
| self.commitment, | ||
| RpcSendTransactionConfig { | ||
| skip_preflight: true, | ||
| ..Default::default() | ||
| }, | ||
| ) | ||
| .with_context(|| { | ||
| format!( | ||
| "Failed to initialize committees. Transaction signature: {}", | ||
| tx.get_signature() | ||
| ) | ||
| })?; | ||
|
|
||
| debug!("Initialized committees: {sig}"); | ||
| Ok(sig) | ||
| pub fn init_committees(&self) -> Result<Vec<Signature>> { | ||
| const CHUNK_SIZE: usize = 5; | ||
| let chain_client = self.try_chain_client()?; | ||
|
|
||
| self.committees | ||
| .chunks(CHUNK_SIZE) | ||
| .map(|chunk| { | ||
| let ixs = self.init_committee_ixs(chunk); | ||
| let mut signers = | ||
| chunk.iter().map(|(p, _)| p).collect::<Vec<_>>(); | ||
| signers.push(&self.payer_chain); | ||
| (ixs, signers) | ||
| }) | ||
| .map(|(ixs, signers)| -> Result<Signature> { | ||
| let tx = Transaction::new_signed_with_payer( | ||
| &ixs, | ||
| Some(&self.payer_chain.pubkey()), | ||
| &signers, | ||
| self.try_chain_blockhash()?, | ||
| ); | ||
| chain_client | ||
| .send_and_confirm_transaction_with_spinner_and_config( | ||
| &tx, | ||
| self.commitment, | ||
| RpcSendTransactionConfig { | ||
| skip_preflight: true, | ||
| ..Default::default() | ||
| }, | ||
| ) | ||
| .with_context(|| { | ||
| format!( | ||
| "Failed to initialize committees. Transaction signature: {}", | ||
| tx.get_signature() | ||
| ) | ||
| }) | ||
| }) | ||
| .collect::<Result<Vec<_>>>() | ||
| } | ||
|
Comment on lines
+197
to
234
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Partial-failure semantics for chunked init/delegate.
|
||
|
|
||
| pub fn escrow_lamports_for_payer(&self) -> Result<Signature> { | ||
|
|
@@ -262,44 +255,49 @@ impl ScheduleCommitTestContext { | |
| .with_context(|| "Failed to escrow fund for payer") | ||
| } | ||
|
|
||
| pub fn delegate_committees(&self) -> Result<Signature> { | ||
| let mut ixs = vec![]; | ||
| for (player, _) in &self.committees { | ||
| let ix = delegate_account_cpi_instruction( | ||
| self.payer_chain.pubkey(), | ||
| self.ephem_validator_identity, | ||
| player.pubkey(), | ||
| self.user_seed, | ||
| ); | ||
| ixs.push(ix); | ||
| } | ||
|
|
||
| let chain_blockhash = self.try_chain_blockhash()?; | ||
|
|
||
| let tx = Transaction::new_signed_with_payer( | ||
| &ixs, | ||
| Some(&self.payer_chain.pubkey()), | ||
| &[&self.payer_chain], | ||
| chain_blockhash, | ||
| ); | ||
| let sig = self | ||
| .try_chain_client()? | ||
| .send_and_confirm_transaction_with_spinner_and_config( | ||
| &tx, | ||
| self.commitment, | ||
| RpcSendTransactionConfig { | ||
| skip_preflight: true, | ||
| ..Default::default() | ||
| }, | ||
| ) | ||
| .with_context(|| { | ||
| format!( | ||
| "Failed to delegate committees on chain '{:?}'", | ||
| tx.signatures[0] | ||
| ) | ||
| })?; | ||
| debug!("Delegated committees: {sig}"); | ||
| Ok(sig) | ||
| pub fn delegate_committees(&self) -> Result<Vec<Signature>> { | ||
| const CHUNK_SIZE: usize = 4; | ||
| let chain_client = self.try_chain_client()?; | ||
|
|
||
| self.committees | ||
| .chunks(CHUNK_SIZE) | ||
| .map(|chunk| { | ||
| chunk | ||
| .iter() | ||
| .map(|(player, _)| { | ||
| delegate_account_cpi_instruction( | ||
| self.payer_chain.pubkey(), | ||
| self.ephem_validator_identity, | ||
| player.pubkey(), | ||
| self.user_seed, | ||
| ) | ||
| }) | ||
| .collect::<Vec<_>>() | ||
| }) | ||
| .map(|ixs| -> Result<Signature> { | ||
| let tx = Transaction::new_signed_with_payer( | ||
| &ixs, | ||
| Some(&self.payer_chain.pubkey()), | ||
| &[&self.payer_chain], | ||
| self.try_chain_blockhash()?, | ||
| ); | ||
| chain_client | ||
| .send_and_confirm_transaction_with_spinner_and_config( | ||
| &tx, | ||
| self.commitment, | ||
| RpcSendTransactionConfig { | ||
| skip_preflight: true, | ||
| ..Default::default() | ||
| }, | ||
| ) | ||
| .with_context(|| { | ||
| format!( | ||
| "Failed to delegate committees on chain '{:?}'", | ||
| tx.signatures[0] | ||
| ) | ||
| }) | ||
| }) | ||
| .collect::<Result<Vec<_>>>() | ||
| } | ||
|
|
||
| // ----------------- | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
CPI_LIMITdoc and threshold semantics.Solana's actual constant is
MAX_INSTRUCTION_TRACE_LENGTH = 64, which bounds total instructions in the trace (top-level + all CPIs), not strictly CPIs. With stepped formulas (2 + 3·n,2 + 6·n,2 + 5·n) the estimate never lands on exactly 64, so>=vs>is indistinguishable in practice today — but the naming and doc-comment suggest "max CPIs = 64" while the check semantics are "reject at 64 or more instructions", and a future helper that produces an estimate of exactly 64 would be incorrectly rejected.Recommend either:
MAX_INSTRUCTION_TRACE_LENGTHand update the comment to match Solana's terminology, or63(one less than Solana's hard limit) to preserve a safety margin against the inherent estimate imprecision.🤖 Prompt for AI Agents