Skip to content

Commit 537b2bf

Browse files
committed
add init multisig ix
1 parent 78a8b44 commit 537b2bf

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use core::slice::from_raw_parts;
2+
3+
use pinocchio::{
4+
account_info::AccountInfo,
5+
cpi::slice_invoke_signed,
6+
instruction::{AccountMeta, Instruction, Signer},
7+
ProgramResult,
8+
};
9+
10+
extern crate alloc;
11+
12+
use alloc::vec::Vec;
13+
14+
use crate::{write_bytes, UNINIT_BYTE};
15+
16+
/// Initialize a new Multisig.
17+
///
18+
/// ### Accounts:
19+
/// 0. `[writable]` The multisig account to initialize.
20+
/// 1. `[]` Rent sysvar
21+
/// 2. ..`2+N`. `[]` The signer accounts, must equal to N where `1 <= N <=
22+
/// 11`.
23+
pub struct InitializeMultisig<'a> {
24+
/// Multisig Account.
25+
pub multisig: &'a AccountInfo,
26+
/// Rent sysvar Account.
27+
pub rent_sysvar: &'a AccountInfo,
28+
/// Signer Accounts
29+
pub multisig_signers: Vec<&'a AccountInfo>,
30+
/// The number of signers (M) required to validate this multisignature
31+
/// account.
32+
pub m: u8,
33+
}
34+
35+
impl InitializeMultisig<'_> {
36+
#[inline(always)]
37+
pub fn invoke(&self) -> ProgramResult {
38+
self.invoke_signed(&[])
39+
}
40+
41+
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
42+
// Account metadata
43+
let mut account_metas = Vec::with_capacity(2 + self.multisig_signers.len());
44+
account_metas.push(AccountMeta::writable(self.multisig.key()));
45+
account_metas.push(AccountMeta::readonly(self.rent_sysvar.key()));
46+
account_metas.extend(
47+
self.multisig_signers
48+
.iter()
49+
.map(|a| AccountMeta::readonly(a.key())),
50+
);
51+
52+
// Instruction data layout:
53+
// - [0]: instruction discriminator (1 byte, u8)
54+
// - [1]: m (1 byte, u8)
55+
let mut instruction_data = [UNINIT_BYTE; 2];
56+
57+
// Set discriminator as u8 at offset [0]
58+
write_bytes(&mut instruction_data, &[2]);
59+
// Set number of signers (m) at offset 1
60+
write_bytes(&mut instruction_data[1..2], &[self.m]);
61+
62+
let instruction = Instruction {
63+
program_id: &crate::ID,
64+
accounts: account_metas.as_slice(),
65+
data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 2) },
66+
};
67+
68+
let mut account_infos = Vec::with_capacity(2 + self.multisig_signers.len());
69+
account_infos.push(self.multisig);
70+
account_infos.push(self.rent_sysvar);
71+
account_infos.extend_from_slice(self.multisig_signers.as_slice());
72+
73+
slice_invoke_signed(&instruction, account_infos.as_slice(), signers)
74+
}
75+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use core::slice::from_raw_parts;
2+
3+
use pinocchio::{
4+
account_info::AccountInfo,
5+
cpi::slice_invoke_signed,
6+
instruction::{AccountMeta, Instruction, Signer},
7+
ProgramResult,
8+
};
9+
10+
extern crate alloc;
11+
12+
use alloc::vec::Vec;
13+
14+
use crate::{write_bytes, UNINIT_BYTE};
15+
16+
/// Initialize a new Multisig.
17+
///
18+
/// ### Accounts:
19+
/// 0. `[writable]` The multisig account to initialize.
20+
/// 1. ..`1+N`. `[]` The signer accounts, must equal to N where `1 <= N <=
21+
/// 11`.
22+
pub struct InitializeMultisig2<'a> {
23+
/// Multisig Account.
24+
pub multisig: &'a AccountInfo,
25+
/// Signer Accounts
26+
pub multisig_signers: Vec<&'a AccountInfo>,
27+
/// The number of signers (M) required to validate this multisignature
28+
/// account.
29+
pub m: u8,
30+
}
31+
32+
impl InitializeMultisig2<'_> {
33+
#[inline(always)]
34+
pub fn invoke(&self) -> ProgramResult {
35+
self.invoke_signed(&[])
36+
}
37+
38+
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
39+
// Account metadata
40+
let mut account_metas = Vec::with_capacity(1 + self.multisig_signers.len());
41+
account_metas.push(AccountMeta::writable(self.multisig.key()));
42+
account_metas.extend(
43+
self.multisig_signers
44+
.iter()
45+
.map(|a| AccountMeta::readonly(a.key())),
46+
);
47+
48+
// Instruction data layout:
49+
// - [0]: instruction discriminator (1 byte, u8)
50+
// - [1]: m (1 byte, u8)
51+
let mut instruction_data = [UNINIT_BYTE; 2];
52+
53+
// Set discriminator as u8 at offset [0]
54+
write_bytes(&mut instruction_data, &[2]);
55+
// Set number of signers (m) at offset 1
56+
write_bytes(&mut instruction_data[1..2], &[self.m]);
57+
58+
let instruction = Instruction {
59+
program_id: &crate::ID,
60+
accounts: account_metas.as_slice(),
61+
data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 2) },
62+
};
63+
64+
let mut account_infos = Vec::with_capacity(1 + self.multisig_signers.len());
65+
account_infos.push(self.multisig);
66+
account_infos.extend_from_slice(self.multisig_signers.as_slice());
67+
68+
slice_invoke_signed(&instruction, &account_infos, signers)
69+
}
70+
}

programs/token/src/instructions/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ mod initialize_account_2;
99
mod initialize_account_3;
1010
mod initialize_mint;
1111
mod initialize_mint_2;
12+
mod initialize_multisig;
13+
mod initialize_multisig_2;
1214
mod mint_to;
1315
mod mint_to_checked;
1416
mod revoke;
@@ -29,6 +31,8 @@ pub use initialize_account_2::*;
2931
pub use initialize_account_3::*;
3032
pub use initialize_mint::*;
3133
pub use initialize_mint_2::*;
34+
pub use initialize_multisig::*;
35+
pub use initialize_multisig_2::*;
3236
pub use mint_to::*;
3337
pub use mint_to_checked::*;
3438
pub use revoke::*;

0 commit comments

Comments
 (0)