Skip to main content

squads_multisig_program/state/
transaction_buffer.rs

1use anchor_lang::prelude::*;
2use anchor_lang::solana_program::hash::hash;
3
4use crate::errors::MultisigError;
5
6// Maximum PDA allocation size in an inner ix is 10240 bytes.
7// 10240 - account contents = 10128 bytes
8pub const MAX_BUFFER_SIZE: usize = 10128 ;
9
10#[account]
11#[derive(Default, Debug)]
12pub struct TransactionBuffer {
13    /// The multisig this belongs to.
14    pub multisig: Pubkey,
15    /// Member of the Multisig who created the TransactionBuffer.
16    pub creator: Pubkey,
17    /// Index to seed address derivation
18    pub buffer_index: u8,
19    /// Vault index of the transaction this buffer belongs to.
20    pub vault_index: u8,
21    /// Hash of the final assembled transaction message.
22    pub final_buffer_hash: [u8; 32],
23    /// The size of the final assembled transaction message.
24    pub final_buffer_size: u16,
25    /// The buffer of the transaction message.
26    pub buffer: Vec<u8>,
27}
28
29impl TransactionBuffer {
30    pub fn size(final_message_buffer_size: u16) -> Result<usize> {
31        // Make sure final size is not greater than MAX_BUFFER_SIZE bytes.
32        if (final_message_buffer_size as usize) > MAX_BUFFER_SIZE {
33            return err!(MultisigError::FinalBufferSizeExceeded);
34        }
35        Ok(
36            8 +   // anchor account discriminator
37            32 +  // multisig
38            32 +  // creator
39            1 +   // buffer_index
40            1 +   // vault_index
41            32 +  // transaction_message_hash
42            2 +  // final_buffer_size
43            4 + // vec length bytes
44            final_message_buffer_size as usize, // buffer
45        )
46    }
47
48    pub fn validate_hash(&self) -> Result<()> {
49        let message_buffer_hash = hash(&self.buffer);
50        require!(
51            message_buffer_hash.to_bytes() == self.final_buffer_hash,
52            MultisigError::FinalBufferHashMismatch
53        );
54        Ok(())
55    }
56    pub fn validate_size(&self) -> Result<()> {
57        require_eq!(
58            self.buffer.len(),
59            self.final_buffer_size as usize,
60            MultisigError::FinalBufferSizeMismatch
61        );
62        Ok(())
63    }
64
65    pub fn invariant(&self) -> Result<()> {
66        require!(
67            self.final_buffer_size as usize <= MAX_BUFFER_SIZE,
68            MultisigError::FinalBufferSizeExceeded
69        );
70        require!(
71            self.buffer.len() <= MAX_BUFFER_SIZE,
72            MultisigError::FinalBufferSizeExceeded
73        );
74        require!(
75            self.buffer.len() <= self.final_buffer_size as usize,
76            MultisigError::FinalBufferSizeMismatch
77        );
78
79        Ok(())
80    }
81}