diff --git a/solana/bridge/program/src/api/governance.rs b/solana/bridge/program/src/api/governance.rs index 972f41e2..212e4c7a 100644 --- a/solana/bridge/program/src/api/governance.rs +++ b/solana/bridge/program/src/api/governance.rs @@ -63,6 +63,7 @@ pub fn upgrade_contract( accs.upgrade_authority.key, accs.spill.key, ); + let _seeds = accs.upgrade_authority.self_seeds(None); invoke_signed(&upgrade_ix, ctx.accounts, &[])?; @@ -82,6 +83,7 @@ pub struct UpgradeGuardianSet<'b> { /// Old guardian set pub guardian_set_old: GuardianSet<'b, { AccountState::Initialized }>, + /// New guardian set pub guardian_set_new: GuardianSet<'b, { AccountState::Uninitialized }>, } diff --git a/solana/bridge/program/src/api/initialize.rs b/solana/bridge/program/src/api/initialize.rs index 88a073a6..f582aa7f 100644 --- a/solana/bridge/program/src/api/initialize.rs +++ b/solana/bridge/program/src/api/initialize.rs @@ -6,6 +6,7 @@ use crate::{ GuardianSetDerivationData, }, types::*, + MAX_LEN_GUARDIAN_KEYS, }; use solitaire::{ CreationLamports::Exempt, @@ -25,22 +26,35 @@ pub struct Initialize<'b> { impl<'b> InstructionContext<'b> for Initialize<'b> { } +#[derive(BorshDeserialize, BorshSerialize, Default)] +pub struct InitializeData { + /// Period for how long a guardian set is valid after it has been replaced by a new one. This + /// guarantees that VAAs issued by that set can still be submitted for a certain period. In + /// this period we still trust the old guardian set. + pub guardian_set_expiration_time: u32, + + /// Amount of lamports that needs to be paid to the protocol to post a message + pub fee: u64, + + /// Initial Guardian Set + pub initial_guardians: Vec<[u8; 20]>, +} + pub fn initialize( ctx: &ExecutionContext, accs: &mut Initialize, - config: BridgeConfig, + data: InitializeData, ) -> Result<()> { - accs.guardian_set.index = 0; + let index = 0; + + // Allocate a default guardian set, with zeroed keys. + accs.guardian_set.index = index; accs.guardian_set.creation_time = 0; - accs.guardian_set.keys = Vec::with_capacity(20); - accs.guardian_set.keys.push([ - 0x1d, 0x72, 0x87, 0x7e, 0xb2, 0xd8, 0x98, 0x73, 0x8a, 0xfe, 0x94, 0xc6, 0x10, 0x11, 0x52, - 0xed, 0xe0, 0x43, 0x5d, 0xe9, - ]); + accs.guardian_set.keys.extend(&data.initial_guardians); // Initialize Guardian Set accs.guardian_set.create( - &GuardianSetDerivationData { index: 0 }, + &GuardianSetDerivationData { index }, ctx, accs.payer.key, Exempt, @@ -48,8 +62,11 @@ pub fn initialize( // Initialize the Bridge state for the first time. accs.bridge.create(ctx, accs.payer.key, Exempt)?; - accs.bridge.guardian_set_index = 0; - accs.bridge.config = config; + accs.bridge.guardian_set_index = index; + accs.bridge.config = BridgeConfig { + guardian_set_expiration_time: data.guardian_set_expiration_time, + fee: data.fee, + }; // Initialize the fee collector account so it's rent exempt and will keep funds accs.fee_collector.create( diff --git a/solana/bridge/program/src/api/post_vaa.rs b/solana/bridge/program/src/api/post_vaa.rs index ec3eeeff..f4b3490d 100644 --- a/solana/bridge/program/src/api/post_vaa.rs +++ b/solana/bridge/program/src/api/post_vaa.rs @@ -207,6 +207,7 @@ fn check_integrity<'r>( v.write_u32::(vaa.nonce)?; v.write_u16::(vaa.emitter_chain)?; v.write(&vaa.emitter_address)?; + v.write_u64::(vaa.sequence)?; v.write(&vaa.payload)?; v.into_inner() }; diff --git a/solana/bridge/program/src/instructions.rs b/solana/bridge/program/src/instructions.rs index f52752eb..069aaf80 100644 --- a/solana/bridge/program/src/instructions.rs +++ b/solana/bridge/program/src/instructions.rs @@ -37,6 +37,7 @@ pub fn initialize( payer: Pubkey, fee: u64, guardian_set_expiration_time: u32, + initial_guardians: &[[u8; 20]], ) -> solitaire::Result { let bridge = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program_id); let guardian_set = GuardianSet::<'_, { AccountState::Uninitialized }>::key( @@ -55,7 +56,8 @@ pub fn initialize( AccountMeta::new_readonly(sysvar::rent::id(), false), AccountMeta::new_readonly(solana_program::system_program::id(), false), ], - data: crate::instruction::Instruction::Initialize(BridgeConfig { + data: crate::instruction::Instruction::Initialize(InitializeData { + initial_guardians: initial_guardians.to_vec(), fee, guardian_set_expiration_time, }) diff --git a/solana/bridge/program/src/types.rs b/solana/bridge/program/src/types.rs index f931ce2f..d91b9e9b 100644 --- a/solana/bridge/program/src/types.rs +++ b/solana/bridge/program/src/types.rs @@ -246,6 +246,7 @@ impl DeserializeGovernancePayload for GovernancePayloadUpgrade { pub struct GovernancePayloadGuardianSetChange { // New GuardianSetIndex pub new_guardian_set_index: u32, + // New GuardianSet pub new_guardian_set: Vec<[u8; 20]>, } diff --git a/solana/bridge/program/src/vaa.rs b/solana/bridge/program/src/vaa.rs index d03cf87c..d658a5bd 100644 --- a/solana/bridge/program/src/vaa.rs +++ b/solana/bridge/program/src/vaa.rs @@ -119,7 +119,8 @@ impl<'b, T: DeserializePayload> PayloadMessage<'b, T> { #[derive(FromAccounts)] pub struct ClaimableVAA<'b, T: DeserializePayload> { // Signed message for the transfer - pub message: PayloadMessage<'b, T>, // TODO use bridge type here that does verifications + // TODO use bridge type here that does verifications + pub message: PayloadMessage<'b, T>, // Claim account to prevent double spending pub claim: Claim<'b, { AccountState::Uninitialized }>, @@ -170,6 +171,7 @@ impl<'b, T: DeserializePayload> ClaimableVAA<'b, T> { payer, Exempt, )?; + self.claim.claimed = true; Ok(())