pinocchio_token/state/multisig.rs
1use {
2 crate::{instructions::MAX_MULTISIG_SIGNERS, ID},
3 core::mem::size_of,
4 solana_account_view::{AccountView, Ref},
5 solana_address::Address,
6 solana_program_error::ProgramError,
7};
8
9/// Multisignature data.
10#[repr(C)]
11pub struct Multisig {
12 /// Number of signers required
13 m: u8,
14 /// Number of valid signers
15 n: u8,
16 /// Is `true` if this structure has been initialized
17 is_initialized: u8,
18 /// Signer public keys
19 signers: [Address; MAX_MULTISIG_SIGNERS],
20}
21
22impl Multisig {
23 /// The length of the `Multisig` account data.
24 pub const LEN: usize = size_of::<Multisig>();
25
26 /// Return a `Multisig` from the given account view.
27 ///
28 /// This method performs owner and length validation on `AccountView`, safe
29 /// borrowing the account data.
30 #[inline]
31 pub fn from_account_view(
32 account_view: &AccountView,
33 ) -> Result<Ref<'_, Multisig>, ProgramError> {
34 if account_view.data_len() != Self::LEN {
35 return Err(ProgramError::InvalidAccountData);
36 }
37 if !account_view.owned_by(&ID) {
38 return Err(ProgramError::InvalidAccountOwner);
39 }
40 Ok(Ref::map(account_view.try_borrow()?, |data| unsafe {
41 Self::from_bytes_unchecked(data)
42 }))
43 }
44
45 /// Return a `Multisig` from the given account view.
46 ///
47 /// This method performs owner and length validation on `AccountView`, but
48 /// does not perform the borrow check.
49 ///
50 /// # Safety
51 ///
52 /// The caller must ensure that it is safe to borrow the account data (e.g.,
53 /// there are no mutable borrows of the account data).
54 #[inline]
55 pub unsafe fn from_account_view_unchecked(
56 account_view: &AccountView,
57 ) -> Result<&Self, ProgramError> {
58 if account_view.data_len() != Self::LEN {
59 return Err(ProgramError::InvalidAccountData);
60 }
61 if account_view.owner() != &ID {
62 return Err(ProgramError::InvalidAccountOwner);
63 }
64 Ok(Self::from_bytes_unchecked(account_view.borrow_unchecked()))
65 }
66
67 /// Return a `Multisig` from the given bytes.
68 ///
69 /// # Safety
70 ///
71 /// The caller must ensure that `bytes` contains a valid representation of
72 /// `Multisig`, and it has the correct length to be interpreted as an
73 /// instance of `Multisig`.
74 #[inline(always)]
75 pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
76 &*(bytes.as_ptr() as *const Multisig)
77 }
78
79 /// Number of signers required to validate the `Multisig` signature.
80 #[inline(always)]
81 pub const fn required_signers(&self) -> u8 {
82 self.m
83 }
84
85 /// Number of signer addresses present on the `Multisig`.
86 #[inline(always)]
87 pub const fn signers_len(&self) -> usize {
88 self.n as usize
89 }
90
91 /// Return the signer addresses of the `Multisig`.
92 #[inline(always)]
93 pub fn signers(&self) -> &[Address] {
94 // SAFETY: `self.signers` is an array of `Address` with a fixed size of
95 // `MAX_MULTISIG_SIGNERS`; `self.signers_len` is always `<=
96 // MAX_MULTISIG_SIGNERS` and indicates how many of these signers are
97 // valid.
98 unsafe { self.signers.get_unchecked(..self.signers_len()) }
99 }
100
101 /// Check whether the multisig is initialized or not.
102 //
103 // It will return a boolean value indicating whether [`self.is_initialized`]
104 // is different than `0` or not.
105 #[inline(always)]
106 pub fn is_initialized(&self) -> bool {
107 self.is_initialized != 0
108 }
109}