diff --git a/chains/solana/contracts/programs/mcm/src/constant.rs b/chains/solana/contracts/programs/mcm/src/constant.rs index c930251d6..98a3fd8c3 100644 --- a/chains/solana/contracts/programs/mcm/src/constant.rs +++ b/chains/solana/contracts/programs/mcm/src/constant.rs @@ -1,12 +1,12 @@ // Business-logic constants pub const MAX_NUM_SIGNERS: usize = 180; // maximum number of signers supported -pub const NUM_GROUPS: usize = 32; // Value copied from EVM reference contract +pub const NUM_GROUPS: usize = 32; // maximum number of signer groups supported -// fixed size msig name for distinguishing different multisig instances -pub const MULTISIG_NAME_PADDED: usize = 32; +// fixed size msig id for distinguishing different multisig instances +pub const MULTISIG_ID_PADDED: usize = 32; // PDA seeds -// Note: These seeds are not full seed, for unique seeds, multisig_name should be appended +// Note: These seeds are not full seed, for unique seeds per instance, multisi_id should be appended pub const SIGNER_SEED: &[u8] = b"multisig_signer"; // seed for dataless pda signing CPI pub const CONFIG_SEED: &[u8] = b"multisig_config"; pub const CONFIG_SIGNERS_SEED: &[u8] = b"multisig_config_signers"; diff --git a/chains/solana/contracts/programs/mcm/src/instructions/execute.rs b/chains/solana/contracts/programs/mcm/src/instructions/execute.rs index 8db40ee21..698ee06c3 100644 --- a/chains/solana/contracts/programs/mcm/src/instructions/execute.rs +++ b/chains/solana/contracts/programs/mcm/src/instructions/execute.rs @@ -12,7 +12,7 @@ use crate::state::root::*; pub fn execute<'info>( ctx: Context<'_, '_, '_, 'info, Execute<'info>>, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], chain_id: u64, nonce: u64, data: Vec, @@ -84,7 +84,7 @@ pub fn execute<'info>( let seeds = &[ SIGNER_SEED, - multisig_name.as_ref(), + multisig_id.as_ref(), &[ctx.bumps.multisig_signer], ]; let signer = &[&seeds[..]]; @@ -103,15 +103,15 @@ pub fn execute<'info>( } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct Execute<'info> { - #[account(mut, seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub multisig_config: Account<'info, MultisigConfig>, - #[account(seeds = [ROOT_METADATA_SEED, multisig_name.as_ref()], bump)] + #[account(seeds = [ROOT_METADATA_SEED, multisig_id.as_ref()], bump)] pub root_metadata: Account<'info, RootMetadata>, - #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_id.as_ref()], bump)] pub expiring_root_and_op_count: Account<'info, ExpiringRootAndOpCount>, /// CHECK: This is just used to invoke it through the CPI, it's value is not accessed directly @@ -119,7 +119,7 @@ pub struct Execute<'info> { /// CHECK: program signer PDA that can hold balance #[account( - seeds = [SIGNER_SEED, multisig_name.as_ref()], + seeds = [SIGNER_SEED, multisig_id.as_ref()], bump )] pub multisig_signer: UncheckedAccount<'info>, diff --git a/chains/solana/contracts/programs/mcm/src/instructions/set_config.rs b/chains/solana/contracts/programs/mcm/src/instructions/set_config.rs index 96211701a..cc1db44e5 100644 --- a/chains/solana/contracts/programs/mcm/src/instructions/set_config.rs +++ b/chains/solana/contracts/programs/mcm/src/instructions/set_config.rs @@ -10,7 +10,7 @@ use crate::state::root::*; /// Set the configuration for the multisig instance after validating the input pub fn set_config( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], // for pda derivation + _multisig_id: [u8; MULTISIG_ID_PADDED], // for pda derivation signer_groups: Vec, group_quorums: [u8; NUM_GROUPS], group_parents: [u8; NUM_GROUPS], @@ -155,7 +155,7 @@ pub fn set_config( pub fn init_signers( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], total_signers: u8, ) -> Result<()> { require!( @@ -171,7 +171,7 @@ pub fn init_signers( pub fn append_signers( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], signers_batch: Vec<[u8; 20]>, ) -> Result<()> { let config_signers = &mut ctx.accounts.config_signers; @@ -203,7 +203,7 @@ pub fn append_signers( pub fn clear_signers( _ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { // NOTE: ctx.accounts.config_signers is closed to be able to re-initialized, // also allow finalized config_signers to be cleared @@ -212,7 +212,7 @@ pub fn clear_signers( pub fn finalize_signers( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { let config_signers = &mut ctx.accounts.config_signers; @@ -227,11 +227,11 @@ pub fn finalize_signers( } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct SetConfig<'info> { #[account( mut, - seeds = [CONFIG_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SEED, multisig_id.as_ref()], bump, realloc = ANCHOR_DISCRIMINATOR + MultisigConfig::space_with_signers( config_signers.signer_addresses.len() @@ -243,17 +243,17 @@ pub struct SetConfig<'info> { #[account( mut, - seeds = [CONFIG_SIGNERS_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SIGNERS_SEED, multisig_id.as_ref()], bump, constraint = config_signers.is_finalized @ McmError::SignersNotFinalized, close = authority // close after config set )] pub config_signers: Account<'info, ConfigSigners>, // preloaded signers account - #[account(mut, seeds = [ROOT_METADATA_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [ROOT_METADATA_SEED, multisig_id.as_ref()], bump)] pub root_metadata: Account<'info, RootMetadata>, - #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_id.as_ref()], bump)] pub expiring_root_and_op_count: Account<'info, ExpiringRootAndOpCount>, #[account(mut, address = multisig_config.owner @ AuthError::Unauthorized)] @@ -263,16 +263,16 @@ pub struct SetConfig<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED], total_signers: u8)] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED], total_signers: u8)] pub struct InitSigners<'info> { - #[account(seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub multisig_config: Account<'info, MultisigConfig>, #[account( init, payer = authority, space = ConfigSigners::space(total_signers as usize), - seeds = [CONFIG_SIGNERS_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SIGNERS_SEED, multisig_id.as_ref()], bump )] pub config_signers: Account<'info, ConfigSigners>, @@ -284,14 +284,14 @@ pub struct InitSigners<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct AppendSigners<'info> { - #[account(seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub multisig_config: Account<'info, MultisigConfig>, #[account( mut, - seeds = [CONFIG_SIGNERS_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SIGNERS_SEED, multisig_id.as_ref()], bump, constraint = !config_signers.is_finalized @ McmError::SignersAlreadyFinalized )] @@ -302,14 +302,14 @@ pub struct AppendSigners<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct ClearSigners<'info> { - #[account(seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub multisig_config: Account<'info, MultisigConfig>, #[account( mut, - seeds = [CONFIG_SIGNERS_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SIGNERS_SEED, multisig_id.as_ref()], bump, close = authority // close so that it can be re-initialized )] @@ -320,14 +320,14 @@ pub struct ClearSigners<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct FinalizeSigners<'info> { - #[account(seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub multisig_config: Account<'info, MultisigConfig>, #[account( mut, - seeds = [CONFIG_SIGNERS_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SIGNERS_SEED, multisig_id.as_ref()], bump, constraint = !config_signers.is_finalized @ McmError::SignersAlreadyFinalized )] diff --git a/chains/solana/contracts/programs/mcm/src/instructions/set_root.rs b/chains/solana/contracts/programs/mcm/src/instructions/set_root.rs index e12a3b696..5c93d27c6 100644 --- a/chains/solana/contracts/programs/mcm/src/instructions/set_root.rs +++ b/chains/solana/contracts/programs/mcm/src/instructions/set_root.rs @@ -9,7 +9,7 @@ use crate::state::root::*; pub fn set_root( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, metadata: RootMetadataInput, @@ -172,7 +172,7 @@ fn verify_ecdsa_signatures( pub fn init_signatures( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], _root: [u8; 32], _valid_until: u32, total_signatures: u8, @@ -186,7 +186,7 @@ pub fn init_signatures( pub fn append_signatures( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], _root: [u8; 32], _valid_until: u32, signatures_batch: Vec, @@ -207,7 +207,7 @@ pub fn append_signatures( pub fn clear_signatures( _ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], _root: [u8; 32], _valid_until: u32, ) -> Result<()> { @@ -218,7 +218,7 @@ pub fn clear_signatures( pub fn finalize_signatures( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], _root: [u8; 32], _valid_until: u32, ) -> Result<()> { @@ -235,33 +235,33 @@ pub fn finalize_signatures( } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED], root: [u8; 32], valid_until: u32)] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32)] pub struct SetRoot<'info> { #[account( mut, - seeds = [ROOT_SIGNATURES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [ROOT_SIGNATURES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump, constraint = root_signatures.is_finalized @ McmError::SignaturesNotFinalized, close = authority )] pub root_signatures: Account<'info, RootSignatures>, // preloaded signatures account - #[account(mut, seeds = [ROOT_METADATA_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [ROOT_METADATA_SEED, multisig_id.as_ref()], bump)] pub root_metadata: Account<'info, RootMetadata>, #[account( init, - seeds = [SEEN_SIGNED_HASHES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [SEEN_SIGNED_HASHES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump, payer = authority, space = ANCHOR_DISCRIMINATOR + SeenSignedHash::INIT_SPACE, )] pub seen_signed_hashes: Account<'info, SeenSignedHash>, - #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_id.as_ref()], bump)] pub expiring_root_and_op_count: Account<'info, ExpiringRootAndOpCount>, - #[account(seeds = [CONFIG_SEED, multisig_name.as_ref()],bump)] + #[account(seeds = [CONFIG_SEED, multisig_id.as_ref()],bump)] pub multisig_config: Account<'info, MultisigConfig>, #[account(mut)] @@ -272,7 +272,7 @@ pub struct SetRoot<'info> { #[derive(Accounts)] #[instruction( - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, total_signatures: u8, @@ -282,7 +282,7 @@ pub struct InitSignatures<'info> { init, payer = authority, space = RootSignatures::space(total_signatures as usize), - seeds = [ROOT_SIGNATURES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [ROOT_SIGNATURES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump )] pub signatures: Account<'info, RootSignatures>, @@ -294,11 +294,11 @@ pub struct InitSignatures<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED], root: [u8; 32], valid_until: u32)] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32)] pub struct AppendSignatures<'info> { #[account( mut, - seeds = [ROOT_SIGNATURES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [ROOT_SIGNATURES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump, constraint = !signatures.is_finalized @ McmError::SignaturesAlreadyFinalized )] @@ -309,11 +309,11 @@ pub struct AppendSignatures<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED], root: [u8; 32], valid_until: u32)] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32)] pub struct ClearSignatures<'info> { #[account( mut, - seeds = [ROOT_SIGNATURES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [ROOT_SIGNATURES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump, close = authority // close so that it can be re-initialized )] @@ -324,11 +324,11 @@ pub struct ClearSignatures<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED], root: [u8; 32], valid_until: u32)] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32)] pub struct FinalizeSignatures<'info> { #[account( mut, - seeds = [ROOT_SIGNATURES_SEED, multisig_name.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], + seeds = [ROOT_SIGNATURES_SEED, multisig_id.as_ref(), root.as_ref(), valid_until.to_le_bytes().as_ref()], bump, constraint = !signatures.is_finalized @ McmError::SignaturesAlreadyFinalized )] diff --git a/chains/solana/contracts/programs/mcm/src/lib.rs b/chains/solana/contracts/programs/mcm/src/lib.rs index cbea85179..6627c893a 100644 --- a/chains/solana/contracts/programs/mcm/src/lib.rs +++ b/chains/solana/contracts/programs/mcm/src/lib.rs @@ -23,21 +23,21 @@ mod instructions; use instructions::*; /// This is mcm program supporting multiple instances of multisig configuration -/// A single deployed program manages multiple multisig states(configurations) identified by multisig_name +/// A single deployed program manages multiple multisig states(configurations) identified by multisig_id #[program] pub mod mcm { use super::*; - /// initialize a new multisig configuration, store the chain_id and multisig_name - /// multisig_name is a unique identifier for the multisig configuration(32 bytes, left-padded) + /// initialize a new multisig configuration, store the chain_id and multisig_id + /// multisig_id is a unique identifier for the multisig configuration(32 bytes, left-padded) pub fn initialize( ctx: Context, chain_id: u64, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { let config = &mut ctx.accounts.multisig_config; config.chain_id = chain_id; - config.multisig_name = multisig_name; + config.multisig_id = multisig_id; config.owner = ctx.accounts.authority.key(); Ok(()) } @@ -45,7 +45,7 @@ pub mod mcm { // shared func signature with other programs pub fn transfer_ownership( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], proposed_owner: Pubkey, ) -> Result<()> { let config = &mut ctx.accounts.config; @@ -57,7 +57,7 @@ pub mod mcm { // shared func signature with other programs pub fn accept_ownership( ctx: Context, - _multisig_name: [u8; MULTISIG_NAME_PADDED], + _multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { ctx.accounts.config.owner = std::mem::take(&mut ctx.accounts.config.proposed_owner); ctx.accounts.config.proposed_owner = Pubkey::new_from_array([0; 32]); @@ -66,7 +66,7 @@ pub mod mcm { pub fn set_config( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], signer_groups: Vec, group_quorums: [u8; NUM_GROUPS], group_parents: [u8; NUM_GROUPS], @@ -74,7 +74,7 @@ pub mod mcm { ) -> Result<()> { instructions::set_config( ctx, - multisig_name, + multisig_id, signer_groups, group_quorums, group_parents, @@ -84,7 +84,7 @@ pub mod mcm { pub fn set_root( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, metadata: RootMetadataInput, @@ -92,7 +92,7 @@ pub mod mcm { ) -> Result<()> { instructions::set_root( ctx, - multisig_name, + multisig_id, root, valid_until, metadata, @@ -102,91 +102,91 @@ pub mod mcm { pub fn execute<'info>( ctx: Context<'_, '_, '_, 'info, Execute<'info>>, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], chain_id: u64, nonce: u64, data: Vec, // bytes array proof: Vec<[u8; 32]>, ) -> Result<()> { - instructions::execute(ctx, multisig_name, chain_id, nonce, data, proof) + instructions::execute(ctx, multisig_id, chain_id, nonce, data, proof) } // batch configuration methods prerequisites for set_config pub fn init_signers( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], total_signers: u8, ) -> Result<()> { - instructions::init_signers(ctx, multisig_name, total_signers) + instructions::init_signers(ctx, multisig_id, total_signers) } pub fn append_signers( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], signers_batch: Vec<[u8; 20]>, ) -> Result<()> { - instructions::append_signers(ctx, multisig_name, signers_batch) + instructions::append_signers(ctx, multisig_id, signers_batch) } pub fn clear_signers( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { - instructions::clear_signers(ctx, multisig_name) + instructions::clear_signers(ctx, multisig_id) } pub fn finalize_signers( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], ) -> Result<()> { - instructions::finalize_signers(ctx, multisig_name) + instructions::finalize_signers(ctx, multisig_id) } // batch configuration methods prerequisites for set_root pub fn init_signatures( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, total_signatures: u8, ) -> Result<()> { - instructions::init_signatures(ctx, multisig_name, root, valid_until, total_signatures) + instructions::init_signatures(ctx, multisig_id, root, valid_until, total_signatures) } pub fn append_signatures( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, signatures_batch: Vec, ) -> Result<()> { - instructions::append_signatures(ctx, multisig_name, root, valid_until, signatures_batch) + instructions::append_signatures(ctx, multisig_id, root, valid_until, signatures_batch) } pub fn clear_signatures( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, ) -> Result<()> { - instructions::clear_signatures(ctx, multisig_name, root, valid_until) + instructions::clear_signatures(ctx, multisig_id, root, valid_until) } pub fn finalize_signatures( ctx: Context, - multisig_name: [u8; MULTISIG_NAME_PADDED], + multisig_id: [u8; MULTISIG_ID_PADDED], root: [u8; 32], valid_until: u32, ) -> Result<()> { - instructions::finalize_signatures(ctx, multisig_name, root, valid_until) + instructions::finalize_signatures(ctx, multisig_id, root, valid_until) } } #[derive(Accounts)] -#[instruction(chain_id: u64, multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(chain_id: u64, multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct Initialize<'info> { #[account( init, - seeds = [CONFIG_SEED, multisig_name.as_ref()], + seeds = [CONFIG_SEED, multisig_id.as_ref()], bump, space = ANCHOR_DISCRIMINATOR + config::MultisigConfig::INIT_SPACE, payer = authority, @@ -206,7 +206,7 @@ pub struct Initialize<'info> { #[account( init, - seeds = [ROOT_METADATA_SEED, multisig_name.as_ref()], + seeds = [ROOT_METADATA_SEED, multisig_id.as_ref()], bump, payer = authority, space = ANCHOR_DISCRIMINATOR + RootMetadata::INIT_SPACE @@ -215,7 +215,7 @@ pub struct Initialize<'info> { #[account( init, - seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_name.as_ref()], + seeds = [EXPIRING_ROOT_AND_OP_COUNT_SEED, multisig_id.as_ref()], bump, payer = authority, space = ANCHOR_DISCRIMINATOR + ExpiringRootAndOpCount::INIT_SPACE, @@ -224,9 +224,9 @@ pub struct Initialize<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct TransferOwnership<'info> { - #[account(mut, seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub config: Account<'info, config::MultisigConfig>, #[account(address = config.owner @ AuthError::Unauthorized)] @@ -234,9 +234,9 @@ pub struct TransferOwnership<'info> { } #[derive(Accounts)] -#[instruction(multisig_name: [u8; MULTISIG_NAME_PADDED])] +#[instruction(multisig_id: [u8; MULTISIG_ID_PADDED])] pub struct AcceptOwnership<'info> { - #[account(mut, seeds = [CONFIG_SEED, multisig_name.as_ref()], bump)] + #[account(mut, seeds = [CONFIG_SEED, multisig_id.as_ref()], bump)] pub config: Account<'info, config::MultisigConfig>, #[account(address = config.proposed_owner @ AuthError::Unauthorized)] diff --git a/chains/solana/contracts/programs/mcm/src/state/config.rs b/chains/solana/contracts/programs/mcm/src/state/config.rs index 8a6bac20e..655225fa7 100644 --- a/chains/solana/contracts/programs/mcm/src/state/config.rs +++ b/chains/solana/contracts/programs/mcm/src/state/config.rs @@ -26,7 +26,7 @@ pub struct McmSigner { #[account] pub struct MultisigConfig { pub chain_id: u64, - pub multisig_name: [u8; MULTISIG_NAME_PADDED], + pub multisig_id: [u8; MULTISIG_ID_PADDED], pub owner: Pubkey, pub proposed_owner: Pubkey, @@ -45,13 +45,13 @@ impl MultisigConfig { NUM_GROUPS + // group_parents [u8; NUM_GROUPS] 32 + // owner (Pubkey) 32 + // proposed_owner (Pubkey) - 4 + // string prefix for multisig_name - MULTISIG_NAME_PADDED + // fixed max multisig_name length from initialization + 4 + // string prefix for multisig_id + MULTISIG_ID_PADDED + // fixed max multisig_id length from initialization 4; // empty vec prefix for signers // for realloc - only need to account for signers pub fn space_with_signers(num_signers: usize) -> usize { - Self::INIT_SPACE + // Base space including fixed multisig_name + Self::INIT_SPACE + // Base space including fixed multisig_id num_signers * McmSigner::INIT_SPACE // Just add signers space } } diff --git a/chains/solana/contracts/programs/timelock/src/constants.rs b/chains/solana/contracts/programs/timelock/src/constants.rs index 63496ffe1..a50b1d065 100644 --- a/chains/solana/contracts/programs/timelock/src/constants.rs +++ b/chains/solana/contracts/programs/timelock/src/constants.rs @@ -8,4 +8,5 @@ pub const TIMELOCK_BLOCKED_FUNCITON_SELECTOR_SEED: &[u8] = b"timelock_blocked_fu pub const ANCHOR_DISCRIMINATOR: usize = 8; pub const DONE_TIMESTAMP: u64 = 1; pub const EMPTY_PREDECESSOR: [u8; 32] = [0; 32]; -pub const MAX_SELECTORS: usize = 32; // todo: temp arbitary max, tested with max 128 +pub const TIMELOCK_ID_PADDED: usize = 32; // fixed size timelock id for distinguishing different timelock states +pub const MAX_SELECTORS: usize = 128; // max number of function selectors that can be blocked(arrayvec) diff --git a/chains/solana/contracts/programs/timelock/src/error.rs b/chains/solana/contracts/programs/timelock/src/error.rs index 852b92040..126520951 100644 --- a/chains/solana/contracts/programs/timelock/src/error.rs +++ b/chains/solana/contracts/programs/timelock/src/error.rs @@ -61,9 +61,6 @@ pub enum TimelockError { #[msg("RBACTimelock: selector not found")] SelectorNotFound, - #[msg("RBACTimelock: invalid instruction data")] - InvalidInstructionData, // todo: update this with solid fn blocker policy - #[msg("RBACTimelock: maximum capacity reached for function blocker")] MaxCapacityReached, } diff --git a/chains/solana/contracts/programs/timelock/src/instructions/cancel.rs b/chains/solana/contracts/programs/timelock/src/instructions/cancel.rs index e967b2ca3..c61e1d4cf 100644 --- a/chains/solana/contracts/programs/timelock/src/instructions/cancel.rs +++ b/chains/solana/contracts/programs/timelock/src/instructions/cancel.rs @@ -2,24 +2,28 @@ use anchor_lang::prelude::*; use access_controller::AccessController; -use crate::constants::{TIMELOCK_CONFIG_SEED, TIMELOCK_OPERATION_SEED}; +use crate::constants::{TIMELOCK_CONFIG_SEED, TIMELOCK_ID_PADDED, TIMELOCK_OPERATION_SEED}; use crate::error::TimelockError; use crate::event::*; use crate::state::{Config, Operation}; /// cancels a pending operation -pub fn cancel<'info>(_ctx: Context<'_, '_, '_, 'info, Cancel<'info>>, id: [u8; 32]) -> Result<()> { +pub fn cancel<'info>( + _ctx: Context<'_, '_, '_, 'info, Cancel<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], + id: [u8; 32], +) -> Result<()> { emit!(Cancelled { id }); // NOTE: PDA is closed - is handled by anchor on exit due to the `close` attribute Ok(()) } #[derive(Accounts)] -#[instruction(id: [u8; 32])] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32])] pub struct Cancel<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, close = authority, // todo: check if we send fund back to the signer, otherwise, we'll have additional destination account constraint = operation.id == id @ TimelockError::InvalidId, @@ -27,7 +31,7 @@ pub struct Cancel<'info> { )] pub operation: Account<'info, Operation>, - #[account( seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account( seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // NOTE: access controller check happens in only_role_or_admin_role macro diff --git a/chains/solana/contracts/programs/timelock/src/instructions/execute.rs b/chains/solana/contracts/programs/timelock/src/instructions/execute.rs index 1a486db2f..1e60a5011 100644 --- a/chains/solana/contracts/programs/timelock/src/instructions/execute.rs +++ b/chains/solana/contracts/programs/timelock/src/instructions/execute.rs @@ -1,4 +1,5 @@ use anchor_lang::solana_program::instruction::Instruction; +use anchor_lang::solana_program::keccak::HASH_BYTES; use anchor_lang::{prelude::*, solana_program}; use solana_program::program::invoke_signed; @@ -6,7 +7,8 @@ use access_controller::AccessController; use bytemuck::Zeroable; use crate::constants::{ - EMPTY_PREDECESSOR, TIMELOCK_CONFIG_SEED, TIMELOCK_OPERATION_SEED, TIMELOCK_SIGNER_SEED, + EMPTY_PREDECESSOR, TIMELOCK_CONFIG_SEED, TIMELOCK_ID_PADDED, TIMELOCK_OPERATION_SEED, + TIMELOCK_SIGNER_SEED, }; use crate::error::TimelockError; use crate::event::*; @@ -16,6 +18,7 @@ use crate::state::{Config, InstructionData, Operation}; /// operation can be executed only if it's ready and all predecessors are done pub fn execute_batch<'info>( ctx: Context<'_, '_, '_, 'info, ExecuteBatch<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], _id: [u8; 32], ) -> Result<()> { let op = &mut ctx.accounts.operation; @@ -27,7 +30,11 @@ pub fn execute_batch<'info>( if op.predecessor != EMPTY_PREDECESSOR { // force predecessor to be provided let (expected_address, _) = Pubkey::find_program_address( - &[TIMELOCK_OPERATION_SEED, op.predecessor.as_ref()], + &[ + TIMELOCK_OPERATION_SEED, + timelock_id.as_ref(), + op.predecessor.as_ref(), + ], ctx.program_id, ); @@ -48,7 +55,11 @@ pub fn execute_batch<'info>( ); } - let seeds = &[TIMELOCK_SIGNER_SEED, &[ctx.bumps.timelock_signer]]; + let seeds = &[ + TIMELOCK_SIGNER_SEED, + timelock_id.as_ref(), + &[ctx.bumps.timelock_signer], + ]; let signer = &[&seeds[..]]; for (i, instruction_data) in op.instructions.iter().enumerate() { @@ -79,11 +90,16 @@ pub fn execute_batch<'info>( /// bypasser_execute also need the operation to be uploaded formerly pub fn bypasser_execute_batch<'info>( ctx: Context<'_, '_, '_, 'info, BypasserExecuteBatch<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], _id: [u8; 32], ) -> Result<()> { let op = &mut ctx.accounts.operation; - let seeds = &[TIMELOCK_SIGNER_SEED, &[ctx.bumps.timelock_signer]]; + let seeds = &[ + TIMELOCK_SIGNER_SEED, + timelock_id.as_ref(), + &[ctx.bumps.timelock_signer], + ]; let signer = &[&seeds[..]]; for (i, instruction_data) in op.instructions.iter().enumerate() { @@ -127,11 +143,11 @@ fn execute( } #[derive(Accounts)] -#[instruction(id: [u8; 32])] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; HASH_BYTES])] pub struct ExecuteBatch<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, constraint = operation.is_scheduled() @ TimelockError::InvalidId, )] @@ -140,12 +156,12 @@ pub struct ExecuteBatch<'info> { /// CHECK: Will be validated in handler if predecessor exists pub predecessor_operation: UncheckedAccount<'info>, - #[account( seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account( seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref(),], bump)] pub config: Account<'info, Config>, /// CHECK: program signer PDA that can hold balance #[account( - seeds = [TIMELOCK_SIGNER_SEED], + seeds = [TIMELOCK_SIGNER_SEED, timelock_id.as_ref()], bump )] pub timelock_signer: UncheckedAccount<'info>, @@ -158,22 +174,22 @@ pub struct ExecuteBatch<'info> { } #[derive(Accounts)] -#[instruction(id: [u8; 32])] +#[instruction(timelock_id: [u8; 32], id: [u8; 32])] pub struct BypasserExecuteBatch<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, constraint = operation.is_finalized @ TimelockError::OperationNotFinalized, )] pub operation: Account<'info, Operation>, - #[account( seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account( seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref(),], bump)] pub config: Account<'info, Config>, /// CHECK: program signer PDA that can hold balance #[account( - seeds = [TIMELOCK_SIGNER_SEED], + seeds = [TIMELOCK_SIGNER_SEED, timelock_id.as_ref()], bump )] pub timelock_signer: UncheckedAccount<'info>, diff --git a/chains/solana/contracts/programs/timelock/src/instructions/initialize.rs b/chains/solana/contracts/programs/timelock/src/instructions/initialize.rs index 4aabf199a..bc3cd2df1 100644 --- a/chains/solana/contracts/programs/timelock/src/instructions/initialize.rs +++ b/chains/solana/contracts/programs/timelock/src/instructions/initialize.rs @@ -2,17 +2,21 @@ use anchor_lang::prelude::*; use access_controller::AccessController; -use crate::constants::{ANCHOR_DISCRIMINATOR, TIMELOCK_CONFIG_SEED}; -use crate::error::AuthError; +use crate::constants::{ANCHOR_DISCRIMINATOR, TIMELOCK_CONFIG_SEED, TIMELOCK_ID_PADDED}; +use crate::error::{AuthError, TimelockError}; use crate::program::Timelock; use crate::state::{Config, Role}; -use crate::TimelockError; /// initialize Timelock config with owner(admin), /// role access controller keys and global configuration value. -pub fn initialize(ctx: Context, min_delay: u64) -> Result<()> { +pub fn initialize( + ctx: Context, + timelock_id: [u8; TIMELOCK_ID_PADDED], + min_delay: u64, +) -> Result<()> { // assign owner(owner is admin) let config = &mut ctx.accounts.config; + config.timelock_id = timelock_id; config.owner = ctx.accounts.authority.key(); config.min_delay = min_delay; @@ -29,6 +33,7 @@ pub fn initialize(ctx: Context, min_delay: u64) -> Result<()> { /// tested with up to 24 addresses per each transaction. pub fn batch_add_access<'info>( ctx: Context<'_, '_, '_, 'info, BatchAddAccess<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], _role: Role, ) -> Result<()> { require!( @@ -52,11 +57,12 @@ pub fn batch_add_access<'info>( } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct Initialize<'info> { #[account( init, space = ANCHOR_DISCRIMINATOR + Config::INIT_SPACE, - seeds = [TIMELOCK_CONFIG_SEED], + seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump, payer = authority, )] @@ -86,10 +92,10 @@ pub struct Initialize<'info> { } #[derive(Accounts)] -#[instruction(role: Role)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], role: Role)] pub struct BatchAddAccess<'info> { #[account( - seeds = [TIMELOCK_CONFIG_SEED], + seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump, )] pub config: Account<'info, Config>, diff --git a/chains/solana/contracts/programs/timelock/src/instructions/schedule.rs b/chains/solana/contracts/programs/timelock/src/instructions/schedule.rs index dc072e3b6..43604437c 100644 --- a/chains/solana/contracts/programs/timelock/src/instructions/schedule.rs +++ b/chains/solana/contracts/programs/timelock/src/instructions/schedule.rs @@ -2,7 +2,9 @@ use anchor_lang::prelude::*; use access_controller::AccessController; -use crate::constants::{ANCHOR_DISCRIMINATOR, TIMELOCK_CONFIG_SEED, TIMELOCK_OPERATION_SEED}; +use crate::constants::{ + ANCHOR_DISCRIMINATOR, TIMELOCK_CONFIG_SEED, TIMELOCK_ID_PADDED, TIMELOCK_OPERATION_SEED, +}; use crate::error::{AuthError, TimelockError}; use crate::event::*; use crate::state::{Config, InstructionData, Operation}; @@ -11,6 +13,7 @@ use crate::state::{Config, InstructionData, Operation}; /// Operation account should be preloaded with instructions and finalized before scheduling pub fn schedule_batch<'info>( ctx: Context<'_, '_, '_, 'info, ScheduleBatch<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], _id: [u8; 32], delay: u64, ) -> Result<()> { @@ -32,16 +35,16 @@ pub fn schedule_batch<'info>( op.timestamp = scheduled_time; for (i, ix) in op.instructions.iter().enumerate() { + // check for 8-byte Anchor discriminator (since our internally developed programs use Anchor) + // non-Anchor instructions may have different/empty data formats and are allowed if ix.data.len() >= ANCHOR_DISCRIMINATOR { - let selector: [u8; ANCHOR_DISCRIMINATOR] = // extract the first 8 bytes from ix.data as the selector - ix.data[..ANCHOR_DISCRIMINATOR].try_into().unwrap(); + let selector: [u8; ANCHOR_DISCRIMINATOR] = + ix.data[..ANCHOR_DISCRIMINATOR].try_into().unwrap(); if config.blocked_selectors.is_blocked(&selector) { return err!(TimelockError::BlockedSelector); } - } else { - // todo: in discussion (allow empty data) } emit!(CallScheduled { @@ -66,6 +69,7 @@ pub fn schedule_batch<'info>( /// in a single execute_batch transaction ensuring atomicy. pub fn initialize_operation<'info>( ctx: Context<'_, '_, '_, 'info, InitializeOperation<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], predecessor: [u8; 32], salt: [u8; 32], @@ -90,6 +94,7 @@ pub fn initialize_operation<'info>( /// append instructions to the operation pub fn append_instructions<'info>( ctx: Context<'_, '_, '_, 'info, AppendInstructions<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], _id: [u8; 32], instructions_batch: Vec, ) -> Result<()> { @@ -103,6 +108,7 @@ pub fn append_instructions<'info>( /// verify the operation status and id before mark it as finalized pub fn finalize_operation<'info>( ctx: Context<'_, '_, '_, 'info, FinalizeOperation<'info>>, + _timelock_id: [u8; TIMELOCK_ID_PADDED], _id: [u8; 32], ) -> Result<()> { let op = &mut ctx.accounts.operation; @@ -111,27 +117,29 @@ pub fn finalize_operation<'info>( Ok(()) } -pub fn clear_operation(_ctx: Context, _id: [u8; 32]) -> Result<()> { +pub fn clear_operation( + _ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], + _id: [u8; 32], +) -> Result<()> { // NOTE: ctx.accounts.operation is closed to be able to re-initialized, // also allow finalized operation to be cleared Ok(()) } #[derive(Accounts)] -#[instruction( - id: [u8; 32], -)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32])] pub struct ScheduleBatch<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, constraint = operation.is_finalized @ TimelockError::OperationNotFinalized, constraint = !operation.is_scheduled() @ TimelockError::OperationAlreadyScheduled )] pub operation: Box>, - #[account( seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // NOTE: access controller check and access happens in only_role_or_admin_role macro @@ -143,6 +151,7 @@ pub struct ScheduleBatch<'info> { #[derive(Accounts)] #[instruction( + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], predecessor: [u8; 32], salt: [u8; 32], @@ -151,7 +160,7 @@ pub struct ScheduleBatch<'info> { pub struct InitializeOperation<'info> { #[account( init, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, payer = authority, space = ANCHOR_DISCRIMINATOR + Operation::INIT_SPACE, @@ -159,7 +168,7 @@ pub struct InitializeOperation<'info> { )] pub operation: Account<'info, Operation>, - #[account(seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, #[account(mut)] @@ -169,11 +178,11 @@ pub struct InitializeOperation<'info> { } #[derive(Accounts)] -#[instruction(id: [u8; 32], instructions_batch: Vec)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], instructions_batch: Vec)] pub struct AppendInstructions<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, realloc = ANCHOR_DISCRIMINATOR + Operation::INIT_SPACE + @@ -191,7 +200,7 @@ pub struct AppendInstructions<'info> { )] pub operation: Account<'info, Operation>, - #[account(seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, #[account( @@ -207,11 +216,11 @@ pub struct AppendInstructions<'info> { } #[derive(Accounts)] -#[instruction(id: [u8; 32])] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32])] pub struct FinalizeOperation<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, constraint = !operation.is_finalized @ TimelockError::OperationAlreadyFinalized, constraint = !operation.is_scheduled() @ TimelockError::OperationAlreadyScheduled, @@ -220,7 +229,7 @@ pub struct FinalizeOperation<'info> { )] pub operation: Account<'info, Operation>, - #[account(seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, #[account( @@ -234,18 +243,18 @@ pub struct FinalizeOperation<'info> { } #[derive(Accounts)] -#[instruction(id: [u8; 32])] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32])] pub struct ClearOperation<'info> { #[account( mut, - seeds = [TIMELOCK_OPERATION_SEED, id.as_ref()], + seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()], bump, close = authority, constraint = !operation.is_scheduled() @ TimelockError::OperationAlreadyScheduled, // restrict clearing of scheduled operation )] pub operation: Account<'info, Operation>, - #[account(seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, #[account( diff --git a/chains/solana/contracts/programs/timelock/src/lib.rs b/chains/solana/contracts/programs/timelock/src/lib.rs index fefe8d11b..56d975356 100644 --- a/chains/solana/contracts/programs/timelock/src/lib.rs +++ b/chains/solana/contracts/programs/timelock/src/lib.rs @@ -26,85 +26,102 @@ pub mod timelock { use super::*; - pub fn initialize(ctx: Context, min_delay: u64) -> Result<()> { - initialize::initialize(ctx, min_delay) + pub fn initialize( + ctx: Context, + timelock_id: [u8; TIMELOCK_ID_PADDED], + min_delay: u64, + ) -> Result<()> { + initialize::initialize(ctx, timelock_id, min_delay) } #[access_control(only_admin!(ctx))] pub fn batch_add_access<'info>( ctx: Context<'_, '_, '_, 'info, BatchAddAccess<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], role: Role, ) -> Result<()> { - initialize::batch_add_access(ctx, role) + initialize::batch_add_access(ctx, timelock_id, role) } #[access_control(only_role_or_admin_role!(ctx, Role::Proposer))] pub fn schedule_batch<'info>( ctx: Context<'_, '_, '_, 'info, ScheduleBatch<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], delay: u64, ) -> Result<()> { - schedule::schedule_batch(ctx, id, delay) + schedule::schedule_batch(ctx, timelock_id, id, delay) } pub fn initialize_operation<'info>( ctx: Context<'_, '_, '_, 'info, InitializeOperation<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], predecessor: [u8; 32], salt: [u8; 32], instruction_count: u32, ) -> Result<()> { - schedule::initialize_operation(ctx, id, predecessor, salt, instruction_count) + schedule::initialize_operation(ctx, timelock_id, id, predecessor, salt, instruction_count) } pub fn append_instructions<'info>( ctx: Context<'_, '_, '_, 'info, AppendInstructions<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], instructions_batch: Vec, ) -> Result<()> { - schedule::append_instructions(ctx, id, instructions_batch) + schedule::append_instructions(ctx, timelock_id, id, instructions_batch) } pub fn clear_operation<'info>( ctx: Context<'_, '_, '_, 'info, ClearOperation<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], ) -> Result<()> { - schedule::clear_operation(ctx, id) + schedule::clear_operation(ctx, timelock_id, id) } pub fn finalize_operation<'info>( ctx: Context<'_, '_, '_, 'info, FinalizeOperation<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], ) -> Result<()> { - schedule::finalize_operation(ctx, id) + schedule::finalize_operation(ctx, timelock_id, id) } #[access_control(only_role_or_admin_role!(ctx, Role::Canceller))] pub fn cancel<'info>( ctx: Context<'_, '_, '_, 'info, Cancel<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], // precalculated id of the tx(instructions) ) -> Result<()> { - cancel::cancel(ctx, id) + cancel::cancel(ctx, timelock_id, id) } #[access_control(only_role_or_admin_role!(ctx, Role::Executor))] pub fn execute_batch<'info>( ctx: Context<'_, '_, '_, 'info, ExecuteBatch<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], ) -> Result<()> { - execute::execute_batch(ctx, id) + execute::execute_batch(ctx, timelock_id, id) } #[access_control(only_role_or_admin_role!(ctx, Role::Bypasser))] pub fn bypasser_execute_batch<'info>( ctx: Context<'_, '_, '_, 'info, BypasserExecuteBatch<'info>>, + timelock_id: [u8; TIMELOCK_ID_PADDED], id: [u8; 32], ) -> Result<()> { - execute::bypasser_execute_batch(ctx, id) + execute::bypasser_execute_batch(ctx, timelock_id, id) } #[access_control(only_admin!(ctx))] - pub fn update_delay(ctx: Context, delay: u64) -> Result<()> { + pub fn update_delay( + ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], + delay: u64, + ) -> Result<()> { let config = &mut ctx.accounts.config; require!(delay > 0, TimelockError::InvalidInput); emit!(MinDelayChange { @@ -118,6 +135,7 @@ pub mod timelock { #[access_control(only_admin!(ctx))] pub fn block_function_selector( ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], selector: [u8; 8], ) -> Result<()> { let config = &mut ctx.accounts.config; @@ -129,6 +147,7 @@ pub mod timelock { #[access_control(only_admin!(ctx))] pub fn unblock_function_selector( ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], selector: [u8; 8], ) -> Result<()> { let config = &mut ctx.accounts.config; @@ -140,6 +159,7 @@ pub mod timelock { #[access_control(only_admin!(ctx))] pub fn transfer_ownership( ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], proposed_owner: Pubkey, ) -> Result<()> { let config = &mut ctx.accounts.config; @@ -148,7 +168,10 @@ pub mod timelock { Ok(()) } - pub fn accept_ownership(ctx: Context) -> Result<()> { + pub fn accept_ownership( + ctx: Context, + _timelock_id: [u8; TIMELOCK_ID_PADDED], + ) -> Result<()> { ctx.accounts.config.owner = std::mem::take(&mut ctx.accounts.config.proposed_owner); ctx.accounts.config.proposed_owner = Pubkey::zeroed(); Ok(()) @@ -156,40 +179,45 @@ pub mod timelock { } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct TransferOwnership<'info> { - #[account(mut, seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(mut, seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // owner(admin) only, access control with only_admin macro pub authority: Signer<'info>, } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct AcceptOwnership<'info> { - #[account(mut, seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(mut, seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, #[account(address = config.proposed_owner @ AuthError::Unauthorized)] pub authority: Signer<'info>, } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct UpdateDelay<'info> { - #[account(mut, seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(mut, seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // owner(admin) only, access control with only_admin macro pub authority: Signer<'info>, } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct BlockFunctionSelector<'info> { - #[account(mut, seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(mut, seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // owner(admin) only, access control with only_admin macro pub authority: Signer<'info>, } #[derive(Accounts)] +#[instruction(timelock_id: [u8; TIMELOCK_ID_PADDED])] pub struct UnblockFunctionSelector<'info> { - #[account(mut, seeds = [TIMELOCK_CONFIG_SEED], bump)] + #[account(mut, seeds = [TIMELOCK_CONFIG_SEED, timelock_id.as_ref()], bump)] pub config: Account<'info, Config>, // owner(admin) only, access control with only_admin macro pub authority: Signer<'info>, diff --git a/chains/solana/contracts/programs/timelock/src/state/config.rs b/chains/solana/contracts/programs/timelock/src/state/config.rs index f60b25290..467702cc2 100644 --- a/chains/solana/contracts/programs/timelock/src/state/config.rs +++ b/chains/solana/contracts/programs/timelock/src/state/config.rs @@ -4,7 +4,7 @@ use std::mem; use arrayvec::arrayvec; -use crate::constants::MAX_SELECTORS; +use crate::constants::{MAX_SELECTORS, TIMELOCK_ID_PADDED}; use crate::error::TimelockError; #[derive(AnchorSerialize, AnchorDeserialize, Debug, Clone, PartialEq)] @@ -19,6 +19,8 @@ pub enum Role { #[account] #[derive(InitSpace)] pub struct Config { + pub timelock_id: [u8; TIMELOCK_ID_PADDED], + pub owner: Pubkey, pub proposed_owner: Pubkey, diff --git a/chains/solana/contracts/target/idl/mcm.json b/chains/solana/contracts/target/idl/mcm.json index fa7adb61c..617746dc5 100644 --- a/chains/solana/contracts/target/idl/mcm.json +++ b/chains/solana/contracts/target/idl/mcm.json @@ -3,14 +3,14 @@ "name": "mcm", "docs": [ "This is mcm program supporting multiple instances of multisig configuration", - "A single deployed program manages multiple multisig states(configurations) identified by multisig_name" + "A single deployed program manages multiple multisig states(configurations) identified by multisig_id" ], "instructions": [ { "name": "initialize", "docs": [ - "initialize a new multisig configuration, store the chain_id and multisig_name", - "multisig_name is a unique identifier for the multisig configuration(32 bytes, left-padded)" + "initialize a new multisig configuration, store the chain_id and multisig_id", + "multisig_id is a unique identifier for the multisig configuration(32 bytes, left-padded)" ], "accounts": [ { @@ -55,7 +55,7 @@ "type": "u64" }, { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -81,7 +81,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -111,7 +111,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -157,7 +157,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -234,7 +234,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -310,7 +310,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -369,7 +369,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -404,7 +404,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -446,7 +446,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -477,7 +477,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -508,7 +508,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -551,7 +551,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -598,7 +598,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -637,7 +637,7 @@ ], "args": [ { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", @@ -699,7 +699,7 @@ "type": "u64" }, { - "name": "multisigName", + "name": "multisigId", "type": { "array": [ "u8", diff --git a/chains/solana/contracts/target/idl/timelock.json b/chains/solana/contracts/target/idl/timelock.json index d9e5f1a20..3bd51e472 100644 --- a/chains/solana/contracts/target/idl/timelock.json +++ b/chains/solana/contracts/target/idl/timelock.json @@ -57,6 +57,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "minDelay", "type": "u64" @@ -88,6 +97,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "role", "type": { @@ -121,6 +139,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -161,6 +188,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -219,6 +255,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -258,6 +303,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -289,6 +343,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -325,6 +388,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -371,6 +443,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -412,6 +493,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "id", "type": { @@ -438,6 +528,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "delay", "type": "u64" @@ -459,6 +558,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "selector", "type": { @@ -485,6 +593,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "selector", "type": { @@ -511,6 +628,15 @@ } ], "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "proposedOwner", "type": "publicKey" @@ -531,7 +657,17 @@ "isSigner": true } ], - "args": [] + "args": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] } ], "accounts": [ @@ -540,6 +676,15 @@ "type": { "kind": "struct", "fields": [ + { + "name": "timelockId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "owner", "type": "publicKey" @@ -653,7 +798,7 @@ 8 ] }, - 32 + 128 ] } }, @@ -758,9 +903,6 @@ { "name": "SelectorNotFound" }, - { - "name": "InvalidInstructionData" - }, { "name": "MaxCapacityReached" } diff --git a/chains/solana/contracts/tests/config/mcm_config.go b/chains/solana/contracts/tests/config/mcm_config.go index c7e0efcce..e357b1daa 100644 --- a/chains/solana/contracts/tests/config/mcm_config.go +++ b/chains/solana/contracts/tests/config/mcm_config.go @@ -24,7 +24,7 @@ var ( } // [0,0,0,...'t','e','s','t','-','m','c','m',] - TestMsigNamePaddedBuffer = [32]byte{ + TestMsigID = [32]byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x6d, 0x63, 0x6d, } MaxNumSigners = 180 diff --git a/chains/solana/contracts/tests/config/timelock_config.go b/chains/solana/contracts/tests/config/timelock_config.go index b336c9318..c3e71b6c0 100644 --- a/chains/solana/contracts/tests/config/timelock_config.go +++ b/chains/solana/contracts/tests/config/timelock_config.go @@ -5,15 +5,11 @@ import ( ) var ( - TimelockProgram = solana.MustPublicKeyFromBase58("LoCoNsJFuhTkSQjfdDfn3yuwqhSYoPujmviRHVCzsqn") - TimelockConfigPDA, _, _ = solana.FindProgramAddress([][]byte{[]byte("timelock_config")}, TimelockProgram) - TimelockSignerPDA, _, _ = solana.FindProgramAddress([][]byte{[]byte("timelock_signer")}, TimelockProgram) - TimelockOperationPDA = func(id [32]byte) solana.PublicKey { - pda, _, _ := solana.FindProgramAddress([][]byte{ - []byte("timelock_operation"), - id[:], - }, TimelockProgram) - return pda + TimelockProgram = solana.MustPublicKeyFromBase58("LoCoNsJFuhTkSQjfdDfn3yuwqhSYoPujmviRHVCzsqn") + + // [0,0,0,...'t','e','s','t','-','t','i','m','e','l','o','c','k'] + TestTimelockID = [32]byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x6c, 0x6f, 0x63, 0x6b, } NumAccountsPerRole = 63 // max 64 accounts per role(access list) * 4 - 1(to keep test accounts fits single funding) BatchAddAccessChunkSize = 24 @@ -23,5 +19,5 @@ var ( TimelockEmptyOpID = [32]byte{} TimelockOpDoneTimestamp = uint64(1) - MaxFunctionSelectorLen = 32 // tested with 128, but for test time consideration, keeping at 32 + MaxFunctionSelectorLen = 128 ) diff --git a/chains/solana/contracts/tests/mcms/mcm_multiple_multisigs_test.go b/chains/solana/contracts/tests/mcms/mcm_multiple_instances_test.go similarity index 89% rename from chains/solana/contracts/tests/mcms/mcm_multiple_multisigs_test.go rename to chains/solana/contracts/tests/mcms/mcm_multiple_instances_test.go index 88db05fb1..9ed130ffd 100644 --- a/chains/solana/contracts/tests/mcms/mcm_multiple_multisigs_test.go +++ b/chains/solana/contracts/tests/mcms/mcm_multiple_instances_test.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" ) -func TestMcmMultipleMultisigs(t *testing.T) { +func TestMcmMultipleInstances(t *testing.T) { t.Parallel() mcm.SetProgramID(config.McmProgram) @@ -31,20 +31,20 @@ func TestMcmMultipleMultisigs(t *testing.T) { solanaGoClient := testutils.DeployAllPrograms(t, testutils.PathToAnchorConfig, admin) // mcm multisig 1 - testMsigName1, err := mcms.PadString32("test_mcm_instance_1") + testMsigID1, err := mcms.PadString32("test_mcm_instance_1") require.NoError(t, err) - multisigConfigPDA1 := mcms.McmConfigAddress(testMsigName1) - rootMetadataPDA1 := mcms.RootMetadataAddress(testMsigName1) - expiringRootAndOpCountPDA1 := mcms.ExpiringRootAndOpCountAddress(testMsigName1) - configSignersPDA1 := mcms.McmConfigSignersAddress(testMsigName1) + multisigConfigPDA1 := mcms.GetConfigPDA(testMsigID1) + rootMetadataPDA1 := mcms.GetRootMetadataPDA(testMsigID1) + expiringRootAndOpCountPDA1 := mcms.GetExpiringRootAndOpCountPDA(testMsigID1) + configSignersPDA1 := mcms.GetConfigSignersPDA(testMsigID1) // mcm multisig 2 - testMsigName2, err := mcms.PadString32("test_mcm_instance_2") + testMsigID2, err := mcms.PadString32("test_mcm_instance_2") require.NoError(t, err) - multisigConfigPDA2 := mcms.McmConfigAddress(testMsigName2) - rootMetadataPDA2 := mcms.RootMetadataAddress(testMsigName2) - expiringRootAndOpCountPDA2 := mcms.ExpiringRootAndOpCountAddress(testMsigName2) - configSignersPDA2 := mcms.McmConfigSignersAddress(testMsigName2) + multisigConfigPDA2 := mcms.GetConfigPDA(testMsigID2) + rootMetadataPDA2 := mcms.GetRootMetadataPDA(testMsigID2) + expiringRootAndOpCountPDA2 := mcms.GetExpiringRootAndOpCountPDA(testMsigID2) + configSignersPDA2 := mcms.GetConfigSignersPDA(testMsigID2) t.Run("setup:funding", func(t *testing.T) { testutils.FundAccounts(ctx, []solana.PrivateKey{admin}, solanaGoClient, t) @@ -67,7 +67,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { ix, err := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName1, + testMsigID1, multisigConfigPDA1, admin.PublicKey(), solana.SystemProgramID, @@ -103,7 +103,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { groupParents := []uint8{0, 0, 0, 2, 0, 0, 0, 0, 0, 0} mcmConfig, err := mcms.NewValidMcmConfig( - testMsigName1, + testMsigID1, signerPrivateKeys, signerGroups, groupQuorums, @@ -115,7 +115,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { signerAddresses := mcmConfig.SignerAddresses t.Run("mcm:set_config: preload signers on PDA", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName1, multisigConfigPDA1, configSignersPDA1, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID1, multisigConfigPDA1, configSignersPDA1, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -136,7 +136,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { t.Run("success:set_config", func(t *testing.T) { ix, err := mcm.NewSetConfigInstruction( - testMsigName1, + testMsigID1, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -191,7 +191,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { ix, err := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName2, + testMsigID2, multisigConfigPDA2, admin.PublicKey(), solana.SystemProgramID, @@ -226,7 +226,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { groupParents := []uint8{0, 0, 0, 2, 0, 0, 0, 0, 0, 0} mcmConfig, err := mcms.NewValidMcmConfig( - testMsigName2, + testMsigID2, signerPrivateKeys, signerGroups, groupQuorums, @@ -238,7 +238,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { signerAddresses := mcmConfig.SignerAddresses t.Run("mcm:set_config: preload signers on PDA", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName2, multisigConfigPDA2, configSignersPDA2, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID2, multisigConfigPDA2, configSignersPDA2, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -259,7 +259,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { t.Run("fail:set_config with invalid seeds", func(t *testing.T) { ix, err := mcm.NewSetConfigInstruction( - testMsigName1, + testMsigID1, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -280,7 +280,7 @@ func TestMcmMultipleMultisigs(t *testing.T) { t.Run("success:set_config", func(t *testing.T) { ix, err := mcm.NewSetConfigInstruction( - testMsigName2, + testMsigID2, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, diff --git a/chains/solana/contracts/tests/mcms/mcm_set_config_test.go b/chains/solana/contracts/tests/mcms/mcm_set_config_test.go index 9a7f8355c..86b211f0d 100644 --- a/chains/solana/contracts/tests/mcms/mcm_set_config_test.go +++ b/chains/solana/contracts/tests/mcms/mcm_set_config_test.go @@ -39,13 +39,13 @@ func TestMcmSetConfig(t *testing.T) { solanaGoClient := testutils.DeployAllPrograms(t, testutils.PathToAnchorConfig, admin) // mcm name - testMsigName := config.TestMsigNamePaddedBuffer + testMsigID := config.TestMsigID // test mcm pdas - multisigConfigPDA := mcms.McmConfigAddress(testMsigName) - rootMetadataPDA := mcms.RootMetadataAddress(testMsigName) - expiringRootAndOpCountPDA := mcms.ExpiringRootAndOpCountAddress(testMsigName) - configSignersPDA := mcms.McmConfigSignersAddress(testMsigName) + multisigConfigPDA := mcms.GetConfigPDA(testMsigID) + rootMetadataPDA := mcms.GetRootMetadataPDA(testMsigID) + expiringRootAndOpCountPDA := mcms.GetExpiringRootAndOpCountPDA(testMsigID) + configSignersPDA := mcms.GetConfigSignersPDA(testMsigID) t.Run("setup:funding", func(t *testing.T) { testutils.FundAccounts(ctx, []solana.PrivateKey{admin, anotherAdmin, user}, solanaGoClient, t) @@ -67,7 +67,7 @@ func TestMcmSetConfig(t *testing.T) { ix, err := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName, + testMsigID, multisigConfigPDA, admin.PublicKey(), solana.SystemProgramID, @@ -91,7 +91,7 @@ func TestMcmSetConfig(t *testing.T) { t.Run("mcm:ownership", func(t *testing.T) { // Fail to transfer ownership when not owner instruction, err := mcm.NewTransferOwnershipInstruction( - testMsigName, + testMsigID, anotherAdmin.PublicKey(), multisigConfigPDA, user.PublicKey(), @@ -102,7 +102,7 @@ func TestMcmSetConfig(t *testing.T) { // successfully transfer ownership instruction, err = mcm.NewTransferOwnershipInstruction( - testMsigName, + testMsigID, anotherAdmin.PublicKey(), multisigConfigPDA, admin.PublicKey(), @@ -113,7 +113,7 @@ func TestMcmSetConfig(t *testing.T) { // Fail to accept ownership when not proposed_owner instruction, err = mcm.NewAcceptOwnershipInstruction( - testMsigName, + testMsigID, multisigConfigPDA, user.PublicKey(), ).ValidateAndBuild() @@ -124,7 +124,7 @@ func TestMcmSetConfig(t *testing.T) { // Successfully accept ownership // anotherAdmin becomes owner for remaining tests instruction, err = mcm.NewAcceptOwnershipInstruction( - testMsigName, + testMsigID, multisigConfigPDA, anotherAdmin.PublicKey(), ).ValidateAndBuild() @@ -134,7 +134,7 @@ func TestMcmSetConfig(t *testing.T) { // Current owner cannot propose self instruction, err = mcm.NewTransferOwnershipInstruction( - testMsigName, + testMsigID, anotherAdmin.PublicKey(), multisigConfigPDA, anotherAdmin.PublicKey(), @@ -154,7 +154,7 @@ func TestMcmSetConfig(t *testing.T) { // get it back instruction, err = mcm.NewTransferOwnershipInstruction( - testMsigName, + testMsigID, admin.PublicKey(), multisigConfigPDA, anotherAdmin.PublicKey(), @@ -164,7 +164,7 @@ func TestMcmSetConfig(t *testing.T) { require.NotNil(t, result) instruction, err = mcm.NewAcceptOwnershipInstruction( - testMsigName, + testMsigID, multisigConfigPDA, admin.PublicKey(), ).ValidateAndBuild() @@ -196,7 +196,7 @@ func TestMcmSetConfig(t *testing.T) { groupParents := []uint8{0, 0, 0, 2, 0, 0, 0, 0, 0, 0} mcmConfig, err := mcms.NewValidMcmConfig( - testMsigName, + testMsigID, signerPrivateKeys, signerGroups, groupQuorums, @@ -208,7 +208,7 @@ func TestMcmSetConfig(t *testing.T) { signerAddresses := mcmConfig.SignerAddresses t.Run("mcm:set_config: preload signers on PDA", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -230,7 +230,7 @@ func TestMcmSetConfig(t *testing.T) { t.Run("mcm:set_config:admin authorization", func(t *testing.T) { t.Run("fail:set_config from unauthorized user", func(t *testing.T) { ix, err := mcm.NewSetConfigInstruction( - mcmConfig.MultisigName, + mcmConfig.MultisigID, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -251,7 +251,7 @@ func TestMcmSetConfig(t *testing.T) { t.Run("success:set_config from admin", func(t *testing.T) { // set config ix, err := mcm.NewSetConfigInstruction( - mcmConfig.MultisigName, + mcmConfig.MultisigID, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -323,7 +323,7 @@ func TestMcmSetConfig(t *testing.T) { groupParents := []uint8{0, 0, 0, 2, 0, 0, 0, 0, 0, 0} mcmConfig, err := mcms.NewValidMcmConfig( - testMsigName, + testMsigID, signerPrivateKeys, signerGroups, groupQuorums, @@ -337,12 +337,10 @@ func TestMcmSetConfig(t *testing.T) { t.Run("mcm:set_config: preload signers on PDA", func(t *testing.T) { // ConfigSignersPDA should be closed before reinitializing testutils.AssertClosedAccount(ctx, t, solanaGoClient, configSignersPDA, config.DefaultCommitment) - - parsedTotalSigners, err := mcms.SafeToUint8(len(signerAddresses)) - require.NoError(t, err) - + //nolint:gosec + parsedTotalSigners := uint8(len(signerAddresses)) initSignersIx, err := mcm.NewInitSignersInstruction( - testMsigName, + testMsigID, parsedTotalSigners, multisigConfigPDA, configSignersPDA, @@ -353,7 +351,7 @@ func TestMcmSetConfig(t *testing.T) { require.NoError(t, err) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initSignersIx}, admin, config.DefaultCommitment) - appendSignersIxs, err := mcms.AppendSignersIxs(signerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + appendSignersIxs, err := mcms.GetAppendSignersIxs(signerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, err) // partially register signers @@ -363,7 +361,7 @@ func TestMcmSetConfig(t *testing.T) { // clear signers(this closes the account) clearIx, err := mcm.NewClearSignersInstruction( - testMsigName, + testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), @@ -374,7 +372,7 @@ func TestMcmSetConfig(t *testing.T) { testutils.AssertClosedAccount(ctx, t, solanaGoClient, configSignersPDA, config.DefaultCommitment) // preload signers again - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -395,7 +393,7 @@ func TestMcmSetConfig(t *testing.T) { t.Run("success:set_config", func(t *testing.T) { ix, err := mcm.NewSetConfigInstruction( - testMsigName, + testMsigID, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -519,14 +517,14 @@ func TestMcmSetConfig(t *testing.T) { t.Parallel() // use different msig accounts per test - failTestMsigName, err := mcms.PadString32(fmt.Sprintf("fail_test_%d", i)) + failTestMsigID, err := mcms.PadString32(fmt.Sprintf("fail_test_%d", i)) require.NoError(t, err) // test scope mcm pdas - failMultisigConfigPDA := mcms.McmConfigAddress(failTestMsigName) - failRootMetadataPDA := mcms.RootMetadataAddress(failTestMsigName) - failExpiringRootAndOpCountPDA := mcms.ExpiringRootAndOpCountAddress(failTestMsigName) - failConfigSignersPDA := mcms.McmConfigSignersAddress(failTestMsigName) + failMultisigConfigPDA := mcms.GetConfigPDA(failTestMsigID) + failRootMetadataPDA := mcms.GetRootMetadataPDA(failTestMsigID) + failExpiringRootAndOpCountPDA := mcms.GetExpiringRootAndOpCountPDA(failTestMsigID) + failConfigSignersPDA := mcms.GetConfigSignersPDA(failTestMsigID) t.Run(fmt.Sprintf("msig initialization:%s", tt.name), func(t *testing.T) { // get program data account @@ -545,7 +543,7 @@ func TestMcmSetConfig(t *testing.T) { // initialize msig ix, initIxErr := mcm.NewInitializeInstruction( config.TestChainID, - failTestMsigName, + failTestMsigID, failMultisigConfigPDA, admin.PublicKey(), solana.SystemProgramID, @@ -559,7 +557,7 @@ func TestMcmSetConfig(t *testing.T) { }) cfg, err := mcms.NewValidMcmConfig( - failTestMsigName, + failTestMsigID, config.SignerPrivateKeys, config.SignerGroups, config.GroupQuorums, @@ -572,11 +570,10 @@ func TestMcmSetConfig(t *testing.T) { if tt.skipPreloadSigners { return } - parsedTotalSigners, parsingErr := mcms.SafeToUint8(len(cfg.SignerAddresses)) - require.NoError(t, parsingErr) - + //nolint:gosec + parsedTotalSigners := uint8(len(cfg.SignerAddresses)) initSignersIx, initSignersErr := mcm.NewInitSignersInstruction( - failTestMsigName, + failTestMsigID, parsedTotalSigners, failMultisigConfigPDA, failConfigSignersPDA, @@ -587,7 +584,7 @@ func TestMcmSetConfig(t *testing.T) { require.NoError(t, initSignersErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initSignersIx}, admin, config.DefaultCommitment) - appendSignersIxs, appendSignersIxsErr := mcms.AppendSignersIxs(cfg.SignerAddresses, failTestMsigName, failMultisigConfigPDA, failConfigSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + appendSignersIxs, appendSignersIxsErr := mcms.GetAppendSignersIxs(cfg.SignerAddresses, failTestMsigID, failMultisigConfigPDA, failConfigSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, appendSignersIxsErr) for _, ix := range appendSignersIxs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) @@ -595,7 +592,7 @@ func TestMcmSetConfig(t *testing.T) { if !tt.skipFinalizeSigners { finalizeSignersIx, finSignersIxErr := mcm.NewFinalizeSignersInstruction( - failTestMsigName, + failTestMsigID, failMultisigConfigPDA, failConfigSignersPDA, admin.PublicKey(), @@ -621,7 +618,7 @@ func TestMcmSetConfig(t *testing.T) { tt.modifyConfig(cfg) ix, err := mcm.NewSetConfigInstruction( - cfg.MultisigName, + cfg.MultisigID, cfg.SignerGroups, cfg.GroupQuorums, cfg.GroupParents, @@ -725,14 +722,14 @@ func TestMcmSetConfig(t *testing.T) { t.Parallel() // use different msig accounts per test - failTestMsigName, err := mcms.PadString32(fmt.Sprintf("fail_preupload_signer_test_%d", i)) + failTestMsigID, err := mcms.PadString32(fmt.Sprintf("fail_preupload_signer_test_%d", i)) require.NoError(t, err) // test scope mcm pdas - failMultisigConfigPDA := mcms.McmConfigAddress(failTestMsigName) - failRootMetadataPDA := mcms.RootMetadataAddress(failTestMsigName) - failExpiringRootAndOpCountPDA := mcms.ExpiringRootAndOpCountAddress(failTestMsigName) - failConfigSignersPDA := mcms.McmConfigSignersAddress(failTestMsigName) + failMultisigConfigPDA := mcms.GetConfigPDA(failTestMsigID) + failRootMetadataPDA := mcms.GetRootMetadataPDA(failTestMsigID) + failExpiringRootAndOpCountPDA := mcms.GetExpiringRootAndOpCountPDA(failTestMsigID) + failConfigSignersPDA := mcms.GetConfigSignersPDA(failTestMsigID) t.Run(fmt.Sprintf("msig initialization:%s", tt.name), func(t *testing.T) { // get program data account @@ -751,7 +748,7 @@ func TestMcmSetConfig(t *testing.T) { // initialize msig ix, initIxErr := mcm.NewInitializeInstruction( config.TestChainID, - failTestMsigName, + failTestMsigID, failMultisigConfigPDA, admin.PublicKey(), solana.SystemProgramID, @@ -765,7 +762,7 @@ func TestMcmSetConfig(t *testing.T) { }) cfg, err := mcms.NewValidMcmConfig( - failTestMsigName, + failTestMsigID, config.SignerPrivateKeys, config.SignerGroups, config.GroupQuorums, @@ -781,10 +778,11 @@ func TestMcmSetConfig(t *testing.T) { if !tt.skipInitSigners { actualLength := len(cfg.SignerAddresses) - totalSigners, _ := mcms.SafeToUint8(actualLength + tt.totalSignersOffset) // offset for the test + //nolint:gosec + totalSigners := uint8(actualLength + tt.totalSignersOffset) // offset for the test initSignersIx, _ := mcm.NewInitSignersInstruction( - failTestMsigName, + failTestMsigID, totalSigners, failMultisigConfigPDA, failConfigSignersPDA, @@ -797,9 +795,9 @@ func TestMcmSetConfig(t *testing.T) { }) } - appendIxs, _ := mcms.AppendSignersIxs( + appendIxs, _ := mcms.GetAppendSignersIxs( cfg.SignerAddresses, - failTestMsigName, + failTestMsigID, failMultisigConfigPDA, failConfigSignersPDA, admin.PublicKey(), @@ -813,7 +811,7 @@ func TestMcmSetConfig(t *testing.T) { } finalizeIx, _ := mcm.NewFinalizeSignersInstruction( - failTestMsigName, + failTestMsigID, failMultisigConfigPDA, failConfigSignersPDA, admin.PublicKey(), diff --git a/chains/solana/contracts/tests/mcms/mcm_set_root_execute_test.go b/chains/solana/contracts/tests/mcms/mcm_set_root_execute_test.go index b09344d66..43ff55566 100644 --- a/chains/solana/contracts/tests/mcms/mcm_set_root_execute_test.go +++ b/chains/solana/contracts/tests/mcms/mcm_set_root_execute_test.go @@ -57,14 +57,14 @@ func TestMcmSetRootAndExecute(t *testing.T) { t.Run("mcm:general test cases", func(t *testing.T) { // mcm name - testMsigName := config.TestMsigNamePaddedBuffer + testMsigID := config.TestMsigID // test mcm pdas - multisigConfigPDA := mcms.McmConfigAddress(testMsigName) - rootMetadataPDA := mcms.RootMetadataAddress(testMsigName) - expiringRootAndOpCountPDA := mcms.ExpiringRootAndOpCountAddress(testMsigName) - configSignersPDA := mcms.McmConfigSignersAddress(testMsigName) - msigSignerPDA := mcms.McmSignerAddress(testMsigName) + multisigConfigPDA := mcms.GetConfigPDA(testMsigID) + rootMetadataPDA := mcms.GetRootMetadataPDA(testMsigID) + expiringRootAndOpCountPDA := mcms.GetExpiringRootAndOpCountPDA(testMsigID) + configSignersPDA := mcms.GetConfigSignersPDA(testMsigID) + msigSignerPDA := mcms.GetSignerPDA(testMsigID) // fund the signer pda fundPDAIx := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), msigSignerPDA).Build() @@ -95,7 +95,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { IsWritable: true, }, { - PublicKey: mcms.McmSignerAddress(config.TestMsigNamePaddedBuffer), + PublicKey: mcms.GetSignerPDA(config.TestMsigID), IsSigner: false, IsWritable: true, }, @@ -149,7 +149,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { IsWritable: true, }, { - PublicKey: mcms.McmSignerAddress(config.TestMsigNamePaddedBuffer), + PublicKey: mcms.GetSignerPDA(config.TestMsigID), IsSigner: false, IsWritable: true, }, @@ -185,7 +185,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { ix, initErr := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName, + testMsigID, multisigConfigPDA, user.PublicKey(), solana.SystemProgramID, @@ -215,7 +215,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { ix, initErr := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName, + testMsigID, multisigConfigPDA, admin.PublicKey(), solana.SystemProgramID, @@ -252,7 +252,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { groupParents := []uint8{0, 0, 0, 2, 0} mcmConfig, configErr := mcms.NewValidMcmConfig( - testMsigName, + testMsigID, signerPrivateKeys, signerGroups, groupQuorums, @@ -264,7 +264,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { signerAddresses := mcmConfig.SignerAddresses t.Run("mcm:preload signers", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -285,7 +285,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { // set config ix, configErr := mcm.NewSetConfigInstruction( - mcmConfig.MultisigName, + mcmConfig.MultisigID, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -346,7 +346,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { }, ) require.NoError(t, rvErr) - signaturesPDA := mcms.RootSignaturesAddress(testMsigName, rootValidationData.Root, validUntil) + signaturesPDA := mcms.GetRootSignaturesPDA(testMsigID, rootValidationData.Root, validUntil) t.Run("preload signatures", func(t *testing.T) { signers, getSignerErr := eth.GetEvmSigners(signerPrivateKeys) @@ -355,11 +355,10 @@ func TestMcmSetRootAndExecute(t *testing.T) { signatures, sigsErr := mcms.BulkSignOnMsgHash(signers, rootValidationData.EthMsgHash) require.NoError(t, sigsErr) - parsedTotalSigs, pErr := mcms.SafeToUint8(len(signatures)) - require.NoError(t, pErr) - + //nolint:gosec + parsedTotalSigs := uint8(len(signatures)) initSigsIx, isErr := mcm.NewInitSignaturesInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, parsedTotalSigs, @@ -371,7 +370,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { require.NoError(t, isErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initSigsIx}, admin, config.DefaultCommitment) - appendSigsIxs, asErr := mcms.AppendSignaturesIxs(signatures, testMsigName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + appendSigsIxs, asErr := mcms.GetAppendSignaturesIxs(signatures, testMsigID, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, asErr) // partially register signatures @@ -381,7 +380,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { // clear uploaded signatures(this closes the account) clearIx, cErr := mcm.NewClearSignaturesInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, signaturesPDA, @@ -393,7 +392,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { testutils.AssertClosedAccount(ctx, t, solanaGoClient, signaturesPDA, config.DefaultCommitment) // preload again - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, testMsigName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, testMsigID, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { @@ -414,14 +413,14 @@ func TestMcmSetRootAndExecute(t *testing.T) { }) newIx, setRootIxErr := mcm.NewSetRootInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, rootValidationData.Metadata, rootValidationData.MetadataProof, signaturesPDA, rootMetadataPDA, - mcms.SeenSignedHashesAddress(testMsigName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(testMsigID, rootValidationData.Root, validUntil), expiringRootAndOpCountPDA, multisigConfigPDA, admin.PublicKey(), @@ -479,7 +478,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { // new config with clear_root newMcmConfig, configErr := mcms.NewValidMcmConfig( - testMsigName, + testMsigID, config.SignerPrivateKeys, config.SignerGroups, config.GroupQuorums, @@ -491,7 +490,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { signerAddresses := newMcmConfig.SignerAddresses t.Run("preload signers", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(signerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(signerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -510,7 +509,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { t.Run("set_config with clear_root", func(t *testing.T) { ix, configErr := mcm.NewSetConfigInstruction( - newMcmConfig.MultisigName, + newMcmConfig.MultisigID, newMcmConfig.SignerGroups, newMcmConfig.GroupQuorums, newMcmConfig.GroupParents, @@ -606,7 +605,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { }, ) require.NoError(t, rvErr) - signaturesPDA := mcms.RootSignaturesAddress(testMsigName, rootValidationData.Root, validUntil) + signaturesPDA := mcms.GetRootSignaturesPDA(testMsigID, rootValidationData.Root, validUntil) t.Run("preload signatures", func(t *testing.T) { signers, getSignerErr := eth.GetEvmSigners(config.SignerPrivateKeys) @@ -615,7 +614,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { signatures, sigsErr := mcms.BulkSignOnMsgHash(signers, rootValidationData.EthMsgHash) require.NoError(t, sigsErr) - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, testMsigName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, testMsigID, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { @@ -636,14 +635,14 @@ func TestMcmSetRootAndExecute(t *testing.T) { }) newIx, setRootIxErr := mcm.NewSetRootInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, rootValidationData.Metadata, rootValidationData.MetadataProof, signaturesPDA, rootMetadataPDA, - mcms.SeenSignedHashesAddress(testMsigName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(testMsigID, rootValidationData.Root, validUntil), expiringRootAndOpCountPDA, multisigConfigPDA, admin.PublicKey(), @@ -697,7 +696,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { require.NoError(t, proofsErr, "Failed to getting op proof") ix := mcm.NewExecuteInstruction( - testMsigName, + testMsigID, config.TestChainID, op.Nonce, op.Data, @@ -707,7 +706,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { rootMetadataPDA, expiringRootAndOpCountPDA, config.ExternalCpiStubProgram, - mcms.McmSignerAddress(testMsigName), + mcms.GetSignerPDA(testMsigID), admin.PublicKey(), ) // append remaining accounts @@ -901,15 +900,15 @@ func TestMcmSetRootAndExecute(t *testing.T) { t.Parallel() // use different msig accounts per test - testMsigName, err := mcms.PadString32(fmt.Sprintf("fail_sig_validation_test_%d", i)) + testMsigID, err := mcms.PadString32(fmt.Sprintf("fail_sig_validation_test_%d", i)) require.NoError(t, err) // test scoped mcm pdas - multisigConfigPDA := mcms.McmConfigAddress(testMsigName) - multisigSignerPDA := mcms.McmSignerAddress(testMsigName) - rootMetadataPDA := mcms.RootMetadataAddress(testMsigName) - expiringRootAndOpCountPDA := mcms.ExpiringRootAndOpCountAddress(testMsigName) - configSignersPDA := mcms.McmConfigSignersAddress(testMsigName) + multisigConfigPDA := mcms.GetConfigPDA(testMsigID) + multisigSignerPDA := mcms.GetSignerPDA(testMsigID) + rootMetadataPDA := mcms.GetRootMetadataPDA(testMsigID) + expiringRootAndOpCountPDA := mcms.GetExpiringRootAndOpCountPDA(testMsigID) + configSignersPDA := mcms.GetConfigSignersPDA(testMsigID) // fund the signer pda fundPDAIx, err := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), multisigSignerPDA).ValidateAndBuild() @@ -935,7 +934,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { ix, initErr := mcm.NewInitializeInstruction( config.TestChainID, - testMsigName, + testMsigID, multisigConfigPDA, admin.PublicKey(), solana.SystemProgramID, @@ -957,7 +956,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { }) mcmConfig, configErr := mcms.NewValidMcmConfig( - testMsigName, + testMsigID, config.SignerPrivateKeys, config.SignerGroups, config.GroupQuorums, @@ -967,7 +966,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { require.NoError(t, configErr) t.Run("setup: load signers and set_config", func(t *testing.T) { - preloadIxs, pierr := mcms.McmPreloadSignersIxs(mcmConfig.SignerAddresses, testMsigName, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + preloadIxs, pierr := mcms.GetPreloadSignersIxs(mcmConfig.SignerAddresses, testMsigID, multisigConfigPDA, configSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, pierr) for _, ix := range preloadIxs { @@ -987,7 +986,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { // set config ix, configErr := mcm.NewSetConfigInstruction( - mcmConfig.MultisigName, + mcmConfig.MultisigID, mcmConfig.SignerGroups, mcmConfig.GroupQuorums, mcmConfig.GroupParents, @@ -1046,7 +1045,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { }, ) require.NoError(t, rvErr) - signaturesPDA := mcms.RootSignaturesAddress(testMsigName, rootValidationData.Root, validUntil) + signaturesPDA := mcms.GetRootSignaturesPDA(testMsigID, rootValidationData.Root, validUntil) signers, getSignerErr := eth.GetEvmSigners(config.SignerPrivateKeys) require.NoError(t, getSignerErr) @@ -1056,12 +1055,10 @@ func TestMcmSetRootAndExecute(t *testing.T) { if tt.modifySigs != nil { tt.modifySigs(&signatures, &rootValidationData) } - - parsedTotalSigs, err := mcms.SafeToUint8(len(signatures)) - require.NoError(t, err) - + //nolint:gosec + parsedTotalSigs := uint8(len(signatures)) initSigsIx, err := mcm.NewInitSignaturesInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, parsedTotalSigs, @@ -1072,14 +1069,14 @@ func TestMcmSetRootAndExecute(t *testing.T) { require.NoError(t, err) txs = append(txs, TxWithStage{Instructions: []solana.Instruction{initSigsIx}, Stage: InitSignatures}) - appendSigsIxs, asErr := mcms.AppendSignaturesIxs(signatures, testMsigName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + appendSigsIxs, asErr := mcms.GetAppendSignaturesIxs(signatures, testMsigID, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, asErr) // one tx is enough since we only have 5 signers txs = append(txs, TxWithStage{Instructions: appendSigsIxs, Stage: AppendSignatures}) finalizeSigsIx, err := mcm.NewFinalizeSignaturesInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, signaturesPDA, @@ -1090,14 +1087,14 @@ func TestMcmSetRootAndExecute(t *testing.T) { txs = append(txs, TxWithStage{Instructions: []solana.Instruction{finalizeSigsIx}, Stage: FinalizeSignatures}) setRootIx, err := mcm.NewSetRootInstruction( - testMsigName, + testMsigID, rootValidationData.Root, validUntil, rootValidationData.Metadata, rootValidationData.MetadataProof, signaturesPDA, rootMetadataPDA, - mcms.SeenSignedHashesAddress(testMsigName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(testMsigID, rootValidationData.Root, validUntil), expiringRootAndOpCountPDA, multisigConfigPDA, admin.PublicKey(), @@ -1117,7 +1114,7 @@ func TestMcmSetRootAndExecute(t *testing.T) { require.NoError(t, proofsErr, "Failed to getting op proof") executeIx := mcm.NewExecuteInstruction( - testMsigName, + testMsigID, config.TestChainID, opNode.Nonce, opNode.Data, diff --git a/chains/solana/contracts/tests/mcms/mcm_timelock_test.go b/chains/solana/contracts/tests/mcms/mcm_timelock_test.go index 90d0f68f5..6f231f96b 100644 --- a/chains/solana/contracts/tests/mcms/mcm_timelock_test.go +++ b/chains/solana/contracts/tests/mcms/mcm_timelock_test.go @@ -67,7 +67,7 @@ func TestMcmWithTimelock(t *testing.T) { admin, config.DefaultCommitment) } // fund timelock signer - fundPDAIx := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), config.TimelockSignerPDA).Build() + fundPDAIx := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)).Build() testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{fundPDAIx}, admin, config.DefaultCommitment) @@ -112,7 +112,7 @@ func TestMcmWithTimelock(t *testing.T) { require.Equal(t, config.TestChainID, configAccount.ChainId) require.Equal(t, admin.PublicKey(), configAccount.Owner) - require.Equal(t, msig.PaddedName, configAccount.MultisigName) + require.Equal(t, msig.PaddedName, configAccount.MultisigId) }) } } @@ -127,10 +127,8 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("preload signers on PDA", func(t *testing.T) { ixs := make([]solana.Instruction, 0) - - parsedTotalSigners, parseErr := mcms.SafeToUint8(len(signerAddresses)) - require.NoError(t, parseErr) - + //nolint:gosec + parsedTotalSigners := uint8(len(signerAddresses)) initSignersIx, initSignersIxErr := mcm.NewInitSignersInstruction( msig.PaddedName, parsedTotalSigners, @@ -142,7 +140,7 @@ func TestMcmWithTimelock(t *testing.T) { require.NoError(t, initSignersIxErr) ixs = append(ixs, initSignersIx) - appendSignersIxs, appendSignersIxsErr := mcms.AppendSignersIxs(signerAddresses, msig.PaddedName, msig.ConfigPDA, msig.ConfigSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) + appendSignersIxs, appendSignersIxsErr := mcms.GetAppendSignersIxs(signerAddresses, msig.PaddedName, msig.ConfigPDA, msig.ConfigSignersPDA, admin.PublicKey(), config.MaxAppendSignerBatchSize) require.NoError(t, appendSignersIxsErr) ixs = append(ixs, appendSignersIxs...) @@ -234,7 +232,7 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("setup: timelock", func(t *testing.T) { for role, roleMsigs := range msigs { t.Run(fmt.Sprintf("init access controller for role %s", role.String()), func(t *testing.T) { - initAccIxs, initAccErr := timelockutil.InitAccessControllersIxs(ctx, roleMsigs.AccessController.PublicKey(), admin, solanaGoClient) + initAccIxs, initAccErr := timelockutil.GetInitAccessControllersIxs(ctx, roleMsigs.AccessController.PublicKey(), admin, solanaGoClient) require.NoError(t, initAccErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, initAccIxs, admin, config.DefaultCommitment, common.AddSigners(roleMsigs.AccessController)) @@ -262,8 +260,9 @@ func TestMcmWithTimelock(t *testing.T) { require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) initTimelockIx, initTimelockErr := timelock.NewInitializeInstruction( + config.TestTimelockID, config.MinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), solana.SystemProgramID, config.TimelockProgram, @@ -279,7 +278,7 @@ func TestMcmWithTimelock(t *testing.T) { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initTimelockIx}, admin, config.DefaultCommitment) var configAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if err != nil { require.NoError(t, err, "failed to get account info") } @@ -300,7 +299,7 @@ func TestMcmWithTimelock(t *testing.T) { for _, msig := range roleMsigs.Multisigs { addresses = append(addresses, msig.SignerPDA) } - batchAddAccessIxs, batchAddAccessErr := timelockutil.BatchAddAccessIxs(ctx, roleMsigs.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) + batchAddAccessIxs, batchAddAccessErr := timelockutil.GetBatchAddAccessIxs(ctx, config.TestTimelockID, roleMsigs.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) require.NoError(t, batchAddAccessErr) for _, ix := range batchAddAccessIxs { @@ -325,7 +324,7 @@ func TestMcmWithTimelock(t *testing.T) { t.Run(fmt.Sprintf(role.String(), mcms.UnpadString32(msig.PaddedName)), func(t *testing.T) { ix, transferOwnershipErr := mcm.NewTransferOwnershipInstruction( msig.PaddedName, - config.TimelockSignerPDA, // new proposed owner + timelockutil.GetSignerPDA(config.TestTimelockID), // new proposed owner msig.ConfigPDA, admin.PublicKey(), ).ValidateAndBuild() @@ -339,18 +338,19 @@ func TestMcmWithTimelock(t *testing.T) { require.NoError(t, err, "failed to get account info") } require.Equal(t, admin.PublicKey(), configAccount.Owner) - require.Equal(t, config.TimelockSignerPDA, configAccount.ProposedOwner) + require.Equal(t, timelockutil.GetSignerPDA(config.TestTimelockID), configAccount.ProposedOwner) acceptOwnershipIx, acceptOwnershipixErr := mcm.NewAcceptOwnershipInstruction( msig.PaddedName, msig.ConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ).ValidateAndBuild() require.NoError(t, acceptOwnershipixErr) - salt, sErr := mcms.SimpleSalt() + salt, sErr := timelockutil.SimpleSalt() require.NoError(t, sErr) acceptOwnershipOp := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: uint64(1), @@ -361,17 +361,18 @@ func TestMcmWithTimelock(t *testing.T) { id := acceptOwnershipOp.OperationID() operationPDA := acceptOwnershipOp.OperationPDA() - ixs, ierr := timelockutil.PreloadOperationIxs(acceptOwnershipOp, admin.PublicKey()) + ixs, ierr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, acceptOwnershipOp, admin.PublicKey()) require.NoError(t, ierr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) } scheduleBatchIx, scErr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, acceptOwnershipOp.OperationID(), acceptOwnershipOp.Delay, operationPDA, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), roleMsigs.AccessController.PublicKey(), admin.PublicKey(), ).ValidateAndBuild() @@ -410,10 +411,11 @@ func TestMcmWithTimelock(t *testing.T) { ) bypassExeIx := timelock.NewBypasserExecuteBatchInstruction( + config.TestTimelockID, acceptOwnershipOp.OperationID(), acceptOwnershipOp.OperationPDA(), - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), roleMsigs.AccessController.PublicKey(), admin.PublicKey(), // bypass execute with admin previledges ) @@ -441,7 +443,7 @@ func TestMcmWithTimelock(t *testing.T) { if err != nil { require.NoError(t, err, "failed to get account info") } - require.Equal(t, config.TimelockSignerPDA, configAccount.Owner) + require.Equal(t, timelockutil.GetSignerPDA(config.TestTimelockID), configAccount.Owner) require.Equal(t, solana.PublicKey{}, configAccount.ProposedOwner) }) } @@ -506,16 +508,17 @@ func TestMcmWithTimelock(t *testing.T) { require.Equal(t, 0, rInitBal) // mint authority to timelock - authIx, aErr := tokens.SetTokenMintAuthority(v.tokenProgram, config.TimelockSignerPDA, mint, admin.PublicKey()) + authIx, aErr := tokens.SetTokenMintAuthority(v.tokenProgram, timelockutil.GetSignerPDA(config.TestTimelockID), mint, admin.PublicKey()) require.NoError(t, aErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{authIx}, admin, config.DefaultCommitment) numMintIxs := 18 - salt, sErr := mcms.SimpleSalt() + salt, sErr := timelockutil.SimpleSalt() require.NoError(t, sErr) opToSchedule := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, // no predecessor Salt: salt, Delay: uint64(1), @@ -523,14 +526,14 @@ func TestMcmWithTimelock(t *testing.T) { for i := 0; i < numMintIxs; i++ { // timelock signer can mint token (transferred authority) - ix, mIxErr := tokens.MintTo(1*solana.LAMPORTS_PER_SOL, v.tokenProgram, mint, rAta, config.TimelockSignerPDA) + ix, mIxErr := tokens.MintTo(1*solana.LAMPORTS_PER_SOL, v.tokenProgram, mint, rAta, timelockutil.GetSignerPDA(config.TestTimelockID)) require.NoError(t, mIxErr) // add instruction to timelock operation opToSchedule.AddInstruction(ix, []solana.PublicKey{v.tokenProgram}) } - ixs, ierr := timelockutil.PreloadOperationIxs(opToSchedule, admin.PublicKey()) + ixs, ierr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, opToSchedule, admin.PublicKey()) require.NoError(t, ierr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) @@ -538,10 +541,11 @@ func TestMcmWithTimelock(t *testing.T) { // Schedule the operation scheduleIx, scErr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, opToSchedule.OperationID(), opToSchedule.Delay, opToSchedule.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), msigs[timelock.Proposer_Role].AccessController.PublicKey(), proposerMsig.SignerPDA, // msig signer since we're going to run this ix with mcm::execute ).ValidateAndBuild() @@ -569,7 +573,7 @@ func TestMcmWithTimelock(t *testing.T) { signaturesPDA := proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil) t.Run("mcm:preload signatures", func(t *testing.T) { - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { @@ -598,7 +602,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, signaturesPDA, proposerMsig.RootMetadataPDA, - mcms.SeenSignedHashesAddress(proposerMsig.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(proposerMsig.PaddedName, rootValidationData.Root, validUntil), proposerMsig.ExpiringRootAndOpCountPDA, proposerMsig.ConfigPDA, admin.PublicKey(), @@ -646,7 +650,7 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("mcm:execute -> timelock::schedule_batch", func(t *testing.T) { t.Run("check if timelock config is correct", func(t *testing.T) { - info, infoErr := solanaGoClient.GetAccountInfoWithOpts(ctx, config.TimelockConfigPDA, &rpc.GetAccountInfoOpts{ + info, infoErr := solanaGoClient.GetAccountInfoWithOpts(ctx, timelockutil.GetConfigPDA(config.TestTimelockID), &rpc.GetAccountInfoOpts{ Commitment: config.DefaultCommitment, }) require.NoError(t, infoErr) @@ -736,11 +740,12 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("timelock worker -> timelock::execute_batch", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, opToSchedule.OperationID(), opToSchedule.OperationPDA(), config.TimelockEmptyOpID, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), // timelock worker authority ) @@ -818,7 +823,7 @@ func TestMcmWithTimelock(t *testing.T) { ) require.NoError(t, cterr) - authIx, aterr := tokens.SetTokenMintAuthority(tokenProgram, config.TimelockSignerPDA, mint, admin.PublicKey()) + authIx, aterr := tokens.SetTokenMintAuthority(tokenProgram, timelockutil.GetSignerPDA(config.TestTimelockID), mint, admin.PublicKey()) require.NoError(t, aterr) setupIxs := append(createTokenIxs, authIx) @@ -831,15 +836,16 @@ func TestMcmWithTimelock(t *testing.T) { treasury, kerr := solana.NewRandomPrivateKey() require.NoError(t, kerr) - ix1, treasuryATA, taerr := tokens.CreateAssociatedTokenAccount(tokenProgram, mint, treasury.PublicKey(), config.TimelockSignerPDA) + ix1, treasuryATA, taerr := tokens.CreateAssociatedTokenAccount(tokenProgram, mint, treasury.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)) require.NoError(t, taerr) - ix2, tmerr := tokens.MintTo(1000*solana.LAMPORTS_PER_SOL, tokenProgram, mint, treasuryATA, config.TimelockSignerPDA) + ix2, tmerr := tokens.MintTo(1000*solana.LAMPORTS_PER_SOL, tokenProgram, mint, treasuryATA, timelockutil.GetSignerPDA(config.TestTimelockID)) require.NoError(t, tmerr) - salt1, serr := mcms.SimpleSalt() + salt1, serr := timelockutil.SimpleSalt() require.NoError(t, serr) op1 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, // no predecessor Salt: salt1, Delay: uint64(1), @@ -859,25 +865,26 @@ func TestMcmWithTimelock(t *testing.T) { ix3, team1ATA, t1cerr := tokens.CreateAssociatedTokenAccount( tokenProgram, mint, team1.PublicKey(), - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ) require.NoError(t, t1cerr) ix4, team2ATA, t2cerr := tokens.CreateAssociatedTokenAccount( tokenProgram, mint, team2.PublicKey(), - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ) require.NoError(t, t2cerr) ix5, team3ATA, t3cerr := tokens.CreateAssociatedTokenAccount( tokenProgram, mint, team3.PublicKey(), - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ) require.NoError(t, t3cerr) - salt2, s2err := mcms.SimpleSalt() + salt2, s2err := timelockutil.SimpleSalt() require.NoError(t, s2err) op2 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: op1.OperationID(), // must happen after initial mint Salt: salt2, Delay: uint64(1), @@ -889,17 +896,18 @@ func TestMcmWithTimelock(t *testing.T) { ////////////////////////////////////////////////////////////// // Timelock Operation 3 - Schedule team token distribution // ////////////////////////////////////////////////////////////// - ix6, i6err := tokens.TokenTransferChecked(100*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team1ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix6, i6err := tokens.TokenTransferChecked(100*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team1ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i6err) - ix7, i7err := tokens.TokenTransferChecked(200*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team2ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix7, i7err := tokens.TokenTransferChecked(200*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team2ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i7err) - ix8, i8err := tokens.TokenTransferChecked(300*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team3ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix8, i8err := tokens.TokenTransferChecked(300*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team3ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i8err) // add all team distribution instructions - salt3, s3err := mcms.SimpleSalt() + salt3, s3err := timelockutil.SimpleSalt() require.NoError(t, s3err) op3 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: op2.OperationID(), // must happen after ata creation Salt: salt3, Delay: uint64(1), @@ -920,17 +928,18 @@ func TestMcmWithTimelock(t *testing.T) { for i, op := range timelockOps { t.Run(fmt.Sprintf("prepare mcm op node %d with timelock::schedule_batch ix", i), func(t *testing.T) { - ixs, ierr := timelockutil.PreloadOperationIxs(op, admin.PublicKey()) + ixs, ierr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, admin.PublicKey()) require.NoError(t, ierr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) } scheduleOpIx, scErr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, op.OperationID(), op.Delay, op.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), msigs[timelock.Proposer_Role].AccessController.PublicKey(), proposerMsig.SignerPDA, ).ValidateAndBuild() @@ -969,7 +978,7 @@ func TestMcmWithTimelock(t *testing.T) { //////////////////////////////////////////////// // mcm::set_root - with preloading signatures // //////////////////////////////////////////////// - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil), admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil), admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { @@ -998,7 +1007,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil), proposerMsig.RootMetadataPDA, - mcms.SeenSignedHashesAddress(proposerMsig.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(proposerMsig.PaddedName, rootValidationData.Root, validUntil), proposerMsig.ExpiringRootAndOpCountPDA, proposerMsig.ConfigPDA, admin.PublicKey(), @@ -1110,9 +1119,10 @@ func TestMcmWithTimelock(t *testing.T) { canceller := msigs[timelock.Canceller_Role].GetAnyMultisig() cancelIx, cerr := timelock.NewCancelInstruction( + config.TestTimelockID, op3.OperationID(), op3.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), msigs[timelock.Canceller_Role].AccessController.PublicKey(), canceller.SignerPDA, ).ValidateAndBuild() @@ -1142,7 +1152,7 @@ func TestMcmWithTimelock(t *testing.T) { signaturesPDA := canceller.RootSignaturesPDA(rootValidationData.Root, validUntil) - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, canceller.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, canceller.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { @@ -1157,7 +1167,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, signaturesPDA, canceller.RootMetadataPDA, - mcms.SeenSignedHashesAddress(canceller.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(canceller.PaddedName, rootValidationData.Root, validUntil), canceller.ExpiringRootAndOpCountPDA, canceller.ConfigPDA, admin.PublicKey(), @@ -1230,17 +1240,18 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("create new operation with corrected amounts", func(t *testing.T) { // Create corrected transfer instructions with new amounts - ix1, i1err := tokens.TokenTransferChecked(150*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team1ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix1, i1err := tokens.TokenTransferChecked(150*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team1ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i1err) - ix2, i2err := tokens.TokenTransferChecked(150*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team2ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix2, i2err := tokens.TokenTransferChecked(150*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team2ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i2err) - ix3, i3err := tokens.TokenTransferChecked(100*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team3ATA, config.TimelockSignerPDA, []solana.PublicKey{}) + ix3, i3err := tokens.TokenTransferChecked(100*solana.LAMPORTS_PER_SOL, 9, tokenProgram, treasuryATA, mint, team3ATA, timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}) require.NoError(t, i3err) // Create new operation - salt, serr := mcms.SimpleSalt() + salt, serr := timelockutil.SimpleSalt() require.NoError(t, serr) newOp3 = timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: op2.OperationID(), Salt: salt, Delay: uint64(1), @@ -1250,7 +1261,7 @@ func TestMcmWithTimelock(t *testing.T) { newOp3.AddInstruction(ix2, []solana.PublicKey{tokenProgram}) newOp3.AddInstruction(ix3, []solana.PublicKey{tokenProgram}) - ixs, perr := timelockutil.PreloadOperationIxs(newOp3, admin.PublicKey()) + ixs, perr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, newOp3, admin.PublicKey()) require.NoError(t, perr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) @@ -1258,10 +1269,11 @@ func TestMcmWithTimelock(t *testing.T) { // Create mcm operation node for scheduling scheduleIx, scerr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, newOp3.OperationID(), newOp3.Delay, newOp3.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), msigs[timelock.Proposer_Role].AccessController.PublicKey(), proposerMsig.SignerPDA, ).ValidateAndBuild() @@ -1293,7 +1305,7 @@ func TestMcmWithTimelock(t *testing.T) { signaturesPDA := proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil) // preload signatures - preloadIxs, plerr := mcms.McmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) + preloadIxs, plerr := mcms.GetMcmPreloadSignaturesIxs(signatures, proposerMsig.PaddedName, rootValidationData.Root, validUntil, signaturesPDA, admin.PublicKey(), config.MaxAppendSignatureBatchSize) require.NoError(t, plerr) for _, ix := range preloadIxs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) @@ -1308,7 +1320,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, signaturesPDA, proposerMsig.RootMetadataPDA, - mcms.SeenSignedHashesAddress(proposerMsig.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(proposerMsig.PaddedName, rootValidationData.Root, validUntil), proposerMsig.ExpiringRootAndOpCountPDA, proposerMsig.ConfigPDA, admin.PublicKey(), @@ -1397,11 +1409,12 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("op2: cannot be executed before op1", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op1.OperationPDA(), // provide op1 PDA as predecessor - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) @@ -1420,11 +1433,12 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("op1: initial mint to treasury", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op1.OperationID(), op1.OperationPDA(), config.TimelockEmptyOpID, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) @@ -1485,7 +1499,7 @@ func TestMcmWithTimelock(t *testing.T) { tokenProgram, treasuryATA, mint, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), treasury.PublicKey(), nil, ) @@ -1495,11 +1509,12 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("op2: should provide the correct predecessor pda address", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op1.OperationID(), // provide op1 ID as predecessor - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) @@ -1518,11 +1533,12 @@ func TestMcmWithTimelock(t *testing.T) { t.Run("op2: team ata creation", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op1.OperationPDA(), // provide op1 PDA as predecessor - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) @@ -1566,11 +1582,12 @@ func TestMcmWithTimelock(t *testing.T) { require.NoError(t, werr) executeTimelockIx := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, newOp3.OperationID(), newOp3.OperationPDA(), op2.OperationPDA(), - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) @@ -1746,7 +1763,7 @@ func TestMcmWithTimelock(t *testing.T) { signaturesPDA := executorMsig.RootSignaturesPDA(rootValidationData.Root, validUntil) // preload signatures - preloadIxs, err := mcms.McmPreloadSignaturesIxs( + preloadIxs, err := mcms.GetMcmPreloadSignaturesIxs( signatures, executorMsig.PaddedName, rootValidationData.Root, @@ -1770,7 +1787,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, signaturesPDA, executorMsig.RootMetadataPDA, - mcms.SeenSignedHashesAddress(executorMsig.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(executorMsig.PaddedName, rootValidationData.Root, validUntil), executorMsig.ExpiringRootAndOpCountPDA, executorMsig.ConfigPDA, admin.PublicKey(), @@ -1896,7 +1913,7 @@ func TestMcmWithTimelock(t *testing.T) { testutils.SendAndConfirm(ctx, t, solanaGoClient, setupIxs, admin, config.DefaultCommitment, common.AddSigners(mintKeypair)) // setup mint authority to Timelock signer - authIx, err := tokens.SetTokenMintAuthority(tokenProgram, config.TimelockSignerPDA, mint, admin.PublicKey()) + authIx, err := tokens.SetTokenMintAuthority(tokenProgram, timelockutil.GetSignerPDA(config.TestTimelockID), mint, admin.PublicKey()) require.NoError(t, err) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{authIx}, admin, config.DefaultCommitment) @@ -1935,7 +1952,7 @@ func TestMcmWithTimelock(t *testing.T) { tokenProgram, treasuryATA, mint, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), treasury.PublicKey(), nil, ) @@ -1991,7 +2008,7 @@ func TestMcmWithTimelock(t *testing.T) { treasuryATA, mint, ata, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), []solana.PublicKey{}, ) require.NoError(t, err) @@ -2016,10 +2033,11 @@ func TestMcmWithTimelock(t *testing.T) { } // create timelock operation for the batch - salt, err := mcms.SimpleSalt() + salt, err := timelockutil.SimpleSalt() require.NoError(t, err) op := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: uint64(1), @@ -2031,7 +2049,7 @@ func TestMcmWithTimelock(t *testing.T) { } // create and initialize operation accounts - ixs, err := timelockutil.PreloadOperationIxs(op, admin.PublicKey()) + ixs, err := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, admin.PublicKey()) require.NoError(t, err) for _, ix := range ixs { cu := testutils.GetRequiredCU(ctx, t, solanaGoClient, []solana.Instruction{ix}, admin, config.DefaultCommitment) @@ -2046,10 +2064,11 @@ func TestMcmWithTimelock(t *testing.T) { // schedule the operation scheduleIx, err := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, op.OperationID(), op.Delay, op.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), msigs[timelock.Proposer_Role].AccessController.PublicKey(), proposerMsig.SignerPDA, ).ValidateAndBuild() @@ -2089,7 +2108,7 @@ func TestMcmWithTimelock(t *testing.T) { signaturesPDA := proposerMsig.RootSignaturesPDA(rootValidationData.Root, validUntil) // preload signatures - preloadIxs, err := mcms.McmPreloadSignaturesIxs( + preloadIxs, err := mcms.GetMcmPreloadSignaturesIxs( signatures, proposerMsig.PaddedName, rootValidationData.Root, @@ -2113,7 +2132,7 @@ func TestMcmWithTimelock(t *testing.T) { rootValidationData.MetadataProof, signaturesPDA, proposerMsig.RootMetadataPDA, - mcms.SeenSignedHashesAddress(proposerMsig.PaddedName, rootValidationData.Root, validUntil), + mcms.GetSeenSignedHashesPDA(proposerMsig.PaddedName, rootValidationData.Root, validUntil), proposerMsig.ExpiringRootAndOpCountPDA, proposerMsig.ConfigPDA, admin.PublicKey(), @@ -2155,11 +2174,12 @@ func TestMcmWithTimelock(t *testing.T) { require.NoError(t, err) tlExeIx := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op.OperationID(), op.OperationPDA(), config.TimelockEmptyOpID, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), msigs[timelock.Executor_Role].AccessController.PublicKey(), admin.PublicKey(), ) diff --git a/chains/solana/contracts/tests/mcms/timelock_bypasser_execute_test.go b/chains/solana/contracts/tests/mcms/timelock_bypasser_execute_test.go index 15a5cc1fd..674a1ca67 100644 --- a/chains/solana/contracts/tests/mcms/timelock_bypasser_execute_test.go +++ b/chains/solana/contracts/tests/mcms/timelock_bypasser_execute_test.go @@ -18,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/accesscontroller" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" timelockutil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" ) @@ -69,7 +68,7 @@ func TestTimelockBypasserExecute(t *testing.T) { t.Run("setup:init access controllers", func(t *testing.T) { for _, data := range roleMap { - initAccIxs, initAccIxsErr := timelockutil.InitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) + initAccIxs, initAccIxsErr := timelockutil.GetInitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) require.NoError(t, initAccIxsErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, initAccIxs, admin, config.DefaultCommitment, common.AddSigners(data.AccessController)) @@ -82,7 +81,7 @@ func TestTimelockBypasserExecute(t *testing.T) { } }) - t.Run("setup:init timelock program", func(t *testing.T) { + t.Run("setup:initialize timelock instance", func(t *testing.T) { // get program data account data, accErr := solanaGoClient.GetAccountInfoWithOpts(ctx, config.TimelockProgram, &rpc.GetAccountInfoOpts{ Commitment: config.DefaultCommitment, @@ -97,8 +96,9 @@ func TestTimelockBypasserExecute(t *testing.T) { require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) initTimelockIx, initErr := timelock.NewInitializeInstruction( + config.TestTimelockID, config.MinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), solana.SystemProgramID, config.TimelockProgram, @@ -114,7 +114,7 @@ func TestTimelockBypasserExecute(t *testing.T) { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initTimelockIx}, admin, config.DefaultCommitment) var configAccount timelock.Config - cfgErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + cfgErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if cfgErr != nil { require.NoError(t, cfgErr, "failed to get account info") } @@ -133,7 +133,7 @@ func TestTimelockBypasserExecute(t *testing.T) { for _, account := range data.Accounts { addresses = append(addresses, account.PublicKey()) } - batchAddAccessIxs, batchAddAccessIxsErr := timelockutil.BatchAddAccessIxs(ctx, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) + batchAddAccessIxs, batchAddAccessIxsErr := timelockutil.GetBatchAddAccessIxs(ctx, config.TestTimelockID, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) require.NoError(t, batchAddAccessIxsErr) for _, ix := range batchAddAccessIxs { @@ -152,7 +152,7 @@ func TestTimelockBypasserExecute(t *testing.T) { t.Run("setup: wsol transfer operation", func(t *testing.T) { requiredAmount := allowance.recipient - fundPDAIx := system.NewTransferInstruction(allowance.timelockAuthority, admin.PublicKey(), config.TimelockSignerPDA).Build() + fundPDAIx := system.NewTransferInstruction(allowance.timelockAuthority, admin.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)).Build() createAdminATAIx, _, caErr := tokens.CreateAssociatedTokenAccount(tokenProgram, wsol, admin.PublicKey(), admin.PublicKey()) require.NoError(t, caErr) @@ -177,7 +177,7 @@ func TestTimelockBypasserExecute(t *testing.T) { tokenProgram, adminATA, wsol, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), admin.PublicKey(), nil, ) @@ -191,7 +191,7 @@ func TestTimelockBypasserExecute(t *testing.T) { // check results timelockAuthorityBalance, tlBalanceErr := solanaGoClient.GetBalance( ctx, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), config.DefaultCommitment, ) require.NoError(t, tlBalanceErr) @@ -207,9 +207,10 @@ func TestTimelockBypasserExecute(t *testing.T) { }) t.Run("success: schedule and execute batch instructions", func(t *testing.T) { - salt, err := mcms.SimpleSalt() + salt, err := timelockutil.SimpleSalt() require.NoError(t, err) op := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: uint64(1000), @@ -219,7 +220,7 @@ func TestTimelockBypasserExecute(t *testing.T) { tokenProgram, wsol, recipient.PublicKey(), - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ) require.NoError(t, ciErr) op.AddInstruction( @@ -234,7 +235,7 @@ func TestTimelockBypasserExecute(t *testing.T) { adminATA, wsol, recipientATA, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), nil, ) require.NoError(t, tiErr) @@ -244,7 +245,7 @@ func TestTimelockBypasserExecute(t *testing.T) { operationPDA := op.OperationPDA() signer := roleMap[timelock.Proposer_Role].RandomPick() - ixs, err := timelockutil.PreloadOperationIxs(op, signer.PublicKey()) + ixs, err := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, signer.PublicKey()) require.NoError(t, err) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, signer, config.DefaultCommitment) @@ -267,10 +268,11 @@ func TestTimelockBypasserExecute(t *testing.T) { ac := roleMap[timelock.Bypasser_Role].AccessController ix := timelock.NewBypasserExecuteBatchInstruction( + config.TestTimelockID, id, operationPDA, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), ac.PublicKey(), signer.PublicKey(), ) diff --git a/chains/solana/contracts/tests/mcms/timelock_multiple_instances_test.go b/chains/solana/contracts/tests/mcms/timelock_multiple_instances_test.go new file mode 100644 index 000000000..73baa9fc8 --- /dev/null +++ b/chains/solana/contracts/tests/mcms/timelock_multiple_instances_test.go @@ -0,0 +1,751 @@ +package contracts + +import ( + "context" + "testing" + + bin "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/programs/system" + "github.com/gagliardetto/solana-go/rpc" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/access_controller" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/accesscontroller" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" + timelockutil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" +) + +type TimelockInstance struct { + ID [32]byte + Admin solana.PrivateKey + ConfigPDA solana.PublicKey + SignerPDA solana.PublicKey + Roles []timelockutil.RoleAccounts + RoleMap timelockutil.RoleMap +} + +func TestTimelockMultipleInstances(t *testing.T) { + t.Parallel() + ctx := tests.Context(t) + + timelock.SetProgramID(config.TimelockProgram) + access_controller.SetProgramID(config.AccessControllerProgram) + + deployer, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + + solanaGoClient := testutils.DeployAllPrograms(t, testutils.PathToAnchorConfig, deployer) + + admin1, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + + admin2, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + + testTimelockID1, err := mcms.PadString32("test_timelock_instance_1") + require.NoError(t, err) + + testTimelockID2, err := mcms.PadString32("test_timelock_instance_2") + require.NoError(t, err) + + roles1, roleMap1 := timelockutil.TestRoleAccounts(1) + roles2, roleMap2 := timelockutil.TestRoleAccounts(1) + + timelockInstances := []TimelockInstance{ + { + ID: testTimelockID1, + Admin: admin1, + ConfigPDA: timelockutil.GetConfigPDA(testTimelockID1), + SignerPDA: timelockutil.GetSignerPDA(testTimelockID1), + Roles: roles1, + RoleMap: roleMap1, + }, + { + ID: testTimelockID2, + Admin: admin2, + ConfigPDA: timelockutil.GetConfigPDA(testTimelockID2), + SignerPDA: timelockutil.GetSignerPDA(testTimelockID2), + Roles: roles2, + RoleMap: roleMap2, + }, + } + + t.Run("setup:funding", func(t *testing.T) { + all := []solana.PrivateKey{} + all = append(all, deployer) + for _, instance := range timelockInstances { + all = append(all, instance.Admin) + for _, role := range instance.Roles { + all = append(all, role.Accounts...) + } + } + testutils.FundAccounts(ctx, all, solanaGoClient, t) + }) + + t.Run("setup:init access controllers", func(t *testing.T) { + for _, instance := range timelockInstances { + for _, data := range instance.RoleMap { + initAccIxs, ierr := timelockutil.GetInitAccessControllersIxs(ctx, data.AccessController.PublicKey(), instance.Admin, solanaGoClient) + require.NoError(t, ierr) + + testutils.SendAndConfirm(ctx, t, solanaGoClient, initAccIxs, instance.Admin, config.DefaultCommitment, common.AddSigners(data.AccessController)) + + var ac access_controller.AccessController + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, data.AccessController.PublicKey(), config.DefaultCommitment, &ac) + if err != nil { + require.NoError(t, err, "failed to get account info") + } + } + } + }) + + t.Run("setup:init timelock instances", func(t *testing.T) { + // get program data account + data, accErr := solanaGoClient.GetAccountInfoWithOpts(ctx, config.TimelockProgram, &rpc.GetAccountInfoOpts{ + Commitment: config.DefaultCommitment, + }) + require.NoError(t, accErr) + + // decode program data + var programData struct { + DataType uint32 + Address solana.PublicKey + } + require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) + + for _, instance := range timelockInstances { + initTimelockIx, ierr := timelock.NewInitializeInstruction( + instance.ID, + config.MinDelay, + instance.ConfigPDA, + deployer.PublicKey(), // deployer is the owner of the timelock program initially + solana.SystemProgramID, + config.TimelockProgram, + programData.Address, + config.AccessControllerProgram, + instance.RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), + instance.RoleMap[timelock.Executor_Role].AccessController.PublicKey(), + instance.RoleMap[timelock.Canceller_Role].AccessController.PublicKey(), + instance.RoleMap[timelock.Bypasser_Role].AccessController.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initTimelockIx}, deployer, config.DefaultCommitment) + + var configAccount timelock.Config + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, instance.ConfigPDA, config.DefaultCommitment, &configAccount) + if err != nil { + require.NoError(t, err, "failed to get account info") + } + + require.Equal(t, deployer.PublicKey(), configAccount.Owner, "The initial owner doesn't match") + require.Equal(t, instance.ID, configAccount.TimelockId, "TimelockID doesn't match") + require.Equal(t, config.MinDelay, configAccount.MinDelay, "MinDelay doesn't match") + require.Equal(t, instance.RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), configAccount.ProposerRoleAccessController, "ProposerRoleAccessController doesn't match") + require.Equal(t, instance.RoleMap[timelock.Executor_Role].AccessController.PublicKey(), configAccount.ExecutorRoleAccessController, "ExecutorRoleAccessController doesn't match") + require.Equal(t, instance.RoleMap[timelock.Canceller_Role].AccessController.PublicKey(), configAccount.CancellerRoleAccessController, "CancellerRoleAccessController doesn't match") + require.Equal(t, instance.RoleMap[timelock.Bypasser_Role].AccessController.PublicKey(), configAccount.BypasserRoleAccessController, "BypasserRoleAccessController doesn't match") + } + }) + + t.Run("transfer config ownership(admin role) to each admin", func(t *testing.T) { + for _, instance := range timelockInstances { + t.Run("transfer ownership", func(t *testing.T) { + ix, ierr := timelock.NewTransferOwnershipInstruction( + instance.ID, + instance.Admin.PublicKey(), + instance.ConfigPDA, + deployer.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + result := testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, deployer, config.DefaultCommitment) + require.NotNil(t, result) + }) + + t.Run("instance.Admin becomes owner", func(t *testing.T) { + ix, ierr := timelock.NewAcceptOwnershipInstruction( + instance.ID, + instance.ConfigPDA, + instance.Admin.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + result := testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, instance.Admin, config.DefaultCommitment) + require.NotNil(t, result) + + // Validate proposed set to 0-address after accepting ownership + var configAccount timelock.Config + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(instance.ID), config.DefaultCommitment, &configAccount) + if err != nil { + require.NoError(t, err, "failed to get account info") + } + require.Equal(t, instance.Admin.PublicKey(), configAccount.Owner) + require.Equal(t, solana.PublicKey{}, configAccount.ProposedOwner) + }) + } + }) + + t.Run("setup:register access list & verify", func(t *testing.T) { + for _, instance := range timelockInstances { + for role, data := range instance.RoleMap { + addresses := []solana.PublicKey{} + for _, account := range data.Accounts { + addresses = append(addresses, account.PublicKey()) + } + batchAddAccessIxs, baerr := timelockutil.GetBatchAddAccessIxs(ctx, instance.ID, data.AccessController.PublicKey(), role, addresses, instance.Admin, config.BatchAddAccessChunkSize, solanaGoClient) + require.NoError(t, baerr) + + for _, ix := range batchAddAccessIxs { + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, instance.Admin, config.DefaultCommitment) + } + + for _, account := range data.Accounts { + found, ferr := accesscontroller.HasAccess(ctx, solanaGoClient, data.AccessController.PublicKey(), account.PublicKey(), config.DefaultCommitment) + require.NoError(t, ferr) + require.True(t, found, "Account %s not found in %s AccessList", account.PublicKey(), data.Role) + } + } + } + }) + + t.Run("instance isolation tests", func(t *testing.T) { + t.Run("config isolation", func(t *testing.T) { + t.Run("cannot access other instance config using own roles", func(t *testing.T) { + t.Parallel() + // try to use instance1's proposer to schedule on instance2 + proposer := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + salt, err := timelockutil.SimpleSalt() + require.NoError(t, err) + + // create test operation for instance2 but using instance1's proposer + op := timelockutil.Operation{ + TimelockID: timelockInstances[1].ID, + Predecessor: config.TimelockEmptyOpID, + Salt: salt, + Delay: uint64(1), + } + + // preload operation instructions + preloadIxs, prierr := timelockutil.GetPreloadOperationIxs( + timelockInstances[1].ID, + op, + proposer.PublicKey(), + ) + require.NoError(t, prierr) + + for _, ix := range preloadIxs { + testutils.SendAndConfirm( + ctx, + t, + solanaGoClient, + []solana.Instruction{ix}, + proposer, + config.DefaultCommitment, + ) + } + + // Try to schedule operation on instance2 using instance1's proposer + ix, ierr := timelock.NewScheduleBatchInstruction( + timelockInstances[1].ID, // instance2's ID + op.OperationID(), + op.Delay, + op.OperationPDA(), + timelockInstances[1].ConfigPDA, // instance2's config + timelockInstances[0].RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), // instance1's proposer AC + proposer.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + result := testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{ix}, + proposer, // signing with instance1's proposer + config.DefaultCommitment, + []string{"Error Code: " + timelock.InvalidAccessController_TimelockError.String()}, + ) + require.NotNil(t, result) + }) + + t.Run("cannot update delay using other instance's admin", func(t *testing.T) { + t.Parallel() + // try to update instance2's delay using instance1's admin + newMinDelay := uint64(14000) + + ix, ierr := timelock.NewUpdateDelayInstruction( + timelockInstances[1].ID, // instance2's ID + newMinDelay, + timelockInstances[1].ConfigPDA, + timelockInstances[0].Admin.PublicKey(), // instance1's admin trying to update + ).ValidateAndBuild() + require.NoError(t, ierr) + + result := testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{ix}, + timelockInstances[0].Admin, // signing with instance1's admin + config.DefaultCommitment, + []string{"Error Code: " + timelockutil.UnauthorizedError.String()}, + ) + require.NotNil(t, result) + }) + + t.Run("cannot modify access controllers of another instance", func(t *testing.T) { + t.Parallel() + // try to use instance1's admin to modify instance2's access controller + randomKey, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + + // try to add access to instance2's proposer role using instance1's admin + ix, ierr := access_controller.NewAddAccessInstruction( + timelockInstances[1].RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), // instance2's proposer AC + timelockInstances[0].Admin.PublicKey(), // instance1's admin trying to modify + randomKey.PublicKey(), // random key to add + ).ValidateAndBuild() + require.NoError(t, ierr) + + result := testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{ix}, + timelockInstances[0].Admin, // signing with instance1's admin + config.DefaultCommitment, + []string{"Error Code: ConstraintHasOne"}, + ) + require.NotNil(t, result) + }) + + t.Run("cannot transfer ownership of another instance", func(t *testing.T) { + t.Parallel() + // try to transfer instance2's ownership using instance1's admin + ix, ierr := timelock.NewTransferOwnershipInstruction( + timelockInstances[1].ID, // instance2's ID + timelockInstances[0].Admin.PublicKey(), // trying to transfer to instance1's admin + timelockInstances[1].ConfigPDA, + timelockInstances[0].Admin.PublicKey(), // instance1's admin trying to transfer + ).ValidateAndBuild() + require.NoError(t, ierr) + + result := testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{ix}, + timelockInstances[0].Admin, // signing with instance1's admin + config.DefaultCommitment, + []string{"Error Code: " + timelockutil.UnauthorizedError.String()}, + ) + require.NotNil(t, result) + }) + }) + + t.Run("operation isolation", func(t *testing.T) { + t.Run("cannot execute operation scheduled on another instance", func(t *testing.T) { + t.Parallel() + // Schedule operation on instance1 + proposer1 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + executor2 := timelockInstances[1].RoleMap[timelock.Executor_Role].RandomPick() + + salt, err := timelockutil.SimpleSalt() + require.NoError(t, err) + + // Create and schedule operation on instance1 + op := timelockutil.Operation{ + TimelockID: timelockInstances[0].ID, + Predecessor: config.TimelockEmptyOpID, + Salt: salt, + Delay: uint64(1), + } + + // Add simple transfer instruction + ix := system.NewTransferInstruction( + 1*solana.LAMPORTS_PER_SOL, + proposer1.PublicKey(), + timelockInstances[0].SignerPDA, + ).Build() + op.AddInstruction(ix, []solana.PublicKey{}) + + // Schedule on instance1 + preloadIxs, prierr := timelockutil.GetPreloadOperationIxs( + timelockInstances[0].ID, + op, + proposer1.PublicKey(), + ) + require.NoError(t, prierr) + for _, ix := range preloadIxs { + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer1, config.DefaultCommitment) + } + + scheduleIx, ierr := timelock.NewScheduleBatchInstruction( + timelockInstances[0].ID, + op.OperationID(), + op.Delay, + op.OperationPDA(), + timelockInstances[0].ConfigPDA, + timelockInstances[0].RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), + proposer1.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{scheduleIx}, proposer1, config.DefaultCommitment) + + // Wait for operation to be ready + err = timelockutil.WaitForOperationToBeReady(ctx, solanaGoClient, op.OperationPDA(), config.DefaultCommitment) + require.NoError(t, err) + + // try to execute instance1's operation using instance2's executor + executeIx := timelock.NewExecuteBatchInstruction( + timelockInstances[1].ID, // Use instance2's ID + op.OperationID(), + op.OperationPDA(), // instance1's operation PDA + config.TimelockEmptyOpID, // empty predecessor + timelockInstances[1].ConfigPDA, // instance2's config + timelockInstances[1].SignerPDA, // instance2's signer + timelockInstances[1].RoleMap[timelock.Executor_Role].AccessController.PublicKey(), + executor2.PublicKey(), + ) + executeIx.AccountMetaSlice = append(executeIx.AccountMetaSlice, op.RemainingAccounts()...) + + vIx, err := executeIx.ValidateAndBuild() + require.NoError(t, err) + + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{vIx}, + executor2, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds."}, + ) + }) + t.Run("cannot cancel operation from another instance", func(t *testing.T) { + t.Parallel() + proposer1 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + salt, err := timelockutil.SimpleSalt() + require.NoError(t, err) + + op := timelockutil.Operation{ + TimelockID: timelockInstances[0].ID, + Predecessor: config.TimelockEmptyOpID, + Salt: salt, + Delay: uint64(1), + } + + ix := system.NewTransferInstruction( + 1*solana.LAMPORTS_PER_SOL, + proposer1.PublicKey(), + timelockInstances[0].SignerPDA, + ).Build() + op.AddInstruction(ix, []solana.PublicKey{}) + + preloadIxs, prierr := timelockutil.GetPreloadOperationIxs( + timelockInstances[0].ID, + op, + proposer1.PublicKey(), + ) + require.NoError(t, prierr) + for _, ix := range preloadIxs { + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer1, config.DefaultCommitment) + } + + scheduleIx, ierr := timelock.NewScheduleBatchInstruction( + timelockInstances[0].ID, + op.OperationID(), + op.Delay, + op.OperationPDA(), + timelockInstances[0].ConfigPDA, + timelockInstances[0].RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), + proposer1.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{scheduleIx}, proposer1, config.DefaultCommitment) + + // try to cancel instance1's operation using instance2's canceller + canceller2 := timelockInstances[1].RoleMap[timelock.Canceller_Role].RandomPick() + + cancelIx, cerr := timelock.NewCancelInstruction( + timelockInstances[1].ID, // using instance2's ID + op.OperationID(), + op.OperationPDA(), + timelockInstances[1].ConfigPDA, + timelockInstances[1].RoleMap[timelock.Canceller_Role].AccessController.PublicKey(), + canceller2.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, cerr) + + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{cancelIx}, + canceller2, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds"}, + ) + }) + }) + + t.Run("role isolation", func(t *testing.T) { + // helper - attempt to schedule on `target` using `source`'s Proposer + testScheduleUsingAnotherProposer := func(t *testing.T, source, target TimelockInstance) { + sourceProposer := source.RoleMap[timelock.Proposer_Role].RandomPick() + + // build trivial op on target TimelockID + salt, err := timelockutil.SimpleSalt() + require.NoError(t, err) + + op := timelockutil.Operation{ + TimelockID: target.ID, + Predecessor: config.TimelockEmptyOpID, + Salt: salt, + Delay: 1, + } + preloadIxs, priErr := timelockutil.GetPreloadOperationIxs(target.ID, op, sourceProposer.PublicKey()) + require.NoError(t, priErr) + + // try sending from sourceProposer + for _, ix := range preloadIxs { + testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, sourceProposer, config.DefaultCommitment) + } + + // attempt to schedule with the WRONG AC + scheduleIx, ierr := timelock.NewScheduleBatchInstruction( + target.ID, + op.OperationID(), + op.Delay, + op.OperationPDA(), + target.ConfigPDA, + source.RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), // cross-instance + sourceProposer.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + // expect failure + result := testutils.SendAndFailWith( + ctx, t, + solanaGoClient, + []solana.Instruction{scheduleIx}, + sourceProposer, + config.DefaultCommitment, + []string{"Error Code: " + timelock.InvalidAccessController_TimelockError.String()}, + ) + require.NotNil(t, result) + } + + t.Run("proposer cannot schedule on other instance", func(t *testing.T) { + t.Parallel() + testScheduleUsingAnotherProposer(t, timelockInstances[0], timelockInstances[1]) + testScheduleUsingAnotherProposer(t, timelockInstances[1], timelockInstances[0]) + }) + + t.Run("executor cannot execute on other instance", func(t *testing.T) { + t.Parallel() + proposer0 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + op := createAndScheduleOperation(ctx, t, solanaGoClient, timelockInstances[0], proposer0, 1) + + err := timelockutil.WaitForOperationToBeReady(ctx, solanaGoClient, op.OperationPDA(), config.DefaultCommitment) + require.NoError(t, err) + + executor1 := timelockInstances[1].RoleMap[timelock.Executor_Role].RandomPick() + executorAC1 := timelockInstances[1].RoleMap[timelock.Executor_Role].AccessController.PublicKey() + + executeIx := timelock.NewExecuteBatchInstruction( + timelockInstances[1].ID, // WRONG ID + op.OperationID(), + op.OperationPDA(), + config.TimelockEmptyOpID, + timelockInstances[1].ConfigPDA, + timelockInstances[1].SignerPDA, + executorAC1, + executor1.PublicKey(), + ) + executeIx.AccountMetaSlice = append(executeIx.AccountMetaSlice, op.RemainingAccounts()...) + + vIx, err := executeIx.ValidateAndBuild() + require.NoError(t, err) + + // Expect a seeds mismatch or similar + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{vIx}, + executor1, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds"}, + ) + }) + + t.Run("canceller cannot cancel on other instance", func(t *testing.T) { + t.Parallel() + // create + schedule op on instance[0] with a large delay => still pending + proposer0 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + op := createAndScheduleOperation(ctx, t, solanaGoClient, timelockInstances[0], proposer0, 9999) + + // try to cancel from instance[1]'s Canceller + canceller1 := timelockInstances[1].RoleMap[timelock.Canceller_Role].RandomPick() + cancellerAC1 := timelockInstances[1].RoleMap[timelock.Canceller_Role].AccessController.PublicKey() + + cancelIx, cerr := timelock.NewCancelInstruction( + timelockInstances[1].ID, + op.OperationID(), + op.OperationPDA(), + timelockInstances[1].ConfigPDA, + cancellerAC1, + canceller1.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, cerr) + + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{cancelIx}, + canceller1, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds"}, + ) + }) + + t.Run("bypasser cannot bypass on other instance", func(t *testing.T) { + t.Parallel() + proposer0 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + op := createAndScheduleOperation(ctx, t, solanaGoClient, timelockInstances[0], proposer0, 1) + + err := timelockutil.WaitForOperationToBeReady(ctx, solanaGoClient, op.OperationPDA(), config.DefaultCommitment) + require.NoError(t, err) + + bypasser1 := timelockInstances[1].RoleMap[timelock.Bypasser_Role].RandomPick() + bypasserAC1 := timelockInstances[1].RoleMap[timelock.Bypasser_Role].AccessController.PublicKey() + + bypassIx := timelock.NewBypasserExecuteBatchInstruction( + timelockInstances[1].ID, + op.OperationID(), + op.OperationPDA(), + timelockInstances[1].ConfigPDA, + timelockInstances[1].SignerPDA, + bypasserAC1, + bypasser1.PublicKey(), + ) + bypassIx.AccountMetaSlice = append(bypassIx.AccountMetaSlice, op.RemainingAccounts()...) + + vIx, err := bypassIx.ValidateAndBuild() + require.NoError(t, err) + + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{vIx}, + bypasser1, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds"}, + ) + }) + }) + + t.Run("reinitialize the same timelock_id fails", func(t *testing.T) { + inst := timelockInstances[0] + + ix, initErr := timelock.NewInitializeInstruction( + inst.ID, // same ID + config.MinDelay, // same delay + inst.ConfigPDA, // same config PDA + inst.Admin.PublicKey(), // new "owner" attempt + solana.SystemProgramID, + config.TimelockProgram, + inst.ConfigPDA, + config.AccessControllerProgram, + inst.RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), + inst.RoleMap[timelock.Executor_Role].AccessController.PublicKey(), + inst.RoleMap[timelock.Canceller_Role].AccessController.PublicKey(), + inst.RoleMap[timelock.Bypasser_Role].AccessController.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, initErr) + + testutils.SendAndFailWith( + ctx, t, + solanaGoClient, + []solana.Instruction{ix}, + inst.Admin, // signing with the instance's admin + config.DefaultCommitment, + []string{"Error Code: AccountOwnedByWrongProgram."}, + ) + }) + + t.Run("attempt to finalize operation with the wrong timelock_id", func(t *testing.T) { + proposer0 := timelockInstances[0].RoleMap[timelock.Proposer_Role].RandomPick() + op := createAndScheduleOperation(ctx, t, solanaGoClient, timelockInstances[0], proposer0, 1) + + finalizeIx, ierr := timelock.NewFinalizeOperationInstruction( + timelockInstances[1].ID, // WRONG + op.OperationID(), + op.OperationPDA(), + timelockInstances[1].ConfigPDA, // Wrong config + timelockInstances[1].Admin.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + // this fails with constraint violation before business logic + testutils.SendAndFailWith( + ctx, + t, + solanaGoClient, + []solana.Instruction{finalizeIx}, + timelockInstances[1].Admin, + config.DefaultCommitment, + []string{"Error Code: ConstraintSeeds"}, + ) + }) + }) +} + +func createAndScheduleOperation( + ctx context.Context, + t *testing.T, + client *rpc.Client, + inst TimelockInstance, + proposer solana.PrivateKey, + delay uint64, +) timelockutil.Operation { + salt, err := timelockutil.SimpleSalt() + require.NoError(t, err) + + op := timelockutil.Operation{ + TimelockID: inst.ID, + Predecessor: config.TimelockEmptyOpID, + Salt: salt, + Delay: delay, + } + + preloadIxs, err := timelockutil.GetPreloadOperationIxs(inst.ID, op, proposer.PublicKey()) + require.NoError(t, err) + for _, ix := range preloadIxs { + testutils.SendAndConfirm(ctx, t, client, []solana.Instruction{ix}, proposer, config.DefaultCommitment) + } + + scheduleIx, ierr := timelock.NewScheduleBatchInstruction( + inst.ID, + op.OperationID(), + op.Delay, + op.OperationPDA(), + inst.ConfigPDA, + inst.RoleMap[timelock.Proposer_Role].AccessController.PublicKey(), + proposer.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, ierr) + + testutils.SendAndConfirm(ctx, t, client, []solana.Instruction{scheduleIx}, proposer, config.DefaultCommitment) + return op +} diff --git a/chains/solana/contracts/tests/mcms/timelock_rbac_test.go b/chains/solana/contracts/tests/mcms/timelock_rbac_test.go index c5d436512..80a909de2 100644 --- a/chains/solana/contracts/tests/mcms/timelock_rbac_test.go +++ b/chains/solana/contracts/tests/mcms/timelock_rbac_test.go @@ -17,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/accesscontroller" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" timelockutil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" ) @@ -52,7 +51,7 @@ func TestTimelockRBAC(t *testing.T) { t.Run("setup:init access controllers", func(t *testing.T) { for _, data := range roleMap { - initAccIxs, ierr := timelockutil.InitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) + initAccIxs, ierr := timelockutil.GetInitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) require.NoError(t, ierr) testutils.SendAndConfirm(ctx, t, solanaGoClient, initAccIxs, admin, config.DefaultCommitment, common.AddSigners(data.AccessController)) @@ -80,8 +79,9 @@ func TestTimelockRBAC(t *testing.T) { require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) initTimelockIx, ierr := timelock.NewInitializeInstruction( + config.TestTimelockID, config.MinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), anotherAdmin.PublicKey(), solana.SystemProgramID, config.TimelockProgram, @@ -98,7 +98,7 @@ func TestTimelockRBAC(t *testing.T) { require.NotNil(t, result) }) - t.Run("setup:init timelock program", func(t *testing.T) { + t.Run("setup:initialize timelock instance", func(t *testing.T) { // get program data account data, accErr := solanaGoClient.GetAccountInfoWithOpts(ctx, config.TimelockProgram, &rpc.GetAccountInfoOpts{ Commitment: config.DefaultCommitment, @@ -113,8 +113,9 @@ func TestTimelockRBAC(t *testing.T) { require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) initTimelockIx, ierr := timelock.NewInitializeInstruction( + config.TestTimelockID, config.MinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), solana.SystemProgramID, config.TimelockProgram, @@ -130,7 +131,7 @@ func TestTimelockRBAC(t *testing.T) { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initTimelockIx}, admin, config.DefaultCommitment) var configAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if err != nil { require.NoError(t, err, "failed to get account info") } @@ -146,8 +147,9 @@ func TestTimelockRBAC(t *testing.T) { t.Run("timelock:ownership", func(t *testing.T) { t.Run("fail to transfer ownership when not owner", func(t *testing.T) { instruction, ierr := timelock.NewTransferOwnershipInstruction( + config.TestTimelockID, anotherAdmin.PublicKey(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), user.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -157,8 +159,9 @@ func TestTimelockRBAC(t *testing.T) { t.Run("Current owner cannot propose self", func(t *testing.T) { instruction, ierr := timelock.NewTransferOwnershipInstruction( + config.TestTimelockID, admin.PublicKey(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -168,8 +171,9 @@ func TestTimelockRBAC(t *testing.T) { t.Run("successfully transfer ownership", func(t *testing.T) { instruction, ierr := timelock.NewTransferOwnershipInstruction( + config.TestTimelockID, anotherAdmin.PublicKey(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -179,7 +183,8 @@ func TestTimelockRBAC(t *testing.T) { t.Run("Fail to accept ownership when not proposed_owner", func(t *testing.T) { instruction, ierr := timelock.NewAcceptOwnershipInstruction( - config.TimelockConfigPDA, + config.TestTimelockID, + timelockutil.GetConfigPDA(config.TestTimelockID), user.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -189,7 +194,8 @@ func TestTimelockRBAC(t *testing.T) { t.Run("anotherAdmin becomes owner", func(t *testing.T) { instruction, ierr := timelock.NewAcceptOwnershipInstruction( - config.TimelockConfigPDA, + config.TestTimelockID, + timelockutil.GetConfigPDA(config.TestTimelockID), anotherAdmin.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -198,7 +204,7 @@ func TestTimelockRBAC(t *testing.T) { // Validate proposed set to 0-address after accepting ownership var configAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if err != nil { require.NoError(t, err, "failed to get account info") } @@ -209,8 +215,9 @@ func TestTimelockRBAC(t *testing.T) { // get it back t.Run("retrieve back ownership to admin", func(t *testing.T) { tix, ierr := timelock.NewTransferOwnershipInstruction( + config.TestTimelockID, admin.PublicKey(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), anotherAdmin.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -218,7 +225,8 @@ func TestTimelockRBAC(t *testing.T) { require.NotNil(t, result) aix, aerr := timelock.NewAcceptOwnershipInstruction( - config.TimelockConfigPDA, + config.TestTimelockID, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, aerr) @@ -226,7 +234,7 @@ func TestTimelockRBAC(t *testing.T) { require.NotNil(t, result) var configAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if err != nil { require.NoError(t, err, "failed to get account info") } @@ -242,7 +250,7 @@ func TestTimelockRBAC(t *testing.T) { for _, account := range data.Accounts { addresses = append(addresses, account.PublicKey()) } - batchAddAccessIxs, baerr := timelockutil.BatchAddAccessIxs(ctx, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) + batchAddAccessIxs, baerr := timelockutil.GetBatchAddAccessIxs(ctx, config.TestTimelockID, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) require.NoError(t, baerr) for _, ix := range batchAddAccessIxs { @@ -258,32 +266,34 @@ func TestTimelockRBAC(t *testing.T) { }) t.Run("rbac: schedule and cancel a timelock operation", func(t *testing.T) { - salt, serr := mcms.SimpleSalt() + salt, serr := timelockutil.SimpleSalt() require.NoError(t, serr) nonExecutableOp := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: uint64(1), } - ix := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), config.TimelockSignerPDA).Build() + ix := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)).Build() nonExecutableOp.AddInstruction(ix, []solana.PublicKey{}) t.Run("rbac: when try to schedule from non proposer role, it fails", func(t *testing.T) { nonProposer := roleMap[timelock.Executor_Role].RandomPick() ac := roleMap[timelock.Proposer_Role].AccessController - ixs, prierr := timelockutil.PreloadOperationIxs(nonExecutableOp, nonProposer.PublicKey()) + ixs, prierr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, nonExecutableOp, nonProposer.PublicKey()) require.NoError(t, prierr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, nonProposer, config.DefaultCommitment) } ix, scerr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, nonExecutableOp.OperationID(), nonExecutableOp.Delay, nonExecutableOp.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), nonProposer.PublicKey(), ).ValidateAndBuild() @@ -309,10 +319,11 @@ func TestTimelockRBAC(t *testing.T) { require.False(t, found, "Account %s should not be in the AccessList", proposer.PublicKey()) ix, scerr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, nonExecutableOp.OperationID(), nonExecutableOp.Delay, nonExecutableOp.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), proposer.PublicKey(), ).ValidateAndBuild() @@ -332,27 +343,29 @@ func TestTimelockRBAC(t *testing.T) { require.NoError(t, ferr) require.True(t, found, "Account %s should be in the AccessList", proposer.PublicKey()) - salt, serr := mcms.SimpleSalt() + salt, serr := timelockutil.SimpleSalt() require.NoError(t, serr) nonExecutableOp2 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: uint64(1), } - ix := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), config.TimelockSignerPDA).Build() + ix := system.NewTransferInstruction(1*solana.LAMPORTS_PER_SOL, admin.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)).Build() nonExecutableOp2.AddInstruction(ix, []solana.PublicKey{}) - ixs, prerr := timelockutil.PreloadOperationIxs(nonExecutableOp2, proposer.PublicKey()) + ixs, prerr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, nonExecutableOp2, proposer.PublicKey()) require.NoError(t, prerr) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer, config.DefaultCommitment) } sbix, sberr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, nonExecutableOp2.OperationID(), nonExecutableOp2.Delay, nonExecutableOp2.OperationPDA(), // formerly uploaded - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), proposer.PublicKey(), ).ValidateAndBuild() @@ -401,9 +414,10 @@ func TestTimelockRBAC(t *testing.T) { ac := roleMap[timelock.Proposer_Role].AccessController ix, cerr := timelock.NewCancelInstruction( + config.TestTimelockID, nonExecutableOp2.OperationID(), nonExecutableOp2.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), signer.PublicKey(), ).ValidateAndBuild() @@ -419,9 +433,10 @@ func TestTimelockRBAC(t *testing.T) { ac := roleMap[timelock.Canceller_Role].AccessController ix, cerr := timelock.NewCancelInstruction( + config.TestTimelockID, nonExecutableOp2.OperationID(), nonExecutableOp2.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), signer.PublicKey(), ).ValidateAndBuild() @@ -436,9 +451,10 @@ func TestTimelockRBAC(t *testing.T) { ac := roleMap[timelock.Canceller_Role].AccessController ix, cerr := timelock.NewCancelInstruction( + config.TestTimelockID, nonExecutableOp2.OperationID(), nonExecutableOp2.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), ac.PublicKey(), signer.PublicKey(), ).ValidateAndBuild() @@ -471,8 +487,9 @@ func TestTimelockRBAC(t *testing.T) { signer := roleMap[timelock.Proposer_Role].RandomPick() ix, ierr := timelock.NewUpdateDelayInstruction( + config.TestTimelockID, newMinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), signer.PublicKey(), ).ValidateAndBuild() require.NoError(t, ierr) @@ -485,14 +502,15 @@ func TestTimelockRBAC(t *testing.T) { signer := admin var oldConfigAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &oldConfigAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &oldConfigAccount) if err != nil { require.NoError(t, err, "failed to get account info") } ix, err := timelock.NewUpdateDelayInstruction( + config.TestTimelockID, newMinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), signer.PublicKey(), ).ValidateAndBuild() require.NoError(t, err) @@ -511,7 +529,7 @@ func TestTimelockRBAC(t *testing.T) { require.Equal(t, newMinDelay, event.NewDuration) var newConfigAccount timelock.Config - err = common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &newConfigAccount) + err = common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &newConfigAccount) if err != nil { require.NoError(t, err, "failed to get account info") } diff --git a/chains/solana/contracts/tests/mcms/timelock_schedule_execute_test.go b/chains/solana/contracts/tests/mcms/timelock_schedule_execute_test.go index e88f65b7b..13e49eac1 100644 --- a/chains/solana/contracts/tests/mcms/timelock_schedule_execute_test.go +++ b/chains/solana/contracts/tests/mcms/timelock_schedule_execute_test.go @@ -2,6 +2,7 @@ package contracts import ( "strconv" + "sync" "testing" "time" @@ -20,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/accesscontroller" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" timelockutil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" ) @@ -70,7 +70,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("setup:init access controllers", func(t *testing.T) { for _, data := range roleMap { - initAccIxs, initAccIxsErr := timelockutil.InitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) + initAccIxs, initAccIxsErr := timelockutil.GetInitAccessControllersIxs(ctx, data.AccessController.PublicKey(), admin, solanaGoClient) require.NoError(t, initAccIxsErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, initAccIxs, admin, config.DefaultCommitment, common.AddSigners(data.AccessController)) @@ -82,7 +82,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { } } }) - t.Run("setup:init timelock program", func(t *testing.T) { + t.Run("setup:initialize timelock instance", func(t *testing.T) { // get program data account data, accErr := solanaGoClient.GetAccountInfoWithOpts(ctx, config.TimelockProgram, &rpc.GetAccountInfoOpts{ Commitment: config.DefaultCommitment, @@ -97,8 +97,9 @@ func TestTimelockScheduleAndExecute(t *testing.T) { require.NoError(t, bin.UnmarshalBorsh(&programData, data.Bytes())) initTimelockIx, initErr := timelock.NewInitializeInstruction( + config.TestTimelockID, config.MinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), solana.SystemProgramID, config.TimelockProgram, @@ -114,7 +115,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{initTimelockIx}, admin, config.DefaultCommitment) var configAccount timelock.Config - cfgErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + cfgErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) if cfgErr != nil { require.NoError(t, cfgErr, "failed to get account info") } @@ -133,7 +134,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { for _, account := range data.Accounts { addresses = append(addresses, account.PublicKey()) } - batchAddAccessIxs, batchAddAccessIxsErr := timelockutil.BatchAddAccessIxs(ctx, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) + batchAddAccessIxs, batchAddAccessIxsErr := timelockutil.GetBatchAddAccessIxs(ctx, config.TestTimelockID, data.AccessController.PublicKey(), role, addresses, admin, config.BatchAddAccessChunkSize, solanaGoClient) require.NoError(t, batchAddAccessIxsErr) for _, ix := range batchAddAccessIxs { @@ -153,8 +154,9 @@ func TestTimelockScheduleAndExecute(t *testing.T) { newMinDelay := uint64(1) ix, updateDelayIxErr := timelock.NewUpdateDelayInstruction( + config.TestTimelockID, newMinDelay, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, updateDelayIxErr) @@ -163,7 +165,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { require.NotNil(t, result) var configAccount timelock.Config - getConfigAccountErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment, &configAccount) + getConfigAccountErr := common.GetAccountDataBorshInto(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment, &configAccount) require.NoError(t, getConfigAccountErr, "failed to get account info") require.Equal(t, newMinDelay, configAccount.MinDelay, "MinDelay is not updated") @@ -172,7 +174,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("setup: wsol transfer operation", func(t *testing.T) { requiredAmount := allowance.recipient - fundPDAIx := system.NewTransferInstruction(allowance.timelockAuthority, admin.PublicKey(), config.TimelockSignerPDA).Build() + fundPDAIx := system.NewTransferInstruction(allowance.timelockAuthority, admin.PublicKey(), timelockutil.GetSignerPDA(config.TestTimelockID)).Build() createAdminATAIx, _, caErr := tokens.CreateAssociatedTokenAccount(tokenProgram, wsol, admin.PublicKey(), admin.PublicKey()) require.NoError(t, caErr) @@ -196,7 +198,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { tokenProgram, adminATA, wsol, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), admin.PublicKey(), nil, ) @@ -209,7 +211,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { timelockAuthorityBalance, tlBalanceErr := solanaGoClient.GetBalance( ctx, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), config.DefaultCommitment, ) require.NoError(t, tlBalanceErr) @@ -225,9 +227,10 @@ func TestTimelockScheduleAndExecute(t *testing.T) { }) t.Run("success: schedule and execute operations", func(t *testing.T) { - salt1, err := mcms.SimpleSalt() + salt1, err := timelockutil.SimpleSalt() require.NoError(t, err) op1 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt1, Delay: 2, @@ -236,14 +239,15 @@ func TestTimelockScheduleAndExecute(t *testing.T) { tokenProgram, wsol, recipient.PublicKey(), - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), ) require.NoError(t, ciErr) op1.AddInstruction(cIx, []solana.PublicKey{solana.TokenProgramID, solana.SPLAssociatedTokenAccountProgramID}) - salt2, err := mcms.SimpleSalt() + salt2, err := timelockutil.SimpleSalt() require.NoError(t, err) op2 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: op1.OperationID(), Salt: salt2, Delay: 2, @@ -256,15 +260,16 @@ func TestTimelockScheduleAndExecute(t *testing.T) { adminATA, wsol, recipientATA, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), nil, ) require.NoError(t, tiErr) op2.AddInstruction(tIx, []solana.PublicKey{tokenProgram}) - salt3, err := mcms.SimpleSalt() + salt3, err := timelockutil.SimpleSalt() require.NoError(t, err) op3 := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: op1.OperationID(), Salt: salt3, Delay: 300, // enough delay to assert OperationNotReady error @@ -277,7 +282,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { adminATA, wsol, recipientATA, - config.TimelockSignerPDA, + timelockutil.GetSignerPDA(config.TestTimelockID), nil, ) require.NoError(t, atErr) @@ -292,7 +297,7 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("success: schedule all operations", func(t *testing.T) { for _, op := range []timelockutil.Operation{op1, op2, op3} { - invalidIxs, ierr := timelockutil.PreloadOperationIxs(op, proposer.PublicKey()) + invalidIxs, ierr := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, proposer.PublicKey()) require.NoError(t, ierr) for _, ix := range invalidIxs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer, config.DefaultCommitment) @@ -301,9 +306,10 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("clear operation", func(t *testing.T) { // clear instructions so that we can reinitialize the operation clearIx, ciErr := timelock.NewClearOperationInstruction( + config.TestTimelockID, op.OperationID(), op.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), proposer.PublicKey(), ).ValidateAndBuild() require.NoError(t, ciErr) @@ -314,17 +320,18 @@ func TestTimelockScheduleAndExecute(t *testing.T) { }) // re-preload instructions - ixs, err := timelockutil.PreloadOperationIxs(op, proposer.PublicKey()) + ixs, err := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, proposer.PublicKey()) require.NoError(t, err) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer, config.DefaultCommitment) } ix, ixVErr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, op.OperationID(), op.Delay, op.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), proposerAccessController, proposer.PublicKey(), ).ValidateAndBuild() @@ -359,10 +366,11 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("fail: OperationAlreadyExists", func(t *testing.T) { ix := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, op1.OperationID(), op1.Delay, op1.OperationPDA(), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), proposerAccessController, proposer.PublicKey(), ).Build() @@ -378,11 +386,12 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("fail: should provide the right dependency pda", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op2.OperationPDA(), // wrong dependency - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), executorAccessController, executor.PublicKey(), ) @@ -396,11 +405,12 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("fail: not able to execute op2 before dependency(op1) execution", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op1.OperationPDA(), // not executed yet - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), executorAccessController, executor.PublicKey(), ) @@ -415,11 +425,12 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("success: op1 executed", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op1.OperationID(), op1.OperationPDA(), config.TimelockEmptyOpID, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), executorAccessController, executor.PublicKey(), ) @@ -461,11 +472,12 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("success: op2 executed", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op2.OperationID(), op2.OperationPDA(), op1.OperationPDA(), - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), executorAccessController, executor.PublicKey(), ) @@ -519,11 +531,12 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("failure on execution try: op3 is not ready", func(t *testing.T) { ix := timelock.NewExecuteBatchInstruction( + config.TestTimelockID, op3.OperationID(), op3.OperationPDA(), config.TimelockEmptyOpID, - config.TimelockConfigPDA, - config.TimelockSignerPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), + timelockutil.GetSignerPDA(config.TestTimelockID), executorAccessController, executor.PublicKey(), ) @@ -539,13 +552,15 @@ func TestTimelockScheduleAndExecute(t *testing.T) { }) t.Run("function blockers", func(t *testing.T) { + t.Parallel() proposer := roleMap[timelock.Proposer_Role].RandomPick() proposerAccessController := roleMap[timelock.Proposer_Role].AccessController.PublicKey() - salt, err := mcms.SimpleSalt() + salt, err := timelockutil.SimpleSalt() require.NoError(t, err) op := timelockutil.Operation{ + TimelockID: config.TestTimelockID, Predecessor: config.TimelockEmptyOpID, Salt: salt, Delay: 1, @@ -562,22 +577,24 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("blocks initialize function", func(t *testing.T) { bIx, bIxErr := timelock.NewBlockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8(external_program_cpi_stub.Instruction_Initialize.Bytes()), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, bIxErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{bIx}, admin, config.DefaultCommitment) - blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment) + blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment) require.NoError(t, bserr) require.Contains(t, blockedSelectors, external_program_cpi_stub.Instruction_Initialize.Bytes()) }) t.Run("not able to block function that is already blocked", func(t *testing.T) { bbIx, bbIxErr := timelock.NewBlockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8(external_program_cpi_stub.Instruction_Initialize.Bytes()), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, bbIxErr) @@ -587,17 +604,18 @@ func TestTimelockScheduleAndExecute(t *testing.T) { id := op.OperationID() operationPDA := op.OperationPDA() - ixs, err := timelockutil.PreloadOperationIxs(op, proposer.PublicKey()) + ixs, err := timelockutil.GetPreloadOperationIxs(config.TestTimelockID, op, proposer.PublicKey()) require.NoError(t, err) for _, ix := range ixs { testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, proposer, config.DefaultCommitment) } scIx, scIxVErr := timelock.NewScheduleBatchInstruction( + config.TestTimelockID, id, op.Delay, operationPDA, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), proposerAccessController, proposer.PublicKey(), ).ValidateAndBuild() @@ -607,22 +625,24 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("unblocks initialize function", func(t *testing.T) { bIx, bIxErr := timelock.NewUnblockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8(external_program_cpi_stub.Instruction_Initialize.Bytes()), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, bIxErr) testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{bIx}, admin, config.DefaultCommitment) - blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment) + blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment) require.NoError(t, bserr) require.NotContains(t, blockedSelectors, external_program_cpi_stub.Instruction_Initialize.Bytes()) }) t.Run("not able to unblock function that is not blocked", func(t *testing.T) { bbIx, bbIxErr := timelock.NewUnblockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8(external_program_cpi_stub.Instruction_Initialize.Bytes()), - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, bbIxErr) @@ -647,15 +667,16 @@ func TestTimelockScheduleAndExecute(t *testing.T) { t.Run("can't register more than MAX_SELECTOR", func(t *testing.T) { // check if it's empty - oldBlockedSelectors, gberr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment) + oldBlockedSelectors, gberr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment) require.NoError(t, gberr) require.Empty(t, oldBlockedSelectors) ixs := []solana.Instruction{} for i := 0; i < config.MaxFunctionSelectorLen; i++ { ix, nberr := timelock.NewBlockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8{byte(i)}, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, nberr) @@ -663,26 +684,36 @@ func TestTimelockScheduleAndExecute(t *testing.T) { ixs = append(ixs, ix) } - // max selectors at 32, two transactions happen here - chunkSize := 16 + // max selectors at 128 + chunkSize := 18 + var wg sync.WaitGroup + for i := 0; i < len(ixs); i += chunkSize { + wg.Add(1) end := i + chunkSize if end > len(ixs) { end = len(ixs) } chunk := ixs[i:end] - testutils.SendAndConfirm(ctx, t, solanaGoClient, chunk, admin, config.DefaultCommitment) + + go func(chunk []solana.Instruction) { + defer wg.Done() + testutils.SendAndConfirm(ctx, t, solanaGoClient, chunk, admin, config.DefaultCommitment) + }(chunk) } + wg.Wait() + // check if it's full - blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, config.TimelockConfigPDA, config.DefaultCommitment) + blockedSelectors, bserr := timelockutil.GetBlockedFunctionSelectors(ctx, solanaGoClient, timelockutil.GetConfigPDA(config.TestTimelockID), config.DefaultCommitment) require.NoError(t, bserr) require.Equal(t, config.MaxFunctionSelectorLen, len(blockedSelectors)) // try one more ix, nberr := timelock.NewBlockFunctionSelectorInstruction( + config.TestTimelockID, [8]uint8{255}, - config.TimelockConfigPDA, + timelockutil.GetConfigPDA(config.TestTimelockID), admin.PublicKey(), ).ValidateAndBuild() require.NoError(t, nberr) diff --git a/chains/solana/gobindings/mcm/AcceptOwnership.go b/chains/solana/gobindings/mcm/AcceptOwnership.go index 295421634..837944aa6 100644 --- a/chains/solana/gobindings/mcm/AcceptOwnership.go +++ b/chains/solana/gobindings/mcm/AcceptOwnership.go @@ -12,7 +12,7 @@ import ( // AcceptOwnership is the `acceptOwnership` instruction. type AcceptOwnership struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 // [0] = [WRITE] config // @@ -28,9 +28,9 @@ func NewAcceptOwnershipInstructionBuilder() *AcceptOwnership { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *AcceptOwnership) SetMultisigName(multisigName [32]uint8) *AcceptOwnership { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *AcceptOwnership) SetMultisigId(multisigId [32]uint8) *AcceptOwnership { + inst.MultisigId = &multisigId return inst } @@ -76,8 +76,8 @@ func (inst AcceptOwnership) ValidateAndBuild() (*Instruction, error) { func (inst *AcceptOwnership) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } } @@ -103,7 +103,7 @@ func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) }) // Accounts of the instruction: @@ -116,16 +116,16 @@ func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { } func (obj AcceptOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } return nil } func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -135,12 +135,12 @@ func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (er // NewAcceptOwnershipInstruction declares a new AcceptOwnership instruction with the provided parameters and accounts. func NewAcceptOwnershipInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *AcceptOwnership { return NewAcceptOwnershipInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetConfigAccount(config). SetAuthorityAccount(authority) } diff --git a/chains/solana/gobindings/mcm/AppendSignatures.go b/chains/solana/gobindings/mcm/AppendSignatures.go index 923f5e3bc..8ef6f3d6e 100644 --- a/chains/solana/gobindings/mcm/AppendSignatures.go +++ b/chains/solana/gobindings/mcm/AppendSignatures.go @@ -12,7 +12,7 @@ import ( // AppendSignatures is the `appendSignatures` instruction. type AppendSignatures struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 Root *[32]uint8 ValidUntil *uint32 SignaturesBatch *[]Signature @@ -31,9 +31,9 @@ func NewAppendSignaturesInstructionBuilder() *AppendSignatures { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *AppendSignatures) SetMultisigName(multisigName [32]uint8) *AppendSignatures { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *AppendSignatures) SetMultisigId(multisigId [32]uint8) *AppendSignatures { + inst.MultisigId = &multisigId return inst } @@ -97,8 +97,8 @@ func (inst AppendSignatures) ValidateAndBuild() (*Instruction, error) { func (inst *AppendSignatures) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.Root == nil { return errors.New("Root parameter is not set") @@ -133,7 +133,7 @@ func (inst *AppendSignatures) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) paramsBranch.Child(ag_format.Param(" ValidUntil", *inst.ValidUntil)) paramsBranch.Child(ag_format.Param("SignaturesBatch", *inst.SignaturesBatch)) @@ -149,8 +149,8 @@ func (inst *AppendSignatures) EncodeToTree(parent ag_treeout.Branches) { } func (obj AppendSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -172,8 +172,8 @@ func (obj AppendSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err return nil } func (obj *AppendSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -198,7 +198,7 @@ func (obj *AppendSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (e // NewAppendSignaturesInstruction declares a new AppendSignatures instruction with the provided parameters and accounts. func NewAppendSignaturesInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, root [32]uint8, validUntil uint32, signaturesBatch []Signature, @@ -206,7 +206,7 @@ func NewAppendSignaturesInstruction( signatures ag_solanago.PublicKey, authority ag_solanago.PublicKey) *AppendSignatures { return NewAppendSignaturesInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetRoot(root). SetValidUntil(validUntil). SetSignaturesBatch(signaturesBatch). diff --git a/chains/solana/gobindings/mcm/AppendSigners.go b/chains/solana/gobindings/mcm/AppendSigners.go index 0bb023156..ec5b68224 100644 --- a/chains/solana/gobindings/mcm/AppendSigners.go +++ b/chains/solana/gobindings/mcm/AppendSigners.go @@ -12,7 +12,7 @@ import ( // AppendSigners is the `appendSigners` instruction. type AppendSigners struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 SignersBatch *[][20]uint8 // [0] = [] multisigConfig @@ -31,9 +31,9 @@ func NewAppendSignersInstructionBuilder() *AppendSigners { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *AppendSigners) SetMultisigName(multisigName [32]uint8) *AppendSigners { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *AppendSigners) SetMultisigId(multisigId [32]uint8) *AppendSigners { + inst.MultisigId = &multisigId return inst } @@ -96,8 +96,8 @@ func (inst AppendSigners) ValidateAndBuild() (*Instruction, error) { func (inst *AppendSigners) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.SignersBatch == nil { return errors.New("SignersBatch parameter is not set") @@ -129,7 +129,7 @@ func (inst *AppendSigners) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param("SignersBatch", *inst.SignersBatch)) }) @@ -144,8 +144,8 @@ func (inst *AppendSigners) EncodeToTree(parent ag_treeout.Branches) { } func (obj AppendSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -157,8 +157,8 @@ func (obj AppendSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err err return nil } func (obj *AppendSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -173,14 +173,14 @@ func (obj *AppendSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err // NewAppendSignersInstruction declares a new AppendSigners instruction with the provided parameters and accounts. func NewAppendSignersInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, signersBatch [][20]uint8, // Accounts: multisigConfig ag_solanago.PublicKey, configSigners ag_solanago.PublicKey, authority ag_solanago.PublicKey) *AppendSigners { return NewAppendSignersInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetSignersBatch(signersBatch). SetMultisigConfigAccount(multisigConfig). SetConfigSignersAccount(configSigners). diff --git a/chains/solana/gobindings/mcm/ClearSignatures.go b/chains/solana/gobindings/mcm/ClearSignatures.go index b511c24cf..afd3ca8e3 100644 --- a/chains/solana/gobindings/mcm/ClearSignatures.go +++ b/chains/solana/gobindings/mcm/ClearSignatures.go @@ -12,9 +12,9 @@ import ( // ClearSignatures is the `clearSignatures` instruction. type ClearSignatures struct { - MultisigName *[32]uint8 - Root *[32]uint8 - ValidUntil *uint32 + MultisigId *[32]uint8 + Root *[32]uint8 + ValidUntil *uint32 // [0] = [WRITE] signatures // @@ -30,9 +30,9 @@ func NewClearSignaturesInstructionBuilder() *ClearSignatures { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *ClearSignatures) SetMultisigName(multisigName [32]uint8) *ClearSignatures { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *ClearSignatures) SetMultisigId(multisigId [32]uint8) *ClearSignatures { + inst.MultisigId = &multisigId return inst } @@ -90,8 +90,8 @@ func (inst ClearSignatures) ValidateAndBuild() (*Instruction, error) { func (inst *ClearSignatures) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.Root == nil { return errors.New("Root parameter is not set") @@ -123,9 +123,9 @@ func (inst *ClearSignatures) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) - paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) - paramsBranch.Child(ag_format.Param(" ValidUntil", *inst.ValidUntil)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) + paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) + paramsBranch.Child(ag_format.Param("ValidUntil", *inst.ValidUntil)) }) // Accounts of the instruction: @@ -138,8 +138,8 @@ func (inst *ClearSignatures) EncodeToTree(parent ag_treeout.Branches) { } func (obj ClearSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -156,8 +156,8 @@ func (obj ClearSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err e return nil } func (obj *ClearSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -177,14 +177,14 @@ func (obj *ClearSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (er // NewClearSignaturesInstruction declares a new ClearSignatures instruction with the provided parameters and accounts. func NewClearSignaturesInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, root [32]uint8, validUntil uint32, // Accounts: signatures ag_solanago.PublicKey, authority ag_solanago.PublicKey) *ClearSignatures { return NewClearSignaturesInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetRoot(root). SetValidUntil(validUntil). SetSignaturesAccount(signatures). diff --git a/chains/solana/gobindings/mcm/ClearSigners.go b/chains/solana/gobindings/mcm/ClearSigners.go index 7d20a37e3..04dbe0cf4 100644 --- a/chains/solana/gobindings/mcm/ClearSigners.go +++ b/chains/solana/gobindings/mcm/ClearSigners.go @@ -12,7 +12,7 @@ import ( // ClearSigners is the `clearSigners` instruction. type ClearSigners struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 // [0] = [] multisigConfig // @@ -30,9 +30,9 @@ func NewClearSignersInstructionBuilder() *ClearSigners { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *ClearSigners) SetMultisigName(multisigName [32]uint8) *ClearSigners { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *ClearSigners) SetMultisigId(multisigId [32]uint8) *ClearSigners { + inst.MultisigId = &multisigId return inst } @@ -89,8 +89,8 @@ func (inst ClearSigners) ValidateAndBuild() (*Instruction, error) { func (inst *ClearSigners) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } } @@ -119,7 +119,7 @@ func (inst *ClearSigners) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) }) // Accounts of the instruction: @@ -133,16 +133,16 @@ func (inst *ClearSigners) EncodeToTree(parent ag_treeout.Branches) { } func (obj ClearSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } return nil } func (obj *ClearSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -152,13 +152,13 @@ func (obj *ClearSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err e // NewClearSignersInstruction declares a new ClearSigners instruction with the provided parameters and accounts. func NewClearSignersInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, // Accounts: multisigConfig ag_solanago.PublicKey, configSigners ag_solanago.PublicKey, authority ag_solanago.PublicKey) *ClearSigners { return NewClearSignersInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetMultisigConfigAccount(multisigConfig). SetConfigSignersAccount(configSigners). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/mcm/Execute.go b/chains/solana/gobindings/mcm/Execute.go index cf265ad60..6985e7794 100644 --- a/chains/solana/gobindings/mcm/Execute.go +++ b/chains/solana/gobindings/mcm/Execute.go @@ -12,11 +12,11 @@ import ( // Execute is the `execute` instruction. type Execute struct { - MultisigName *[32]uint8 - ChainId *uint64 - Nonce *uint64 - Data *[]byte - Proof *[][32]uint8 + MultisigId *[32]uint8 + ChainId *uint64 + Nonce *uint64 + Data *[]byte + Proof *[][32]uint8 // [0] = [WRITE] multisigConfig // @@ -40,9 +40,9 @@ func NewExecuteInstructionBuilder() *Execute { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *Execute) SetMultisigName(multisigName [32]uint8) *Execute { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *Execute) SetMultisigId(multisigId [32]uint8) *Execute { + inst.MultisigId = &multisigId return inst } @@ -156,8 +156,8 @@ func (inst Execute) ValidateAndBuild() (*Instruction, error) { func (inst *Execute) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.ChainId == nil { return errors.New("ChainId parameter is not set") @@ -207,11 +207,11 @@ func (inst *Execute) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=5]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) - paramsBranch.Child(ag_format.Param(" ChainId", *inst.ChainId)) - paramsBranch.Child(ag_format.Param(" Nonce", *inst.Nonce)) - paramsBranch.Child(ag_format.Param(" Data", *inst.Data)) - paramsBranch.Child(ag_format.Param(" Proof", *inst.Proof)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) + paramsBranch.Child(ag_format.Param(" ChainId", *inst.ChainId)) + paramsBranch.Child(ag_format.Param(" Nonce", *inst.Nonce)) + paramsBranch.Child(ag_format.Param(" Data", *inst.Data)) + paramsBranch.Child(ag_format.Param(" Proof", *inst.Proof)) }) // Accounts of the instruction: @@ -228,8 +228,8 @@ func (inst *Execute) EncodeToTree(parent ag_treeout.Branches) { } func (obj Execute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -256,8 +256,8 @@ func (obj Execute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { return nil } func (obj *Execute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -287,7 +287,7 @@ func (obj *Execute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) // NewExecuteInstruction declares a new Execute instruction with the provided parameters and accounts. func NewExecuteInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, chainId uint64, nonce uint64, data []byte, @@ -300,7 +300,7 @@ func NewExecuteInstruction( multisigSigner ag_solanago.PublicKey, authority ag_solanago.PublicKey) *Execute { return NewExecuteInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetChainId(chainId). SetNonce(nonce). SetData(data). diff --git a/chains/solana/gobindings/mcm/FinalizeSignatures.go b/chains/solana/gobindings/mcm/FinalizeSignatures.go index 9e090b282..78feba789 100644 --- a/chains/solana/gobindings/mcm/FinalizeSignatures.go +++ b/chains/solana/gobindings/mcm/FinalizeSignatures.go @@ -12,9 +12,9 @@ import ( // FinalizeSignatures is the `finalizeSignatures` instruction. type FinalizeSignatures struct { - MultisigName *[32]uint8 - Root *[32]uint8 - ValidUntil *uint32 + MultisigId *[32]uint8 + Root *[32]uint8 + ValidUntil *uint32 // [0] = [WRITE] signatures // @@ -30,9 +30,9 @@ func NewFinalizeSignaturesInstructionBuilder() *FinalizeSignatures { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *FinalizeSignatures) SetMultisigName(multisigName [32]uint8) *FinalizeSignatures { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *FinalizeSignatures) SetMultisigId(multisigId [32]uint8) *FinalizeSignatures { + inst.MultisigId = &multisigId return inst } @@ -90,8 +90,8 @@ func (inst FinalizeSignatures) ValidateAndBuild() (*Instruction, error) { func (inst *FinalizeSignatures) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.Root == nil { return errors.New("Root parameter is not set") @@ -123,9 +123,9 @@ func (inst *FinalizeSignatures) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) - paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) - paramsBranch.Child(ag_format.Param(" ValidUntil", *inst.ValidUntil)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) + paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) + paramsBranch.Child(ag_format.Param("ValidUntil", *inst.ValidUntil)) }) // Accounts of the instruction: @@ -138,8 +138,8 @@ func (inst *FinalizeSignatures) EncodeToTree(parent ag_treeout.Branches) { } func (obj FinalizeSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -156,8 +156,8 @@ func (obj FinalizeSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (er return nil } func (obj *FinalizeSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -177,14 +177,14 @@ func (obj *FinalizeSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) // NewFinalizeSignaturesInstruction declares a new FinalizeSignatures instruction with the provided parameters and accounts. func NewFinalizeSignaturesInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, root [32]uint8, validUntil uint32, // Accounts: signatures ag_solanago.PublicKey, authority ag_solanago.PublicKey) *FinalizeSignatures { return NewFinalizeSignaturesInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetRoot(root). SetValidUntil(validUntil). SetSignaturesAccount(signatures). diff --git a/chains/solana/gobindings/mcm/FinalizeSigners.go b/chains/solana/gobindings/mcm/FinalizeSigners.go index c6439a697..47c6fab53 100644 --- a/chains/solana/gobindings/mcm/FinalizeSigners.go +++ b/chains/solana/gobindings/mcm/FinalizeSigners.go @@ -12,7 +12,7 @@ import ( // FinalizeSigners is the `finalizeSigners` instruction. type FinalizeSigners struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 // [0] = [] multisigConfig // @@ -30,9 +30,9 @@ func NewFinalizeSignersInstructionBuilder() *FinalizeSigners { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *FinalizeSigners) SetMultisigName(multisigName [32]uint8) *FinalizeSigners { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *FinalizeSigners) SetMultisigId(multisigId [32]uint8) *FinalizeSigners { + inst.MultisigId = &multisigId return inst } @@ -89,8 +89,8 @@ func (inst FinalizeSigners) ValidateAndBuild() (*Instruction, error) { func (inst *FinalizeSigners) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } } @@ -119,7 +119,7 @@ func (inst *FinalizeSigners) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) }) // Accounts of the instruction: @@ -133,16 +133,16 @@ func (inst *FinalizeSigners) EncodeToTree(parent ag_treeout.Branches) { } func (obj FinalizeSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } return nil } func (obj *FinalizeSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -152,13 +152,13 @@ func (obj *FinalizeSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (er // NewFinalizeSignersInstruction declares a new FinalizeSigners instruction with the provided parameters and accounts. func NewFinalizeSignersInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, // Accounts: multisigConfig ag_solanago.PublicKey, configSigners ag_solanago.PublicKey, authority ag_solanago.PublicKey) *FinalizeSigners { return NewFinalizeSignersInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetMultisigConfigAccount(multisigConfig). SetConfigSignersAccount(configSigners). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/mcm/InitSignatures.go b/chains/solana/gobindings/mcm/InitSignatures.go index 418ffebb7..d2f5aaa95 100644 --- a/chains/solana/gobindings/mcm/InitSignatures.go +++ b/chains/solana/gobindings/mcm/InitSignatures.go @@ -12,7 +12,7 @@ import ( // InitSignatures is the `initSignatures` instruction. type InitSignatures struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 Root *[32]uint8 ValidUntil *uint32 TotalSignatures *uint8 @@ -33,9 +33,9 @@ func NewInitSignaturesInstructionBuilder() *InitSignatures { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *InitSignatures) SetMultisigName(multisigName [32]uint8) *InitSignatures { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *InitSignatures) SetMultisigId(multisigId [32]uint8) *InitSignatures { + inst.MultisigId = &multisigId return inst } @@ -110,8 +110,8 @@ func (inst InitSignatures) ValidateAndBuild() (*Instruction, error) { func (inst *InitSignatures) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.Root == nil { return errors.New("Root parameter is not set") @@ -149,7 +149,7 @@ func (inst *InitSignatures) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) paramsBranch.Child(ag_format.Param(" ValidUntil", *inst.ValidUntil)) paramsBranch.Child(ag_format.Param("TotalSignatures", *inst.TotalSignatures)) @@ -166,8 +166,8 @@ func (inst *InitSignatures) EncodeToTree(parent ag_treeout.Branches) { } func (obj InitSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -189,8 +189,8 @@ func (obj InitSignatures) MarshalWithEncoder(encoder *ag_binary.Encoder) (err er return nil } func (obj *InitSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -215,7 +215,7 @@ func (obj *InitSignatures) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err // NewInitSignaturesInstruction declares a new InitSignatures instruction with the provided parameters and accounts. func NewInitSignaturesInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, root [32]uint8, validUntil uint32, totalSignatures uint8, @@ -224,7 +224,7 @@ func NewInitSignaturesInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *InitSignatures { return NewInitSignaturesInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetRoot(root). SetValidUntil(validUntil). SetTotalSignatures(totalSignatures). diff --git a/chains/solana/gobindings/mcm/InitSigners.go b/chains/solana/gobindings/mcm/InitSigners.go index bbc72af6a..01fc3ea98 100644 --- a/chains/solana/gobindings/mcm/InitSigners.go +++ b/chains/solana/gobindings/mcm/InitSigners.go @@ -12,7 +12,7 @@ import ( // InitSigners is the `initSigners` instruction. type InitSigners struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 TotalSigners *uint8 // [0] = [] multisigConfig @@ -33,9 +33,9 @@ func NewInitSignersInstructionBuilder() *InitSigners { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *InitSigners) SetMultisigName(multisigName [32]uint8) *InitSigners { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *InitSigners) SetMultisigId(multisigId [32]uint8) *InitSigners { + inst.MultisigId = &multisigId return inst } @@ -109,8 +109,8 @@ func (inst InitSigners) ValidateAndBuild() (*Instruction, error) { func (inst *InitSigners) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.TotalSigners == nil { return errors.New("TotalSigners parameter is not set") @@ -145,7 +145,7 @@ func (inst *InitSigners) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param("TotalSigners", *inst.TotalSigners)) }) @@ -161,8 +161,8 @@ func (inst *InitSigners) EncodeToTree(parent ag_treeout.Branches) { } func (obj InitSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -174,8 +174,8 @@ func (obj InitSigners) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error return nil } func (obj *InitSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -190,7 +190,7 @@ func (obj *InitSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err er // NewInitSignersInstruction declares a new InitSigners instruction with the provided parameters and accounts. func NewInitSignersInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, totalSigners uint8, // Accounts: multisigConfig ag_solanago.PublicKey, @@ -198,7 +198,7 @@ func NewInitSignersInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *InitSigners { return NewInitSignersInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetTotalSigners(totalSigners). SetMultisigConfigAccount(multisigConfig). SetConfigSignersAccount(configSigners). diff --git a/chains/solana/gobindings/mcm/Initialize.go b/chains/solana/gobindings/mcm/Initialize.go index b61c0095f..cc15fa359 100644 --- a/chains/solana/gobindings/mcm/Initialize.go +++ b/chains/solana/gobindings/mcm/Initialize.go @@ -10,11 +10,11 @@ import ( ag_treeout "github.com/gagliardetto/treeout" ) -// initialize a new multisig configuration, store the chain_id and multisig_name -// multisig_name is a unique identifier for the multisig configuration(32 bytes, left-padded) +// initialize a new multisig configuration, store the chain_id and multisig_id +// multisig_id is a unique identifier for the multisig configuration(32 bytes, left-padded) type Initialize struct { - ChainId *uint64 - MultisigName *[32]uint8 + ChainId *uint64 + MultisigId *[32]uint8 // [0] = [WRITE] multisigConfig // @@ -46,9 +46,9 @@ func (inst *Initialize) SetChainId(chainId uint64) *Initialize { return inst } -// SetMultisigName sets the "multisigName" parameter. -func (inst *Initialize) SetMultisigName(multisigName [32]uint8) *Initialize { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *Initialize) SetMultisigId(multisigId [32]uint8) *Initialize { + inst.MultisigId = &multisigId return inst } @@ -152,8 +152,8 @@ func (inst *Initialize) Validate() error { if inst.ChainId == nil { return errors.New("ChainId parameter is not set") } - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } } @@ -194,8 +194,8 @@ func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" ChainId", *inst.ChainId)) - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" ChainId", *inst.ChainId)) + paramsBranch.Child(ag_format.Param("MultisigId", *inst.MultisigId)) }) // Accounts of the instruction: @@ -218,8 +218,8 @@ func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) if err != nil { return err } - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -231,8 +231,8 @@ func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err err if err != nil { return err } - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -243,7 +243,7 @@ func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err err func NewInitializeInstruction( // Parameters: chainId uint64, - multisigName [32]uint8, + multisigId [32]uint8, // Accounts: multisigConfig ag_solanago.PublicKey, authority ag_solanago.PublicKey, @@ -254,7 +254,7 @@ func NewInitializeInstruction( expiringRootAndOpCount ag_solanago.PublicKey) *Initialize { return NewInitializeInstructionBuilder(). SetChainId(chainId). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetMultisigConfigAccount(multisigConfig). SetAuthorityAccount(authority). SetSystemProgramAccount(systemProgram). diff --git a/chains/solana/gobindings/mcm/SetConfig.go b/chains/solana/gobindings/mcm/SetConfig.go index 7fd44d5dc..6eb8ea7a0 100644 --- a/chains/solana/gobindings/mcm/SetConfig.go +++ b/chains/solana/gobindings/mcm/SetConfig.go @@ -12,7 +12,7 @@ import ( // SetConfig is the `setConfig` instruction. type SetConfig struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 SignerGroups *[]byte GroupQuorums *[32]uint8 GroupParents *[32]uint8 @@ -40,9 +40,9 @@ func NewSetConfigInstructionBuilder() *SetConfig { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *SetConfig) SetMultisigName(multisigName [32]uint8) *SetConfig { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *SetConfig) SetMultisigId(multisigId [32]uint8) *SetConfig { + inst.MultisigId = &multisigId return inst } @@ -156,8 +156,8 @@ func (inst SetConfig) ValidateAndBuild() (*Instruction, error) { func (inst *SetConfig) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.SignerGroups == nil { return errors.New("SignerGroups parameter is not set") @@ -207,7 +207,7 @@ func (inst *SetConfig) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=5]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param("SignerGroups", *inst.SignerGroups)) paramsBranch.Child(ag_format.Param("GroupQuorums", *inst.GroupQuorums)) paramsBranch.Child(ag_format.Param("GroupParents", *inst.GroupParents)) @@ -228,8 +228,8 @@ func (inst *SetConfig) EncodeToTree(parent ag_treeout.Branches) { } func (obj SetConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -256,8 +256,8 @@ func (obj SetConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) return nil } func (obj *SetConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -287,7 +287,7 @@ func (obj *SetConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err erro // NewSetConfigInstruction declares a new SetConfig instruction with the provided parameters and accounts. func NewSetConfigInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, signerGroups []byte, groupQuorums [32]uint8, groupParents [32]uint8, @@ -300,7 +300,7 @@ func NewSetConfigInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *SetConfig { return NewSetConfigInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetSignerGroups(signerGroups). SetGroupQuorums(groupQuorums). SetGroupParents(groupParents). diff --git a/chains/solana/gobindings/mcm/SetRoot.go b/chains/solana/gobindings/mcm/SetRoot.go index 48c41dc7a..aff38d574 100644 --- a/chains/solana/gobindings/mcm/SetRoot.go +++ b/chains/solana/gobindings/mcm/SetRoot.go @@ -12,7 +12,7 @@ import ( // SetRoot is the `setRoot` instruction. type SetRoot struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 Root *[32]uint8 ValidUntil *uint32 Metadata *RootMetadataInput @@ -42,9 +42,9 @@ func NewSetRootInstructionBuilder() *SetRoot { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *SetRoot) SetMultisigName(multisigName [32]uint8) *SetRoot { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *SetRoot) SetMultisigId(multisigId [32]uint8) *SetRoot { + inst.MultisigId = &multisigId return inst } @@ -169,8 +169,8 @@ func (inst SetRoot) ValidateAndBuild() (*Instruction, error) { func (inst *SetRoot) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.Root == nil { return errors.New("Root parameter is not set") @@ -223,7 +223,7 @@ func (inst *SetRoot) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=5]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param(" Root", *inst.Root)) paramsBranch.Child(ag_format.Param(" ValidUntil", *inst.ValidUntil)) paramsBranch.Child(ag_format.Param(" Metadata", *inst.Metadata)) @@ -245,8 +245,8 @@ func (inst *SetRoot) EncodeToTree(parent ag_treeout.Branches) { } func (obj SetRoot) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -273,8 +273,8 @@ func (obj SetRoot) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { return nil } func (obj *SetRoot) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -304,7 +304,7 @@ func (obj *SetRoot) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) // NewSetRootInstruction declares a new SetRoot instruction with the provided parameters and accounts. func NewSetRootInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, root [32]uint8, validUntil uint32, metadata RootMetadataInput, @@ -318,7 +318,7 @@ func NewSetRootInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *SetRoot { return NewSetRootInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetRoot(root). SetValidUntil(validUntil). SetMetadata(metadata). diff --git a/chains/solana/gobindings/mcm/TransferOwnership.go b/chains/solana/gobindings/mcm/TransferOwnership.go index dacffff5f..b8bde772c 100644 --- a/chains/solana/gobindings/mcm/TransferOwnership.go +++ b/chains/solana/gobindings/mcm/TransferOwnership.go @@ -12,7 +12,7 @@ import ( // TransferOwnership is the `transferOwnership` instruction. type TransferOwnership struct { - MultisigName *[32]uint8 + MultisigId *[32]uint8 ProposedOwner *ag_solanago.PublicKey // [0] = [WRITE] config @@ -29,9 +29,9 @@ func NewTransferOwnershipInstructionBuilder() *TransferOwnership { return nd } -// SetMultisigName sets the "multisigName" parameter. -func (inst *TransferOwnership) SetMultisigName(multisigName [32]uint8) *TransferOwnership { - inst.MultisigName = &multisigName +// SetMultisigId sets the "multisigId" parameter. +func (inst *TransferOwnership) SetMultisigId(multisigId [32]uint8) *TransferOwnership { + inst.MultisigId = &multisigId return inst } @@ -83,8 +83,8 @@ func (inst TransferOwnership) ValidateAndBuild() (*Instruction, error) { func (inst *TransferOwnership) Validate() error { // Check whether all (required) parameters are set: { - if inst.MultisigName == nil { - return errors.New("MultisigName parameter is not set") + if inst.MultisigId == nil { + return errors.New("MultisigId parameter is not set") } if inst.ProposedOwner == nil { return errors.New("ProposedOwner parameter is not set") @@ -113,7 +113,7 @@ func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" MultisigName", *inst.MultisigName)) + paramsBranch.Child(ag_format.Param(" MultisigId", *inst.MultisigId)) paramsBranch.Child(ag_format.Param("ProposedOwner", *inst.ProposedOwner)) }) @@ -127,8 +127,8 @@ func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { } func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -140,8 +140,8 @@ func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err return nil } func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } @@ -156,13 +156,13 @@ func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) ( // NewTransferOwnershipInstruction declares a new TransferOwnership instruction with the provided parameters and accounts. func NewTransferOwnershipInstruction( // Parameters: - multisigName [32]uint8, + multisigId [32]uint8, proposedOwner ag_solanago.PublicKey, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *TransferOwnership { return NewTransferOwnershipInstructionBuilder(). - SetMultisigName(multisigName). + SetMultisigId(multisigId). SetProposedOwner(proposedOwner). SetConfigAccount(config). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/mcm/accounts.go b/chains/solana/gobindings/mcm/accounts.go index f7bb22546..56f429593 100644 --- a/chains/solana/gobindings/mcm/accounts.go +++ b/chains/solana/gobindings/mcm/accounts.go @@ -74,7 +74,7 @@ func (obj *ConfigSigners) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err type MultisigConfig struct { ChainId uint64 - MultisigName [32]uint8 + MultisigId [32]uint8 Owner ag_solanago.PublicKey ProposedOwner ag_solanago.PublicKey GroupQuorums [32]uint8 @@ -95,8 +95,8 @@ func (obj MultisigConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err er if err != nil { return err } - // Serialize `MultisigName` param: - err = encoder.Encode(obj.MultisigName) + // Serialize `MultisigId` param: + err = encoder.Encode(obj.MultisigId) if err != nil { return err } @@ -147,8 +147,8 @@ func (obj *MultisigConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err if err != nil { return err } - // Deserialize `MultisigName`: - err = decoder.Decode(&obj.MultisigName) + // Deserialize `MultisigId`: + err = decoder.Decode(&obj.MultisigId) if err != nil { return err } diff --git a/chains/solana/gobindings/mcm/instructions.go b/chains/solana/gobindings/mcm/instructions.go index 1c6db2533..e46a3777a 100644 --- a/chains/solana/gobindings/mcm/instructions.go +++ b/chains/solana/gobindings/mcm/instructions.go @@ -1,5 +1,5 @@ // This is mcm program supporting multiple instances of multisig configuration -// A single deployed program manages multiple multisig states(configurations) identified by multisig_name +// A single deployed program manages multiple multisig states(configurations) identified by multisig_id // Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. package mcm @@ -30,8 +30,8 @@ func init() { } var ( - // initialize a new multisig configuration, store the chain_id and multisig_name - // multisig_name is a unique identifier for the multisig configuration(32 bytes, left-padded) + // initialize a new multisig configuration, store the chain_id and multisig_id + // multisig_id is a unique identifier for the multisig configuration(32 bytes, left-padded) Instruction_Initialize = ag_binary.TypeID([8]byte{175, 175, 109, 31, 13, 152, 155, 237}) Instruction_TransferOwnership = ag_binary.TypeID([8]byte{65, 177, 215, 73, 53, 45, 99, 47}) diff --git a/chains/solana/gobindings/timelock/AcceptOwnership.go b/chains/solana/gobindings/timelock/AcceptOwnership.go index c95e33898..570ad3547 100644 --- a/chains/solana/gobindings/timelock/AcceptOwnership.go +++ b/chains/solana/gobindings/timelock/AcceptOwnership.go @@ -12,6 +12,7 @@ import ( // AcceptOwnership is the `acceptOwnership` instruction. type AcceptOwnership struct { + TimelockId *[32]uint8 // [0] = [WRITE] config // @@ -27,6 +28,12 @@ func NewAcceptOwnershipInstructionBuilder() *AcceptOwnership { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *AcceptOwnership) SetTimelockId(timelockId [32]uint8) *AcceptOwnership { + inst.TimelockId = &timelockId + return inst +} + // SetConfigAccount sets the "config" account. func (inst *AcceptOwnership) SetConfigAccount(config ag_solanago.PublicKey) *AcceptOwnership { inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() @@ -67,6 +74,13 @@ func (inst AcceptOwnership) ValidateAndBuild() (*Instruction, error) { } func (inst *AcceptOwnership) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } + } + // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { @@ -88,7 +102,9 @@ func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + }) // Accounts of the instruction: instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { @@ -100,18 +116,31 @@ func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { } func (obj AcceptOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } return nil } func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } return nil } // NewAcceptOwnershipInstruction declares a new AcceptOwnership instruction with the provided parameters and accounts. func NewAcceptOwnershipInstruction( + // Parameters: + timelockId [32]uint8, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *AcceptOwnership { return NewAcceptOwnershipInstructionBuilder(). + SetTimelockId(timelockId). SetConfigAccount(config). SetAuthorityAccount(authority) } diff --git a/chains/solana/gobindings/timelock/AppendInstructions.go b/chains/solana/gobindings/timelock/AppendInstructions.go index e2b0f8b9a..b26cba4d4 100644 --- a/chains/solana/gobindings/timelock/AppendInstructions.go +++ b/chains/solana/gobindings/timelock/AppendInstructions.go @@ -12,6 +12,7 @@ import ( // AppendInstructions is the `appendInstructions` instruction. type AppendInstructions struct { + TimelockId *[32]uint8 Id *[32]uint8 InstructionsBatch *[]InstructionData @@ -33,6 +34,12 @@ func NewAppendInstructionsInstructionBuilder() *AppendInstructions { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *AppendInstructions) SetTimelockId(timelockId [32]uint8) *AppendInstructions { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *AppendInstructions) SetId(id [32]uint8) *AppendInstructions { inst.Id = &id @@ -109,6 +116,9 @@ func (inst AppendInstructions) ValidateAndBuild() (*Instruction, error) { func (inst *AppendInstructions) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -144,7 +154,8 @@ func (inst *AppendInstructions) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" TimelockId", *inst.TimelockId)) paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) paramsBranch.Child(ag_format.Param("InstructionsBatch", *inst.InstructionsBatch)) }) @@ -161,6 +172,11 @@ func (inst *AppendInstructions) EncodeToTree(parent ag_treeout.Branches) { } func (obj AppendInstructions) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -174,6 +190,11 @@ func (obj AppendInstructions) MarshalWithEncoder(encoder *ag_binary.Encoder) (er return nil } func (obj *AppendInstructions) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -190,6 +211,7 @@ func (obj *AppendInstructions) UnmarshalWithDecoder(decoder *ag_binary.Decoder) // NewAppendInstructionsInstruction declares a new AppendInstructions instruction with the provided parameters and accounts. func NewAppendInstructionsInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, instructionsBatch []InstructionData, // Accounts: @@ -198,6 +220,7 @@ func NewAppendInstructionsInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *AppendInstructions { return NewAppendInstructionsInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetInstructionsBatch(instructionsBatch). SetOperationAccount(operation). diff --git a/chains/solana/gobindings/timelock/BatchAddAccess.go b/chains/solana/gobindings/timelock/BatchAddAccess.go index ce331614b..4a8c82547 100644 --- a/chains/solana/gobindings/timelock/BatchAddAccess.go +++ b/chains/solana/gobindings/timelock/BatchAddAccess.go @@ -12,7 +12,8 @@ import ( // BatchAddAccess is the `batchAddAccess` instruction. type BatchAddAccess struct { - Role *Role + TimelockId *[32]uint8 + Role *Role // [0] = [] config // @@ -32,6 +33,12 @@ func NewBatchAddAccessInstructionBuilder() *BatchAddAccess { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *BatchAddAccess) SetTimelockId(timelockId [32]uint8) *BatchAddAccess { + inst.TimelockId = &timelockId + return inst +} + // SetRole sets the "role" parameter. func (inst *BatchAddAccess) SetRole(role Role) *BatchAddAccess { inst.Role = &role @@ -102,6 +109,9 @@ func (inst BatchAddAccess) ValidateAndBuild() (*Instruction, error) { func (inst *BatchAddAccess) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Role == nil { return errors.New("Role parameter is not set") } @@ -134,8 +144,9 @@ func (inst *BatchAddAccess) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Role", *inst.Role)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Role", *inst.Role)) }) // Accounts of the instruction: @@ -150,6 +161,11 @@ func (inst *BatchAddAccess) EncodeToTree(parent ag_treeout.Branches) { } func (obj BatchAddAccess) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Role` param: err = encoder.Encode(obj.Role) if err != nil { @@ -158,6 +174,11 @@ func (obj BatchAddAccess) MarshalWithEncoder(encoder *ag_binary.Encoder) (err er return nil } func (obj *BatchAddAccess) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Role`: err = decoder.Decode(&obj.Role) if err != nil { @@ -169,6 +190,7 @@ func (obj *BatchAddAccess) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err // NewBatchAddAccessInstruction declares a new BatchAddAccess instruction with the provided parameters and accounts. func NewBatchAddAccessInstruction( // Parameters: + timelockId [32]uint8, role Role, // Accounts: config ag_solanago.PublicKey, @@ -176,6 +198,7 @@ func NewBatchAddAccessInstruction( roleAccessController ag_solanago.PublicKey, authority ag_solanago.PublicKey) *BatchAddAccess { return NewBatchAddAccessInstructionBuilder(). + SetTimelockId(timelockId). SetRole(role). SetConfigAccount(config). SetAccessControllerProgramAccount(accessControllerProgram). diff --git a/chains/solana/gobindings/timelock/BlockFunctionSelector.go b/chains/solana/gobindings/timelock/BlockFunctionSelector.go index dad390be2..70add28cf 100644 --- a/chains/solana/gobindings/timelock/BlockFunctionSelector.go +++ b/chains/solana/gobindings/timelock/BlockFunctionSelector.go @@ -12,7 +12,8 @@ import ( // BlockFunctionSelector is the `blockFunctionSelector` instruction. type BlockFunctionSelector struct { - Selector *[8]uint8 + TimelockId *[32]uint8 + Selector *[8]uint8 // [0] = [WRITE] config // @@ -28,6 +29,12 @@ func NewBlockFunctionSelectorInstructionBuilder() *BlockFunctionSelector { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *BlockFunctionSelector) SetTimelockId(timelockId [32]uint8) *BlockFunctionSelector { + inst.TimelockId = &timelockId + return inst +} + // SetSelector sets the "selector" parameter. func (inst *BlockFunctionSelector) SetSelector(selector [8]uint8) *BlockFunctionSelector { inst.Selector = &selector @@ -76,6 +83,9 @@ func (inst BlockFunctionSelector) ValidateAndBuild() (*Instruction, error) { func (inst *BlockFunctionSelector) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Selector == nil { return errors.New("Selector parameter is not set") } @@ -102,8 +112,9 @@ func (inst *BlockFunctionSelector) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Selector", *inst.Selector)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Selector", *inst.Selector)) }) // Accounts of the instruction: @@ -116,6 +127,11 @@ func (inst *BlockFunctionSelector) EncodeToTree(parent ag_treeout.Branches) { } func (obj BlockFunctionSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Selector` param: err = encoder.Encode(obj.Selector) if err != nil { @@ -124,6 +140,11 @@ func (obj BlockFunctionSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) return nil } func (obj *BlockFunctionSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Selector`: err = decoder.Decode(&obj.Selector) if err != nil { @@ -135,11 +156,13 @@ func (obj *BlockFunctionSelector) UnmarshalWithDecoder(decoder *ag_binary.Decode // NewBlockFunctionSelectorInstruction declares a new BlockFunctionSelector instruction with the provided parameters and accounts. func NewBlockFunctionSelectorInstruction( // Parameters: + timelockId [32]uint8, selector [8]uint8, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *BlockFunctionSelector { return NewBlockFunctionSelectorInstructionBuilder(). + SetTimelockId(timelockId). SetSelector(selector). SetConfigAccount(config). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/timelock/BypasserExecuteBatch.go b/chains/solana/gobindings/timelock/BypasserExecuteBatch.go index 3a07483ff..bdd04312a 100644 --- a/chains/solana/gobindings/timelock/BypasserExecuteBatch.go +++ b/chains/solana/gobindings/timelock/BypasserExecuteBatch.go @@ -12,7 +12,8 @@ import ( // BypasserExecuteBatch is the `bypasserExecuteBatch` instruction. type BypasserExecuteBatch struct { - Id *[32]uint8 + TimelockId *[32]uint8 + Id *[32]uint8 // [0] = [WRITE] operation // @@ -34,6 +35,12 @@ func NewBypasserExecuteBatchInstructionBuilder() *BypasserExecuteBatch { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *BypasserExecuteBatch) SetTimelockId(timelockId [32]uint8) *BypasserExecuteBatch { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *BypasserExecuteBatch) SetId(id [32]uint8) *BypasserExecuteBatch { inst.Id = &id @@ -115,6 +122,9 @@ func (inst BypasserExecuteBatch) ValidateAndBuild() (*Instruction, error) { func (inst *BypasserExecuteBatch) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -150,8 +160,9 @@ func (inst *BypasserExecuteBatch) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Id", *inst.Id)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) }) // Accounts of the instruction: @@ -167,6 +178,11 @@ func (inst *BypasserExecuteBatch) EncodeToTree(parent ag_treeout.Branches) { } func (obj BypasserExecuteBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -175,6 +191,11 @@ func (obj BypasserExecuteBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) ( return nil } func (obj *BypasserExecuteBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -186,6 +207,7 @@ func (obj *BypasserExecuteBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder // NewBypasserExecuteBatchInstruction declares a new BypasserExecuteBatch instruction with the provided parameters and accounts. func NewBypasserExecuteBatchInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, // Accounts: operation ag_solanago.PublicKey, @@ -194,6 +216,7 @@ func NewBypasserExecuteBatchInstruction( roleAccessController ag_solanago.PublicKey, authority ag_solanago.PublicKey) *BypasserExecuteBatch { return NewBypasserExecuteBatchInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetOperationAccount(operation). SetConfigAccount(config). diff --git a/chains/solana/gobindings/timelock/Cancel.go b/chains/solana/gobindings/timelock/Cancel.go index 4970af812..07b0cb06d 100644 --- a/chains/solana/gobindings/timelock/Cancel.go +++ b/chains/solana/gobindings/timelock/Cancel.go @@ -12,7 +12,8 @@ import ( // Cancel is the `cancel` instruction. type Cancel struct { - Id *[32]uint8 + TimelockId *[32]uint8 + Id *[32]uint8 // [0] = [WRITE] operation // @@ -32,6 +33,12 @@ func NewCancelInstructionBuilder() *Cancel { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *Cancel) SetTimelockId(timelockId [32]uint8) *Cancel { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *Cancel) SetId(id [32]uint8) *Cancel { inst.Id = &id @@ -102,6 +109,9 @@ func (inst Cancel) ValidateAndBuild() (*Instruction, error) { func (inst *Cancel) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -134,8 +144,9 @@ func (inst *Cancel) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Id", *inst.Id)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) }) // Accounts of the instruction: @@ -150,6 +161,11 @@ func (inst *Cancel) EncodeToTree(parent ag_treeout.Branches) { } func (obj Cancel) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -158,6 +174,11 @@ func (obj Cancel) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { return nil } func (obj *Cancel) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -169,6 +190,7 @@ func (obj *Cancel) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) // NewCancelInstruction declares a new Cancel instruction with the provided parameters and accounts. func NewCancelInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, // Accounts: operation ag_solanago.PublicKey, @@ -176,6 +198,7 @@ func NewCancelInstruction( roleAccessController ag_solanago.PublicKey, authority ag_solanago.PublicKey) *Cancel { return NewCancelInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetOperationAccount(operation). SetConfigAccount(config). diff --git a/chains/solana/gobindings/timelock/ClearOperation.go b/chains/solana/gobindings/timelock/ClearOperation.go index 8ef60bd3c..5e8dd6a7f 100644 --- a/chains/solana/gobindings/timelock/ClearOperation.go +++ b/chains/solana/gobindings/timelock/ClearOperation.go @@ -12,7 +12,8 @@ import ( // ClearOperation is the `clearOperation` instruction. type ClearOperation struct { - Id *[32]uint8 + TimelockId *[32]uint8 + Id *[32]uint8 // [0] = [WRITE] operation // @@ -30,6 +31,12 @@ func NewClearOperationInstructionBuilder() *ClearOperation { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *ClearOperation) SetTimelockId(timelockId [32]uint8) *ClearOperation { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *ClearOperation) SetId(id [32]uint8) *ClearOperation { inst.Id = &id @@ -89,6 +96,9 @@ func (inst ClearOperation) ValidateAndBuild() (*Instruction, error) { func (inst *ClearOperation) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -118,8 +128,9 @@ func (inst *ClearOperation) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Id", *inst.Id)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) }) // Accounts of the instruction: @@ -133,6 +144,11 @@ func (inst *ClearOperation) EncodeToTree(parent ag_treeout.Branches) { } func (obj ClearOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -141,6 +157,11 @@ func (obj ClearOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (err er return nil } func (obj *ClearOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -152,12 +173,14 @@ func (obj *ClearOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err // NewClearOperationInstruction declares a new ClearOperation instruction with the provided parameters and accounts. func NewClearOperationInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, // Accounts: operation ag_solanago.PublicKey, config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *ClearOperation { return NewClearOperationInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetOperationAccount(operation). SetConfigAccount(config). diff --git a/chains/solana/gobindings/timelock/ExecuteBatch.go b/chains/solana/gobindings/timelock/ExecuteBatch.go index 76b97b14c..67aacbed2 100644 --- a/chains/solana/gobindings/timelock/ExecuteBatch.go +++ b/chains/solana/gobindings/timelock/ExecuteBatch.go @@ -12,7 +12,8 @@ import ( // ExecuteBatch is the `executeBatch` instruction. type ExecuteBatch struct { - Id *[32]uint8 + TimelockId *[32]uint8 + Id *[32]uint8 // [0] = [WRITE] operation // @@ -36,6 +37,12 @@ func NewExecuteBatchInstructionBuilder() *ExecuteBatch { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *ExecuteBatch) SetTimelockId(timelockId [32]uint8) *ExecuteBatch { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *ExecuteBatch) SetId(id [32]uint8) *ExecuteBatch { inst.Id = &id @@ -128,6 +135,9 @@ func (inst ExecuteBatch) ValidateAndBuild() (*Instruction, error) { func (inst *ExecuteBatch) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -166,8 +176,9 @@ func (inst *ExecuteBatch) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Id", *inst.Id)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) }) // Accounts of the instruction: @@ -184,6 +195,11 @@ func (inst *ExecuteBatch) EncodeToTree(parent ag_treeout.Branches) { } func (obj ExecuteBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -192,6 +208,11 @@ func (obj ExecuteBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) (err erro return nil } func (obj *ExecuteBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -203,6 +224,7 @@ func (obj *ExecuteBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err e // NewExecuteBatchInstruction declares a new ExecuteBatch instruction with the provided parameters and accounts. func NewExecuteBatchInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, // Accounts: operation ag_solanago.PublicKey, @@ -212,6 +234,7 @@ func NewExecuteBatchInstruction( roleAccessController ag_solanago.PublicKey, authority ag_solanago.PublicKey) *ExecuteBatch { return NewExecuteBatchInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetOperationAccount(operation). SetPredecessorOperationAccount(predecessorOperation). diff --git a/chains/solana/gobindings/timelock/FinalizeOperation.go b/chains/solana/gobindings/timelock/FinalizeOperation.go index 2387ef651..46d9f6935 100644 --- a/chains/solana/gobindings/timelock/FinalizeOperation.go +++ b/chains/solana/gobindings/timelock/FinalizeOperation.go @@ -12,7 +12,8 @@ import ( // FinalizeOperation is the `finalizeOperation` instruction. type FinalizeOperation struct { - Id *[32]uint8 + TimelockId *[32]uint8 + Id *[32]uint8 // [0] = [WRITE] operation // @@ -30,6 +31,12 @@ func NewFinalizeOperationInstructionBuilder() *FinalizeOperation { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *FinalizeOperation) SetTimelockId(timelockId [32]uint8) *FinalizeOperation { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *FinalizeOperation) SetId(id [32]uint8) *FinalizeOperation { inst.Id = &id @@ -89,6 +96,9 @@ func (inst FinalizeOperation) ValidateAndBuild() (*Instruction, error) { func (inst *FinalizeOperation) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -118,8 +128,9 @@ func (inst *FinalizeOperation) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Id", *inst.Id)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) }) // Accounts of the instruction: @@ -133,6 +144,11 @@ func (inst *FinalizeOperation) EncodeToTree(parent ag_treeout.Branches) { } func (obj FinalizeOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -141,6 +157,11 @@ func (obj FinalizeOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (err return nil } func (obj *FinalizeOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -152,12 +173,14 @@ func (obj *FinalizeOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) ( // NewFinalizeOperationInstruction declares a new FinalizeOperation instruction with the provided parameters and accounts. func NewFinalizeOperationInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, // Accounts: operation ag_solanago.PublicKey, config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *FinalizeOperation { return NewFinalizeOperationInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetOperationAccount(operation). SetConfigAccount(config). diff --git a/chains/solana/gobindings/timelock/Initialize.go b/chains/solana/gobindings/timelock/Initialize.go index 1ce4b0e0e..cab1d7ee4 100644 --- a/chains/solana/gobindings/timelock/Initialize.go +++ b/chains/solana/gobindings/timelock/Initialize.go @@ -12,7 +12,8 @@ import ( // Initialize is the `initialize` instruction. type Initialize struct { - MinDelay *uint64 + TimelockId *[32]uint8 + MinDelay *uint64 // [0] = [WRITE] config // @@ -44,6 +45,12 @@ func NewInitializeInstructionBuilder() *Initialize { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *Initialize) SetTimelockId(timelockId [32]uint8) *Initialize { + inst.TimelockId = &timelockId + return inst +} + // SetMinDelay sets the "minDelay" parameter. func (inst *Initialize) SetMinDelay(minDelay uint64) *Initialize { inst.MinDelay = &minDelay @@ -180,6 +187,9 @@ func (inst Initialize) ValidateAndBuild() (*Instruction, error) { func (inst *Initialize) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.MinDelay == nil { return errors.New("MinDelay parameter is not set") } @@ -230,8 +240,9 @@ func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("MinDelay", *inst.MinDelay)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" MinDelay", *inst.MinDelay)) }) // Accounts of the instruction: @@ -252,6 +263,11 @@ func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { } func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `MinDelay` param: err = encoder.Encode(obj.MinDelay) if err != nil { @@ -260,6 +276,11 @@ func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) return nil } func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `MinDelay`: err = decoder.Decode(&obj.MinDelay) if err != nil { @@ -271,6 +292,7 @@ func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err err // NewInitializeInstruction declares a new Initialize instruction with the provided parameters and accounts. func NewInitializeInstruction( // Parameters: + timelockId [32]uint8, minDelay uint64, // Accounts: config ag_solanago.PublicKey, @@ -284,6 +306,7 @@ func NewInitializeInstruction( cancellerRoleAccessController ag_solanago.PublicKey, bypasserRoleAccessController ag_solanago.PublicKey) *Initialize { return NewInitializeInstructionBuilder(). + SetTimelockId(timelockId). SetMinDelay(minDelay). SetConfigAccount(config). SetAuthorityAccount(authority). diff --git a/chains/solana/gobindings/timelock/InitializeOperation.go b/chains/solana/gobindings/timelock/InitializeOperation.go index 61dead7e1..47c1223a6 100644 --- a/chains/solana/gobindings/timelock/InitializeOperation.go +++ b/chains/solana/gobindings/timelock/InitializeOperation.go @@ -12,6 +12,7 @@ import ( // InitializeOperation is the `initializeOperation` instruction. type InitializeOperation struct { + TimelockId *[32]uint8 Id *[32]uint8 Predecessor *[32]uint8 Salt *[32]uint8 @@ -35,6 +36,12 @@ func NewInitializeOperationInstructionBuilder() *InitializeOperation { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *InitializeOperation) SetTimelockId(timelockId [32]uint8) *InitializeOperation { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *InitializeOperation) SetId(id [32]uint8) *InitializeOperation { inst.Id = &id @@ -123,6 +130,9 @@ func (inst InitializeOperation) ValidateAndBuild() (*Instruction, error) { func (inst *InitializeOperation) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -164,7 +174,8 @@ func (inst *InitializeOperation) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + instructionBranch.Child("Params[len=5]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" TimelockId", *inst.TimelockId)) paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) paramsBranch.Child(ag_format.Param(" Predecessor", *inst.Predecessor)) paramsBranch.Child(ag_format.Param(" Salt", *inst.Salt)) @@ -183,6 +194,11 @@ func (inst *InitializeOperation) EncodeToTree(parent ag_treeout.Branches) { } func (obj InitializeOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -206,6 +222,11 @@ func (obj InitializeOperation) MarshalWithEncoder(encoder *ag_binary.Encoder) (e return nil } func (obj *InitializeOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -232,6 +253,7 @@ func (obj *InitializeOperation) UnmarshalWithDecoder(decoder *ag_binary.Decoder) // NewInitializeOperationInstruction declares a new InitializeOperation instruction with the provided parameters and accounts. func NewInitializeOperationInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, predecessor [32]uint8, salt [32]uint8, @@ -242,6 +264,7 @@ func NewInitializeOperationInstruction( authority ag_solanago.PublicKey, systemProgram ag_solanago.PublicKey) *InitializeOperation { return NewInitializeOperationInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetPredecessor(predecessor). SetSalt(salt). diff --git a/chains/solana/gobindings/timelock/ScheduleBatch.go b/chains/solana/gobindings/timelock/ScheduleBatch.go index 65de135fa..6f00df6cc 100644 --- a/chains/solana/gobindings/timelock/ScheduleBatch.go +++ b/chains/solana/gobindings/timelock/ScheduleBatch.go @@ -12,8 +12,9 @@ import ( // ScheduleBatch is the `scheduleBatch` instruction. type ScheduleBatch struct { - Id *[32]uint8 - Delay *uint64 + TimelockId *[32]uint8 + Id *[32]uint8 + Delay *uint64 // [0] = [WRITE] operation // @@ -33,6 +34,12 @@ func NewScheduleBatchInstructionBuilder() *ScheduleBatch { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *ScheduleBatch) SetTimelockId(timelockId [32]uint8) *ScheduleBatch { + inst.TimelockId = &timelockId + return inst +} + // SetId sets the "id" parameter. func (inst *ScheduleBatch) SetId(id [32]uint8) *ScheduleBatch { inst.Id = &id @@ -109,6 +116,9 @@ func (inst ScheduleBatch) ValidateAndBuild() (*Instruction, error) { func (inst *ScheduleBatch) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Id == nil { return errors.New("Id parameter is not set") } @@ -144,9 +154,10 @@ func (inst *ScheduleBatch) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) - paramsBranch.Child(ag_format.Param("Delay", *inst.Delay)) + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Id", *inst.Id)) + paramsBranch.Child(ag_format.Param(" Delay", *inst.Delay)) }) // Accounts of the instruction: @@ -161,6 +172,11 @@ func (inst *ScheduleBatch) EncodeToTree(parent ag_treeout.Branches) { } func (obj ScheduleBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Id` param: err = encoder.Encode(obj.Id) if err != nil { @@ -174,6 +190,11 @@ func (obj ScheduleBatch) MarshalWithEncoder(encoder *ag_binary.Encoder) (err err return nil } func (obj *ScheduleBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Id`: err = decoder.Decode(&obj.Id) if err != nil { @@ -190,6 +211,7 @@ func (obj *ScheduleBatch) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err // NewScheduleBatchInstruction declares a new ScheduleBatch instruction with the provided parameters and accounts. func NewScheduleBatchInstruction( // Parameters: + timelockId [32]uint8, id [32]uint8, delay uint64, // Accounts: @@ -198,6 +220,7 @@ func NewScheduleBatchInstruction( roleAccessController ag_solanago.PublicKey, authority ag_solanago.PublicKey) *ScheduleBatch { return NewScheduleBatchInstructionBuilder(). + SetTimelockId(timelockId). SetId(id). SetDelay(delay). SetOperationAccount(operation). diff --git a/chains/solana/gobindings/timelock/TransferOwnership.go b/chains/solana/gobindings/timelock/TransferOwnership.go index 1b596daf9..400b67f6d 100644 --- a/chains/solana/gobindings/timelock/TransferOwnership.go +++ b/chains/solana/gobindings/timelock/TransferOwnership.go @@ -12,6 +12,7 @@ import ( // TransferOwnership is the `transferOwnership` instruction. type TransferOwnership struct { + TimelockId *[32]uint8 ProposedOwner *ag_solanago.PublicKey // [0] = [WRITE] config @@ -28,6 +29,12 @@ func NewTransferOwnershipInstructionBuilder() *TransferOwnership { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *TransferOwnership) SetTimelockId(timelockId [32]uint8) *TransferOwnership { + inst.TimelockId = &timelockId + return inst +} + // SetProposedOwner sets the "proposedOwner" parameter. func (inst *TransferOwnership) SetProposedOwner(proposedOwner ag_solanago.PublicKey) *TransferOwnership { inst.ProposedOwner = &proposedOwner @@ -76,6 +83,9 @@ func (inst TransferOwnership) ValidateAndBuild() (*Instruction, error) { func (inst *TransferOwnership) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.ProposedOwner == nil { return errors.New("ProposedOwner parameter is not set") } @@ -102,7 +112,8 @@ func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" TimelockId", *inst.TimelockId)) paramsBranch.Child(ag_format.Param("ProposedOwner", *inst.ProposedOwner)) }) @@ -116,6 +127,11 @@ func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { } func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `ProposedOwner` param: err = encoder.Encode(obj.ProposedOwner) if err != nil { @@ -124,6 +140,11 @@ func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err return nil } func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `ProposedOwner`: err = decoder.Decode(&obj.ProposedOwner) if err != nil { @@ -135,11 +156,13 @@ func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) ( // NewTransferOwnershipInstruction declares a new TransferOwnership instruction with the provided parameters and accounts. func NewTransferOwnershipInstruction( // Parameters: + timelockId [32]uint8, proposedOwner ag_solanago.PublicKey, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *TransferOwnership { return NewTransferOwnershipInstructionBuilder(). + SetTimelockId(timelockId). SetProposedOwner(proposedOwner). SetConfigAccount(config). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/timelock/UnblockFunctionSelector.go b/chains/solana/gobindings/timelock/UnblockFunctionSelector.go index 1e336f4c5..03d84ba17 100644 --- a/chains/solana/gobindings/timelock/UnblockFunctionSelector.go +++ b/chains/solana/gobindings/timelock/UnblockFunctionSelector.go @@ -12,7 +12,8 @@ import ( // UnblockFunctionSelector is the `unblockFunctionSelector` instruction. type UnblockFunctionSelector struct { - Selector *[8]uint8 + TimelockId *[32]uint8 + Selector *[8]uint8 // [0] = [WRITE] config // @@ -28,6 +29,12 @@ func NewUnblockFunctionSelectorInstructionBuilder() *UnblockFunctionSelector { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *UnblockFunctionSelector) SetTimelockId(timelockId [32]uint8) *UnblockFunctionSelector { + inst.TimelockId = &timelockId + return inst +} + // SetSelector sets the "selector" parameter. func (inst *UnblockFunctionSelector) SetSelector(selector [8]uint8) *UnblockFunctionSelector { inst.Selector = &selector @@ -76,6 +83,9 @@ func (inst UnblockFunctionSelector) ValidateAndBuild() (*Instruction, error) { func (inst *UnblockFunctionSelector) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Selector == nil { return errors.New("Selector parameter is not set") } @@ -102,8 +112,9 @@ func (inst *UnblockFunctionSelector) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Selector", *inst.Selector)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Selector", *inst.Selector)) }) // Accounts of the instruction: @@ -116,6 +127,11 @@ func (inst *UnblockFunctionSelector) EncodeToTree(parent ag_treeout.Branches) { } func (obj UnblockFunctionSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Selector` param: err = encoder.Encode(obj.Selector) if err != nil { @@ -124,6 +140,11 @@ func (obj UnblockFunctionSelector) MarshalWithEncoder(encoder *ag_binary.Encoder return nil } func (obj *UnblockFunctionSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Selector`: err = decoder.Decode(&obj.Selector) if err != nil { @@ -135,11 +156,13 @@ func (obj *UnblockFunctionSelector) UnmarshalWithDecoder(decoder *ag_binary.Deco // NewUnblockFunctionSelectorInstruction declares a new UnblockFunctionSelector instruction with the provided parameters and accounts. func NewUnblockFunctionSelectorInstruction( // Parameters: + timelockId [32]uint8, selector [8]uint8, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *UnblockFunctionSelector { return NewUnblockFunctionSelectorInstructionBuilder(). + SetTimelockId(timelockId). SetSelector(selector). SetConfigAccount(config). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/timelock/UpdateDelay.go b/chains/solana/gobindings/timelock/UpdateDelay.go index f07a1d868..be2c06eeb 100644 --- a/chains/solana/gobindings/timelock/UpdateDelay.go +++ b/chains/solana/gobindings/timelock/UpdateDelay.go @@ -12,7 +12,8 @@ import ( // UpdateDelay is the `updateDelay` instruction. type UpdateDelay struct { - Delay *uint64 + TimelockId *[32]uint8 + Delay *uint64 // [0] = [WRITE] config // @@ -28,6 +29,12 @@ func NewUpdateDelayInstructionBuilder() *UpdateDelay { return nd } +// SetTimelockId sets the "timelockId" parameter. +func (inst *UpdateDelay) SetTimelockId(timelockId [32]uint8) *UpdateDelay { + inst.TimelockId = &timelockId + return inst +} + // SetDelay sets the "delay" parameter. func (inst *UpdateDelay) SetDelay(delay uint64) *UpdateDelay { inst.Delay = &delay @@ -76,6 +83,9 @@ func (inst UpdateDelay) ValidateAndBuild() (*Instruction, error) { func (inst *UpdateDelay) Validate() error { // Check whether all (required) parameters are set: { + if inst.TimelockId == nil { + return errors.New("TimelockId parameter is not set") + } if inst.Delay == nil { return errors.New("Delay parameter is not set") } @@ -102,8 +112,9 @@ func (inst *UpdateDelay) EncodeToTree(parent ag_treeout.Branches) { ParentFunc(func(instructionBranch ag_treeout.Branches) { // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Delay", *inst.Delay)) + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("TimelockId", *inst.TimelockId)) + paramsBranch.Child(ag_format.Param(" Delay", *inst.Delay)) }) // Accounts of the instruction: @@ -116,6 +127,11 @@ func (inst *UpdateDelay) EncodeToTree(parent ag_treeout.Branches) { } func (obj UpdateDelay) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Delay` param: err = encoder.Encode(obj.Delay) if err != nil { @@ -124,6 +140,11 @@ func (obj UpdateDelay) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error return nil } func (obj *UpdateDelay) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Delay`: err = decoder.Decode(&obj.Delay) if err != nil { @@ -135,11 +156,13 @@ func (obj *UpdateDelay) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err er // NewUpdateDelayInstruction declares a new UpdateDelay instruction with the provided parameters and accounts. func NewUpdateDelayInstruction( // Parameters: + timelockId [32]uint8, delay uint64, // Accounts: config ag_solanago.PublicKey, authority ag_solanago.PublicKey) *UpdateDelay { return NewUpdateDelayInstructionBuilder(). + SetTimelockId(timelockId). SetDelay(delay). SetConfigAccount(config). SetAuthorityAccount(authority) diff --git a/chains/solana/gobindings/timelock/accounts.go b/chains/solana/gobindings/timelock/accounts.go index ad213c0e9..701d7bb6a 100644 --- a/chains/solana/gobindings/timelock/accounts.go +++ b/chains/solana/gobindings/timelock/accounts.go @@ -9,6 +9,7 @@ import ( ) type Config struct { + TimelockId [32]uint8 Owner ag_solanago.PublicKey ProposedOwner ag_solanago.PublicKey ProposerRoleAccessController ag_solanago.PublicKey @@ -27,6 +28,11 @@ func (obj Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { if err != nil { return err } + // Serialize `TimelockId` param: + err = encoder.Encode(obj.TimelockId) + if err != nil { + return err + } // Serialize `Owner` param: err = encoder.Encode(obj.Owner) if err != nil { @@ -84,6 +90,11 @@ func (obj *Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) fmt.Sprint(discriminator[:])) } } + // Deserialize `TimelockId`: + err = decoder.Decode(&obj.TimelockId) + if err != nil { + return err + } // Deserialize `Owner`: err = decoder.Decode(&obj.Owner) if err != nil { diff --git a/chains/solana/gobindings/timelock/types.go b/chains/solana/gobindings/timelock/types.go index 430d58b9f..20632ae44 100644 --- a/chains/solana/gobindings/timelock/types.go +++ b/chains/solana/gobindings/timelock/types.go @@ -8,7 +8,7 @@ import ( ) type BlockedSelectors struct { - Xs [32][8]uint8 + Xs [128][8]uint8 Len uint64 } @@ -146,7 +146,6 @@ const ( BlockedSelector_TimelockError AlreadyBlocked_TimelockError SelectorNotFound_TimelockError - InvalidInstructionData_TimelockError MaxCapacityReached_TimelockError ) @@ -182,8 +181,6 @@ func (value TimelockError) String() string { return "AlreadyBlocked" case SelectorNotFound_TimelockError: return "SelectorNotFound" - case InvalidInstructionData_TimelockError: - return "InvalidInstructionData" case MaxCapacityReached_TimelockError: return "MaxCapacityReached" default: diff --git a/chains/solana/utils/mcms/common.go b/chains/solana/utils/mcms/common.go deleted file mode 100644 index c80578b61..000000000 --- a/chains/solana/utils/mcms/common.go +++ /dev/null @@ -1,131 +0,0 @@ -package mcms - -import ( - crypto_rand "crypto/rand" - "encoding/binary" - "errors" - "fmt" - "math" - "time" - - "golang.org/x/crypto/sha3" - - "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/eth" -) - -type McmConfigArgs struct { - MultisigName [32]uint8 - SignerAddresses [][20]uint8 - SignerGroups []byte - GroupQuorums [32]uint8 - GroupParents [32]uint8 - ClearRoot bool -} - -func NewValidMcmConfig(msigName [32]byte, signerPrivateKeys []string, signerGroups []byte, quorums []uint8, parents []uint8, clearRoot bool) (*McmConfigArgs, error) { - if len(signerGroups) == 0 { - return nil, fmt.Errorf("signerGroups cannot be empty") - } - - signers, err := eth.GetEvmSigners(signerPrivateKeys) - if err != nil { - return nil, fmt.Errorf("failed to get test EVM signers: %w", err) - } - - if len(signers) != len(signerGroups) { - return nil, fmt.Errorf("number of signers (%d) does not match length of signerGroups (%d)", len(signers), len(signerGroups)) - } - - signerAddresses := make([][20]uint8, len(signers)) - for i, signer := range signers { - signerAddresses[i] = signer.Address - } - - var groupQuorums [32]uint8 - var groupParents [32]uint8 - - copy(groupQuorums[:], quorums) - copy(groupParents[:], parents) - - // Create new config vars to ensure atomic test configs - newSignerAddresses := make([][20]uint8, len(signerAddresses)) - copy(newSignerAddresses, signerAddresses) - - newSignerGroups := make([]byte, len(signerGroups)) - copy(newSignerGroups, signerGroups) - - newGroupQuorums := groupQuorums - newGroupParents := groupParents - newClearRoot := clearRoot - - config := &McmConfigArgs{ - MultisigName: msigName, - } - config.SignerAddresses = newSignerAddresses - config.SignerGroups = newSignerGroups - config.GroupQuorums = newGroupQuorums - config.GroupParents = newGroupParents - config.ClearRoot = newClearRoot - return config, nil -} - -func Keccak256(data []byte) []byte { - hash := sha3.NewLegacyKeccak256() - hash.Write(data) - return hash.Sum(nil) -} - -func SafeToUint8(n int) (uint8, error) { - if n < 0 || n > 255 { - return 0, fmt.Errorf("value %d is outside uint8 range [0,255]", n) - } - return uint8(n), nil -} - -func SafeToUint32(n int) (uint32, error) { - if n < 0 || n > math.MaxUint32 { - return 0, fmt.Errorf("value %d is outside uint32 range [0,%d]", n, math.MaxUint32) - } - return uint32(n), nil -} - -func PadString32(input string) ([32]byte, error) { - var result [32]byte - inputBytes := []byte(input) - inputLen := len(inputBytes) - if inputLen > 32 { - return result, errors.New("input string exceeds 32 bytes") - } - startPos := 32 - inputLen - copy(result[startPos:], inputBytes) - return result, nil -} - -func UnpadString32(input [32]byte) string { - startPos := 0 - for i := 0; i < len(input); i++ { - if input[i] != 0 { - startPos = i - break - } - } - return string(input[startPos:]) -} - -// simple salt generator that uses the current Unix timestamp(in mills) -func SimpleSalt() ([32]byte, error) { - var salt [32]byte - now := time.Now().UnixMilli() - if now < 0 { - return salt, fmt.Errorf("negative timestamp: %d", now) - } - // unix timestamp in millseconds - binary.BigEndian.PutUint64(salt[:8], uint64(now)) - // Next 8 bytes: Crypto random - randBytes := make([]byte, 8) - if _, err := crypto_rand.Read(randBytes); err != nil { - return salt, fmt.Errorf("failed to generate random bytes: %w", err) - } - copy(salt[8:16], randBytes) - return salt, nil -} diff --git a/chains/solana/utils/mcms/mcm.go b/chains/solana/utils/mcms/mcm.go index c52a44486..5fa03a702 100644 --- a/chains/solana/utils/mcms/mcm.go +++ b/chains/solana/utils/mcms/mcm.go @@ -13,54 +13,54 @@ import ( ) // mcm signer dataless pda -func McmSignerAddress(msigName [32]byte) solana.PublicKey { +func GetSignerPDA(msigID [32]byte) solana.PublicKey { pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("multisig_signer"), - msigName[:], + msigID[:], }, config.McmProgram) return pda } -func McmConfigAddress(msigName [32]byte) solana.PublicKey { +func GetConfigPDA(msigID [32]byte) solana.PublicKey { pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("multisig_config"), - msigName[:], + msigID[:], }, config.McmProgram) return pda } -func McmConfigSignersAddress(msigName [32]byte) solana.PublicKey { +func GetConfigSignersPDA(msigID [32]byte) solana.PublicKey { pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("multisig_config_signers"), - msigName[:], + msigID[:], }, config.McmProgram) return pda } -func RootMetadataAddress(msigName [32]byte) solana.PublicKey { +func GetRootMetadataPDA(msigID [32]byte) solana.PublicKey { pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("root_metadata"), - msigName[:], + msigID[:], }, config.McmProgram) return pda } -func ExpiringRootAndOpCountAddress(msigName [32]byte) solana.PublicKey { +func GetExpiringRootAndOpCountPDA(msigID [32]byte) solana.PublicKey { pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("expiring_root_and_op_count"), - msigName[:], + msigID[:], }, config.McmProgram) return pda } // get address of the root_signatures pda -func RootSignaturesAddress(msigName [32]byte, root [32]byte, validUntil uint32) solana.PublicKey { +func GetRootSignaturesPDA(msigID [32]byte, root [32]byte, validUntil uint32) solana.PublicKey { validUntilBytes := make([]byte, 4) binary.LittleEndian.PutUint32(validUntilBytes, validUntil) pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("root_signatures"), - msigName[:], + msigID[:], root[:], validUntilBytes, }, config.McmProgram) @@ -68,46 +68,123 @@ func RootSignaturesAddress(msigName [32]byte, root [32]byte, validUntil uint32) } // get address of the seen_signed_hashes pda -func SeenSignedHashesAddress(msigName [32]byte, root [32]byte, validUntil uint32) solana.PublicKey { +func GetSeenSignedHashesPDA(msigID [32]byte, root [32]byte, validUntil uint32) solana.PublicKey { validUntilBytes := make([]byte, 4) binary.LittleEndian.PutUint32(validUntilBytes, validUntil) pda, _, _ := solana.FindProgramAddress([][]byte{ []byte("seen_signed_hashes"), - msigName[:], + msigID[:], root[:], validUntilBytes, }, config.McmProgram) return pda } -func NewMcmMultisig(name [32]byte) Multisig { +// utils for padding mcm id +func PadString32(input string) ([32]byte, error) { + var result [32]byte + inputBytes := []byte(input) + inputLen := len(inputBytes) + if inputLen > 32 { + return result, errors.New("input string exceeds 32 bytes") + } + startPos := 32 - inputLen + copy(result[startPos:], inputBytes) + return result, nil +} + +func UnpadString32(input [32]byte) string { + startPos := 0 + for i := 0; i < len(input); i++ { + if input[i] != 0 { + startPos = i + break + } + } + return string(input[startPos:]) +} + +type McmConfigArgs struct { + MultisigID [32]uint8 + SignerAddresses [][20]uint8 + SignerGroups []byte + GroupQuorums [32]uint8 + GroupParents [32]uint8 + ClearRoot bool +} + +func NewValidMcmConfig(msigID [32]byte, signerPrivateKeys []string, signerGroups []byte, quorums []uint8, parents []uint8, clearRoot bool) (*McmConfigArgs, error) { + if len(signerGroups) == 0 { + return nil, fmt.Errorf("signerGroups cannot be empty") + } + + signers, err := eth.GetEvmSigners(signerPrivateKeys) + if err != nil { + return nil, fmt.Errorf("failed to get test EVM signers: %w", err) + } + + if len(signers) != len(signerGroups) { + return nil, fmt.Errorf("number of signers (%d) does not match length of signerGroups (%d)", len(signers), len(signerGroups)) + } + + signerAddresses := make([][20]uint8, len(signers)) + for i, signer := range signers { + signerAddresses[i] = signer.Address + } + + var groupQuorums [32]uint8 + var groupParents [32]uint8 + + copy(groupQuorums[:], quorums) + copy(groupParents[:], parents) + + // Create new config vars to ensure atomic test configs + newSignerAddresses := make([][20]uint8, len(signerAddresses)) + copy(newSignerAddresses, signerAddresses) + + newSignerGroups := make([]byte, len(signerGroups)) + copy(newSignerGroups, signerGroups) + + newGroupQuorums := groupQuorums + newGroupParents := groupParents + newClearRoot := clearRoot + + config := &McmConfigArgs{ + MultisigID: msigID, + } + config.SignerAddresses = newSignerAddresses + config.SignerGroups = newSignerGroups + config.GroupQuorums = newGroupQuorums + config.GroupParents = newGroupParents + config.ClearRoot = newClearRoot + return config, nil +} + +func GetNewMcmMultisig(name [32]byte) Multisig { return Multisig{ PaddedName: name, - SignerPDA: McmSignerAddress(name), - ConfigPDA: McmConfigAddress(name), - RootMetadataPDA: RootMetadataAddress(name), - ExpiringRootAndOpCountPDA: ExpiringRootAndOpCountAddress(name), - ConfigSignersPDA: McmConfigSignersAddress(name), + SignerPDA: GetSignerPDA(name), + ConfigPDA: GetConfigPDA(name), + RootMetadataPDA: GetRootMetadataPDA(name), + ExpiringRootAndOpCountPDA: GetExpiringRootAndOpCountPDA(name), + ConfigSignersPDA: GetConfigSignersPDA(name), RootSignaturesPDA: func(root [32]byte, validUntil uint32) solana.PublicKey { - return RootSignaturesAddress(name, root, validUntil) + return GetRootSignaturesPDA(name, root, validUntil) }, SeenSignedHashesPDA: func(root [32]byte, validUntil uint32) solana.PublicKey { - return SeenSignedHashesAddress(name, root, validUntil) + return GetSeenSignedHashesPDA(name, root, validUntil) }, } } // instructions builder for preloading signers -func McmPreloadSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multisigCfgPDA solana.PublicKey, cfgSignersPDA solana.PublicKey, authority solana.PublicKey, appendChunkSize int) ([]solana.Instruction, error) { +func GetPreloadSignersIxs(signerAddresses [][20]uint8, msigID [32]byte, multisigCfgPDA solana.PublicKey, cfgSignersPDA solana.PublicKey, authority solana.PublicKey, appendChunkSize int) ([]solana.Instruction, error) { ixs := make([]solana.Instruction, 0) - parsedTotalSigners, pErr := SafeToUint8(len(signerAddresses)) - if pErr != nil { - return nil, pErr - } initSignersIx, isErr := mcm.NewInitSignersInstruction( - msigName, - parsedTotalSigners, + msigID, + //nolint:gosec + uint8(len(signerAddresses)), multisigCfgPDA, cfgSignersPDA, authority, @@ -118,14 +195,14 @@ func McmPreloadSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multis } ixs = append(ixs, initSignersIx) - appendSignersIxs, asErr := AppendSignersIxs(signerAddresses, msigName, multisigCfgPDA, cfgSignersPDA, authority, appendChunkSize) + appendSignersIxs, asErr := GetAppendSignersIxs(signerAddresses, msigID, multisigCfgPDA, cfgSignersPDA, authority, appendChunkSize) if asErr != nil { return nil, asErr } ixs = append(ixs, appendSignersIxs...) finalizeSignersIx, fsErr := mcm.NewFinalizeSignersInstruction( - msigName, + msigID, multisigCfgPDA, cfgSignersPDA, authority, @@ -139,7 +216,7 @@ func McmPreloadSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multis } // get chunked append instructions to preload signers to pda, required before set_config -func AppendSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multisigCfgPDA solana.PublicKey, cfgSignersPDA solana.PublicKey, authority solana.PublicKey, chunkSize int) ([]solana.Instruction, error) { +func GetAppendSignersIxs(signerAddresses [][20]uint8, msigID [32]byte, multisigCfgPDA solana.PublicKey, cfgSignersPDA solana.PublicKey, authority solana.PublicKey, chunkSize int) ([]solana.Instruction, error) { if chunkSize > config.MaxAppendSignerBatchSize { return nil, errors.New("chunkSize exceeds max signers chunk size") } @@ -150,7 +227,7 @@ func AppendSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multisigCf end = len(signerAddresses) } appendIx, appendErr := mcm.NewAppendSignersInstruction( - msigName, + msigID, signerAddresses[i:end], multisigCfgPDA, cfgSignersPDA, @@ -165,19 +242,15 @@ func AppendSignersIxs(signerAddresses [][20]uint8, msigName [32]byte, multisigCf } // instructions builder for preloading signatures -func McmPreloadSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root [32]uint8, validUntil uint32, signaturesPDA solana.PublicKey, authority solana.PublicKey, appendChunkSize int) ([]solana.Instruction, error) { +func GetMcmPreloadSignaturesIxs(signatures []mcm.Signature, msigID [32]byte, root [32]uint8, validUntil uint32, signaturesPDA solana.PublicKey, authority solana.PublicKey, appendChunkSize int) ([]solana.Instruction, error) { ixs := make([]solana.Instruction, 0) - parsedTotalSigs, pErr := SafeToUint8(len(signatures)) - if pErr != nil { - return nil, pErr - } - initSigsIx, isErr := mcm.NewInitSignaturesInstruction( - msigName, + msigID, root, validUntil, - parsedTotalSigs, + //nolint:gosec + uint8(len(signatures)), signaturesPDA, authority, solana.SystemProgramID, @@ -187,7 +260,7 @@ func McmPreloadSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root } ixs = append(ixs, initSigsIx) - appendSigsIxs, asErr := AppendSignaturesIxs(signatures, msigName, root, validUntil, signaturesPDA, authority, appendChunkSize) + appendSigsIxs, asErr := GetAppendSignaturesIxs(signatures, msigID, root, validUntil, signaturesPDA, authority, appendChunkSize) if asErr != nil { return nil, asErr } @@ -195,7 +268,7 @@ func McmPreloadSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root ixs = append(ixs, appendSigsIxs...) finalizeSigsIx, fsErr := mcm.NewFinalizeSignaturesInstruction( - msigName, + msigID, root, validUntil, signaturesPDA, @@ -210,7 +283,7 @@ func McmPreloadSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root } // get chunked append instructions to preload signatures to pda, required before set_root -func AppendSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root [32]uint8, validUntil uint32, signaturesPDA solana.PublicKey, authority solana.PublicKey, chunkSize int) ([]solana.Instruction, error) { +func GetAppendSignaturesIxs(signatures []mcm.Signature, msigID [32]byte, root [32]uint8, validUntil uint32, signaturesPDA solana.PublicKey, authority solana.PublicKey, chunkSize int) ([]solana.Instruction, error) { if chunkSize > config.MaxAppendSignatureBatchSize { return nil, errors.New("chunkSize exceeds max signatures chunk size") } @@ -221,7 +294,7 @@ func AppendSignaturesIxs(signatures []mcm.Signature, msigName [32]byte, root [32 end = len(signatures) } appendIx, appendErr := mcm.NewAppendSignaturesInstruction( - msigName, + msigID, root, validUntil, signatures[i:end], diff --git a/chains/solana/utils/mcms/common_test.go b/chains/solana/utils/mcms/mcm_test.go similarity index 100% rename from chains/solana/utils/mcms/common_test.go rename to chains/solana/utils/mcms/mcm_test.go diff --git a/chains/solana/utils/mcms/multisig.go b/chains/solana/utils/mcms/multisig.go index 3b3cbb113..a207f2e8c 100644 --- a/chains/solana/utils/mcms/multisig.go +++ b/chains/solana/utils/mcms/multisig.go @@ -105,11 +105,9 @@ func (sa *SignatureAnalyzer) PrintGroupStructure() { parentID := sa.groupParents[groupID] parentStr := "root" - groupIDUint8, err := SafeToUint8(groupID) - if err != nil { - panic(err) - } - if parentID != groupIDUint8 { + + //nolint:gosec + if parentID != uint8(groupID) { parentStr = fmt.Sprintf("%d", parentID) } fmt.Printf("Parent group: %s\n", parentStr) diff --git a/chains/solana/utils/timelock/timelock.go b/chains/solana/utils/timelock/timelock.go index 4f3d1ccdf..7256eb109 100644 --- a/chains/solana/utils/timelock/timelock.go +++ b/chains/solana/utils/timelock/timelock.go @@ -3,6 +3,7 @@ package timelock import ( "context" crypto_rand "crypto/rand" + "encoding/binary" "fmt" "math/big" "time" @@ -19,8 +20,27 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" ) +func GetSignerPDA(timelockID [32]byte) solana.PublicKey { + pda, _, _ := solana.FindProgramAddress([][]byte{[]byte("timelock_signer"), timelockID[:]}, config.TimelockProgram) + return pda +} + +func GetConfigPDA(timelockID [32]byte) solana.PublicKey { + pda, _, _ := solana.FindProgramAddress([][]byte{[]byte("timelock_config"), timelockID[:]}, config.TimelockProgram) + return pda +} + +func GetOperationPDA(timelockID [32]byte, opID [32]byte) solana.PublicKey { + pda, _, _ := solana.FindProgramAddress([][]byte{ + []byte("timelock_operation"), + timelockID[:], + opID[:], + }, config.TimelockProgram) + return pda +} + // instruction builder for initializing access controllers -func InitAccessControllersIxs(ctx context.Context, roleAcAccount solana.PublicKey, authority solana.PrivateKey, client *rpc.Client) ([]solana.Instruction, error) { +func GetInitAccessControllersIxs(ctx context.Context, roleAcAccount solana.PublicKey, authority solana.PrivateKey, client *rpc.Client) ([]solana.Instruction, error) { ixs := []solana.Instruction{} rentExemption, err := client.GetMinimumBalanceForRentExemption( @@ -57,7 +77,7 @@ func InitAccessControllersIxs(ctx context.Context, roleAcAccount solana.PublicKe } // instructions builder for adding access to a role -func BatchAddAccessIxs(ctx context.Context, roleAcAccount solana.PublicKey, role timelock.Role, addresses []solana.PublicKey, authority solana.PrivateKey, chunkSize int, client *rpc.Client) ([]solana.Instruction, error) { +func GetBatchAddAccessIxs(ctx context.Context, timelockID [32]byte, roleAcAccount solana.PublicKey, role timelock.Role, addresses []solana.PublicKey, authority solana.PrivateKey, chunkSize int, client *rpc.Client) ([]solana.Instruction, error) { var ac access_controller.AccessController err := common.GetAccountDataBorshInto(ctx, client, roleAcAccount, config.DefaultCommitment, &ac) if err != nil { @@ -71,8 +91,9 @@ func BatchAddAccessIxs(ctx context.Context, roleAcAccount solana.PublicKey, role } chunk := addresses[i:end] ix := timelock.NewBatchAddAccessInstruction( + timelockID, role, - config.TimelockConfigPDA, + GetConfigPDA(timelockID), config.AccessControllerProgram, roleAcAccount, authority.PublicKey(), @@ -90,15 +111,16 @@ func BatchAddAccessIxs(ctx context.Context, roleAcAccount solana.PublicKey, role } // instructions builder for preloading instructions to timelock operation -func PreloadOperationIxs(op Operation, authority solana.PublicKey) ([]solana.Instruction, error) { +func GetPreloadOperationIxs(timelockID [32]byte, op Operation, authority solana.PublicKey) ([]solana.Instruction, error) { ixs := []solana.Instruction{} initOpIx, ioErr := timelock.NewInitializeOperationInstruction( + timelockID, op.OperationID(), op.Predecessor, op.Salt, op.IxsCountU32(), op.OperationPDA(), - config.TimelockConfigPDA, + GetConfigPDA(timelockID), authority, solana.SystemProgramID, ).ValidateAndBuild() @@ -109,10 +131,11 @@ func PreloadOperationIxs(op Operation, authority solana.PublicKey) ([]solana.Ins for _, instruction := range op.ToInstructionData() { appendIxsIx, apErr := timelock.NewAppendInstructionsInstruction( + timelockID, op.OperationID(), []timelock.InstructionData{instruction}, // this should be a slice of instruction within 1232 bytes op.OperationPDA(), - config.TimelockConfigPDA, + GetConfigPDA(timelockID), authority, solana.SystemProgramID, // for reallocation ).ValidateAndBuild() @@ -123,9 +146,10 @@ func PreloadOperationIxs(op Operation, authority solana.PublicKey) ([]solana.Ins } finOpIx, foErr := timelock.NewFinalizeOperationInstruction( + timelockID, op.OperationID(), op.OperationPDA(), - config.TimelockConfigPDA, + GetConfigPDA(timelockID), authority, ).ValidateAndBuild() if foErr != nil { @@ -158,7 +182,7 @@ func CreateRoleMultisigs(role timelock.Role, numMsigs int) RoleMultisigs { msigs := make([]mcms.Multisig, numMsigs) for i := 0; i < numMsigs; i++ { name, _ := mcms.PadString32(fmt.Sprintf("%s_%d", role.String(), i)) - msig := mcms.NewMcmMultisig(name) + msig := mcms.GetNewMcmMultisig(name) // Create and set the config for each msig // ┌──────┐ // │2-of-2│ root @@ -264,3 +288,21 @@ func GetBlockedFunctionSelectors( return selectors, nil } + +// simple salt generator that uses the current Unix timestamp(in mills) +func SimpleSalt() ([32]byte, error) { + var salt [32]byte + now := time.Now().UnixMilli() + if now < 0 { + return salt, fmt.Errorf("negative timestamp: %d", now) + } + // unix timestamp in millseconds + binary.BigEndian.PutUint64(salt[:8], uint64(now)) + // Next 8 bytes: Crypto random + randBytes := make([]byte, 8) + if _, err := crypto_rand.Read(randBytes); err != nil { + return salt, fmt.Errorf("failed to generate random bytes: %w", err) + } + copy(salt[8:16], randBytes) + return salt, nil +} diff --git a/chains/solana/utils/timelock/timelock_operations.go b/chains/solana/utils/timelock/timelock_operations.go index dae9866c4..489246909 100644 --- a/chains/solana/utils/timelock/timelock_operations.go +++ b/chains/solana/utils/timelock/timelock_operations.go @@ -7,8 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/mcms" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/eth" ) // represents a single instruction with its required accounts @@ -19,6 +18,7 @@ type Instruction struct { // represents a batch of instructions that having atomicy to be scheduled and executed via timelock type Operation struct { + TimelockID [32]byte // timelock instance identifier Predecessor [32]byte // hashed id of the previous operation Salt [32]byte // random salt for the operation Delay uint64 // delay in seconds @@ -47,11 +47,8 @@ func (op *Operation) AddInstruction(ix solana.Instruction, additionalPrograms [] } func (op *Operation) IxsCountU32() uint32 { - ixsCount, err := mcms.SafeToUint32(len(op.instructions)) - if err != nil { - panic(err) - } - return ixsCount + //nolint:gosec + return uint32(len(op.instructions)) } // convert operation to timelock instruction data slice @@ -99,7 +96,7 @@ func (op *Operation) OperationID() [32]byte { func (op *Operation) OperationPDA() solana.PublicKey { id := op.OperationID() - return config.TimelockOperationPDA(id) + return GetOperationPDA(op.TimelockID, id) } // type conversion from solana instruction to timelock instruction data @@ -150,7 +147,7 @@ func hashOperation(instructions []timelock.InstructionData, predecessor [32]byte encodedData.Write(predecessor[:]) encodedData.Write(salt[:]) - result := mcms.Keccak256(encodedData.Bytes()) + result := eth.Keccak256(encodedData.Bytes()) var hash [32]byte copy(hash[:], result)