squads_multisig_program/state/
batch.rs

1use anchor_lang::prelude::*;
2use anchor_lang::solana_program::borsh0_10::get_instance_packed_len;
3
4use crate::{TransactionMessage, VaultTransactionMessage};
5
6/// Stores data required for serial execution of a batch of multisig vault transactions.
7/// Vault transaction is a transaction that's executed on behalf of the multisig vault PDA
8/// and wraps arbitrary Solana instructions, typically calling into other Solana programs.
9/// The transactions themselves are stored in separate PDAs associated with the this account.
10#[account]
11#[derive(InitSpace)]
12pub struct Batch {
13    /// The multisig this belongs to.
14    pub multisig: Pubkey,
15    /// Member of the Multisig who submitted the batch.
16    pub creator: Pubkey,
17    /// Index of this batch within the multisig transactions.
18    pub index: u64,
19    /// PDA bump.
20    pub bump: u8,
21    /// Index of the vault this batch belongs to.
22    pub vault_index: u8,
23    /// Derivation bump of the vault PDA this batch belongs to.
24    pub vault_bump: u8,
25    /// Number of transactions in the batch.
26    pub size: u32,
27    /// Index of the last executed transaction within the batch.
28    /// 0 means that no transactions have been executed yet.
29    pub executed_transaction_index: u32,
30}
31
32impl Batch {
33    pub fn invariant(&self) -> Result<()> {
34        // Just a sanity check.
35        require_gte!(self.size, self.executed_transaction_index);
36
37        Ok(())
38    }
39}
40
41/// Stores data required for execution of one transaction from a batch.
42#[account]
43pub struct VaultBatchTransaction {
44    /// PDA bump.
45    pub bump: u8,
46    /// Derivation bumps for additional signers.
47    /// Some transactions require multiple signers. Often these additional signers are "ephemeral" keypairs
48    /// that are generated on the client with a sole purpose of signing the transaction and be discarded immediately after.
49    /// When wrapping such transactions into multisig ones, we replace these "ephemeral" signing keypairs
50    /// with PDAs derived from the transaction's `transaction_index` and controlled by the Multisig Program;
51    /// during execution the program includes the seeds of these PDAs into the `invoke_signed` calls,
52    /// thus "signing" on behalf of these PDAs.
53    pub ephemeral_signer_bumps: Vec<u8>,
54    /// data required for executing the transaction.
55    pub message: VaultTransactionMessage,
56}
57
58impl VaultBatchTransaction {
59    pub fn size(ephemeral_signers_length: u8, transaction_message: &[u8]) -> Result<usize> {
60        let transaction_message: VaultTransactionMessage =
61            TransactionMessage::deserialize(&mut &transaction_message[..])?.try_into()?;
62
63        let message_size = get_instance_packed_len(&transaction_message).unwrap_or_default();
64
65        Ok(
66            8 +   // anchor account discriminator
67            1 +   // bump
68            (4 + usize::from(ephemeral_signers_length)) +   // ephemeral_signers_bumps vec
69            message_size, // message
70        )
71    }
72}