浏览代码

Create different accounts for message posting and VAA posting

Change-Id: I88a3f74301aeecc16bb51ba693ea9523dc16b612
Hendrik Hofstadt 4 年之前
父节点
当前提交
add04e8755

+ 3 - 2
clients/solana/main.ts

@@ -31,6 +31,7 @@ yargs(hideBin(process.argv))
         // Generate a new random public key
         let from = web3.Keypair.generate();
         let emitter = web3.Keypair.generate();
+        let message = web3.Keypair.generate();
         let airdropSignature = await connection.requestAirdrop(
             from.publicKey,
             web3.LAMPORTS_PER_SOL,
@@ -49,7 +50,7 @@ yargs(hideBin(process.argv))
             throw new Error("invalid consistency level")
         }
 
-        let ix = ixFromRust(post_message_ix(bridge_id.toString(), from.publicKey.toString(), emitter.publicKey.toString(), argv.nonce, Buffer.from(argv.message, "hex"), argv.consistency));
+        let ix = ixFromRust(post_message_ix(bridge_id.toString(), from.publicKey.toString(), emitter.publicKey.toString(), message.publicKey.toString(), argv.nonce, Buffer.from(argv.message, "hex"), argv.consistency));
         // Add transfer instruction to transaction
         let transaction = new web3.Transaction().add(transferIx, ix);
 
@@ -57,7 +58,7 @@ yargs(hideBin(process.argv))
         let signature = await web3.sendAndConfirmTransaction(
             connection,
             transaction,
-            [from, emitter],
+            [from, emitter, message],
             {
                 skipPreflight: true
             }

+ 23 - 26
solana/bridge/client/src/main.rs

@@ -135,32 +135,29 @@ fn command_post_message(
     );
 
     let emitter = Keypair::new();
+    let message = Keypair::new();
     let ix = match proxy {
-        Some(p) => {
-            cpi_poster::instructions::post_message(
-                p,
-                *bridge,
-                config.owner.pubkey(),
-                emitter.pubkey(),
-                nonce,
-                payload,
-                commitment,
-            )
-            .unwrap()
-            .1
-        }
-        None => {
-            bridge::instructions::post_message(
-                *bridge,
-                config.owner.pubkey(),
-                emitter.pubkey(),
-                nonce,
-                payload,
-                commitment,
-            )
-            .unwrap()
-            .1
-        }
+        Some(p) => cpi_poster::instructions::post_message(
+            p,
+            *bridge,
+            config.owner.pubkey(),
+            emitter.pubkey(),
+            message.pubkey(),
+            nonce,
+            payload,
+            commitment,
+        )
+        .unwrap(),
+        None => bridge::instructions::post_message(
+            *bridge,
+            config.owner.pubkey(),
+            emitter.pubkey(),
+            message.pubkey(),
+            nonce,
+            payload,
+            commitment,
+        )
+        .unwrap(),
     };
     let mut transaction =
         Transaction::new_with_payer(&[transfer_ix, ix], Some(&config.fee_payer.pubkey()));
@@ -168,7 +165,7 @@ fn command_post_message(
     let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
     check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
     transaction.sign(
-        &[&config.fee_payer, &config.owner, &emitter],
+        &[&config.fee_payer, &config.owner, &emitter, &message],
         recent_blockhash,
     );
     Ok(Some(transaction))

+ 3 - 2
solana/bridge/cpi_poster/src/api/post_message.rs

@@ -11,7 +11,7 @@ pub struct PostMessage<'b> {
     pub bridge: Mut<Info<'b>>,
 
     /// Account to store the posted message
-    pub message: Mut<Info<'b>>,
+    pub message: Signer<Mut<Info<'b>>>,
 
     /// Emitter of the VAA
     pub emitter: Info<'b>,
@@ -50,10 +50,11 @@ pub fn post_message(
     accs: &mut PostMessage,
     data: PostMessageData,
 ) -> Result<()> {
-    let (_, ix) = bridge::instructions::post_message(
+    let ix = bridge::instructions::post_message(
         *accs.bridge_program.key,
         *accs.payer.key,
         *accs.emitter.key,
+        *accs.message.key,
         data.nonce,
         data.payload,
         data.consistency_level,

+ 10 - 11
solana/bridge/cpi_poster/src/instructions.rs

@@ -12,23 +12,22 @@ pub fn post_message(
     bridge_id: Pubkey,
     payer: Pubkey,
     emitter: Pubkey,
+    message: Pubkey,
     nonce: u32,
     payload: Vec<u8>,
     commitment: ConsistencyLevel,
-) -> solitaire::Result<(Pubkey, Instruction)> {
-    let (k, ix) =
-        bridge::instructions::post_message(bridge_id, payer, emitter, nonce, payload, commitment)?;
+) -> solitaire::Result<Instruction> {
+    let ix = bridge::instructions::post_message(
+        bridge_id, payer, emitter, message, nonce, payload, commitment,
+    )?;
     let mut accounts = ix.accounts;
     accounts.insert(7, AccountMeta::new_readonly(bridge_id, false));
     let mut data = ix.data;
     data[0] = 0;
 
-    Ok((
-        k,
-        Instruction {
-            program_id,
-            accounts,
-            data,
-        },
-    ))
+    Ok(Instruction {
+        program_id,
+        accounts,
+        data,
+    })
 }

+ 14 - 22
solana/bridge/program/src/accounts.rs

@@ -2,7 +2,8 @@ use crate::{
     types,
     types::{
         BridgeData,
-        PostedMessage,
+        PostedMessageData,
+        PostedVAAData,
         SequenceTracker,
     },
 };
@@ -55,29 +56,17 @@ impl<'b, const State: AccountState> Seeded<&ClaimDerivationData> for Claim<'b, {
 
 pub type SignatureSet<'b, const State: AccountState> = Data<'b, types::SignatureSet, { State }>;
 
-pub type Message<'b, const State: AccountState> = Data<'b, PostedMessage, { State }>;
+pub type PostedMessage<'b, const State: AccountState> = Data<'b, PostedMessageData, { State }>;
 
-pub struct MessageDerivationData {
-    pub emitter_key: [u8; 32],
-    pub emitter_chain: u16,
-    pub nonce: u32,
-    pub payload: Vec<u8>,
-    // This field is only used when a VAA from a foreign chain is posted
-    pub sequence: Option<u64>,
+pub type PostedVAA<'b, const State: AccountState> = Data<'b, PostedVAAData, { State }>;
+
+pub struct PostedVAADerivationData {
+    pub payload_hash: Vec<u8>,
 }
 
-impl<'b, const State: AccountState> Seeded<&MessageDerivationData> for Message<'b, { State }> {
-    fn seeds(data: &MessageDerivationData) -> Vec<Vec<u8>> {
-        let mut seeds = vec![
-            data.emitter_key.to_vec(),
-            data.emitter_chain.to_be_bytes().to_vec(),
-            data.nonce.to_be_bytes().to_vec(),
-        ];
-        if let Some(seq) = data.sequence {
-            seeds.push(seq.to_be_bytes().to_vec())
-        }
-        seeds.append(&mut data.payload.chunks(32).map(|v| v.to_vec()).collect());
-        seeds
+impl<'b, const State: AccountState> Seeded<&PostedVAADerivationData> for PostedVAA<'b, { State }> {
+    fn seeds(data: &PostedVAADerivationData) -> Vec<Vec<u8>> {
+        vec!["PostedVAA".as_bytes().to_vec(), data.payload_hash.to_vec()]
     }
 }
 
@@ -89,6 +78,9 @@ pub struct SequenceDerivationData<'a> {
 
 impl<'b> Seeded<&SequenceDerivationData<'b>> for Sequence<'b> {
     fn seeds(data: &SequenceDerivationData) -> Vec<Vec<u8>> {
-        vec![data.emitter_key.to_bytes().to_vec()]
+        vec![
+            "Sequence".as_bytes().to_vec(),
+            data.emitter_key.to_bytes().to_vec(),
+        ]
     }
 }

+ 12 - 17
solana/bridge/program/src/api/post_message.rs

@@ -2,8 +2,7 @@ use crate::{
     accounts::{
         Bridge,
         FeeCollector,
-        Message,
-        MessageDerivationData,
+        PostedMessage,
         Sequence,
         SequenceDerivationData,
     },
@@ -25,7 +24,7 @@ use solitaire::{
     *,
 };
 
-pub type UninitializedMessage<'b> = Message<'b, { AccountState::Uninitialized }>;
+pub type UninitializedMessage<'b> = PostedMessage<'b, { AccountState::Uninitialized }>;
 
 impl<'a> From<&PostMessage<'a>> for SequenceDerivationData<'a> {
     fn from(accs: &PostMessage<'a>) -> Self {
@@ -41,7 +40,7 @@ pub struct PostMessage<'b> {
     pub bridge: Mut<Bridge<'b, { AccountState::Initialized }>>,
 
     /// Account to store the posted message
-    pub message: Mut<UninitializedMessage<'b>>,
+    pub message: Signer<Mut<UninitializedMessage<'b>>>,
 
     /// Emitter of the VAA
     pub emitter: Signer<Info<'b>>,
@@ -85,17 +84,6 @@ pub fn post_message(
     accs.sequence
         .verify_derivation(ctx.program_id, &(&*accs).into())?;
 
-    let msg_derivation = MessageDerivationData {
-        emitter_key: accs.emitter.key.to_bytes(),
-        emitter_chain: CHAIN_ID_SOLANA,
-        nonce: data.nonce,
-        payload: data.payload.clone(),
-        sequence: None,
-    };
-
-    accs.message
-        .verify_derivation(ctx.program_id, &msg_derivation)?;
-
     let fee = accs.bridge.config.fee;
     // Fee handling, checking previously known balance allows us to not care who is the payer of
     // this submission.
@@ -137,8 +125,15 @@ pub fn post_message(
     };
 
     // Create message account
-    accs.message
-        .create(&msg_derivation, ctx, accs.payer.key, Exempt)?;
+    let size = accs.message.size();
+    let ix = solana_program::system_instruction::create_account(
+        accs.payer.key,
+        accs.message.info().key,
+        Exempt.amount(size),
+        size as u64,
+        ctx.program_id,
+    );
+    solana_program::program::invoke(&ix, ctx.accounts)?;
 
     // Bump sequence number
     trace!("New Sequence: {}", accs.sequence.sequence + 1);

+ 18 - 25
solana/bridge/program/src/api/post_vaa.rs

@@ -14,8 +14,8 @@ use crate::{
         Bridge,
         GuardianSet,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
         SignatureSet,
     },
     error::Error::{
@@ -64,7 +64,7 @@ pub struct PostVAA<'b> {
     pub signature_set: SignatureSet<'b, { AccountState::Initialized }>,
 
     /// Message the VAA is associated with.
-    pub message: Mut<Message<'b, { AccountState::MaybeInitialized }>>,
+    pub message: Mut<PostedVAA<'b, { AccountState::MaybeInitialized }>>,
 
     /// Account used to pay for auxillary instructions.
     pub payer: Mut<Signer<Info<'b>>>,
@@ -103,22 +103,19 @@ pub struct PostVAAData {
 }
 
 pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
-    let mut msg_derivation = MessageDerivationData {
-        emitter_key: vaa.emitter_address,
-        emitter_chain: vaa.emitter_chain,
-        nonce: vaa.nonce,
-        payload: vaa.payload.clone(),
-        sequence: None,
+    let msg_derivation = PostedVAADerivationData {
+        payload_hash: accs.signature_set.hash.to_vec(),
     };
-    if vaa.emitter_chain != CHAIN_ID_SOLANA {
-        msg_derivation.sequence = Some(vaa.sequence)
-    }
 
     accs.message
         .verify_derivation(ctx.program_id, &msg_derivation)?;
     accs.guardian_set
         .verify_derivation(ctx.program_id, &(&vaa).into())?;
 
+    if accs.message.is_initialized() {
+        return Ok(());
+    }
+
     // Verify any required invariants before we process the instruction.
     check_active(&accs.guardian_set, &accs.clock)?;
     check_valid_sigs(&accs.guardian_set, &accs.signature_set)?;
@@ -148,22 +145,18 @@ pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) ->
         return Err(PostVAAConsensusFailed.into());
     }
 
-    // If the VAA originates from another chain we need to create the account and populate all fields
-    if !accs.message.is_initialized() {
-        accs.message.nonce = vaa.nonce;
-        accs.message.emitter_chain = vaa.emitter_chain;
-        accs.message.emitter_address = vaa.emitter_address;
-        accs.message.sequence = vaa.sequence;
-        accs.message.payload = vaa.payload;
-        accs.message.consistency_level = vaa.consistency_level;
-        accs.message
-            .create(&msg_derivation, ctx, accs.payer.key, Exempt)?;
-    }
-
-    // Store VAA data in associated message.
+    // Persist VAA data
+    accs.message.nonce = vaa.nonce;
+    accs.message.emitter_chain = vaa.emitter_chain;
+    accs.message.emitter_address = vaa.emitter_address;
+    accs.message.sequence = vaa.sequence;
+    accs.message.payload = vaa.payload;
+    accs.message.consistency_level = vaa.consistency_level;
     accs.message.vaa_version = vaa.version;
     accs.message.vaa_time = vaa.timestamp;
     accs.message.vaa_signature_account = *accs.signature_set.info().key;
+    accs.message
+        .create(&msg_derivation, ctx, accs.payer.key, Exempt)?;
 
     Ok(())
 }

+ 32 - 51
solana/bridge/program/src/instructions.rs

@@ -30,8 +30,8 @@ use crate::{
         FeeCollector,
         GuardianSet,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
         Sequence,
         SequenceDerivationData,
     },
@@ -88,10 +88,11 @@ pub fn post_message(
     program_id: Pubkey,
     payer: Pubkey,
     emitter: Pubkey,
+    message: Pubkey,
     nonce: u32,
     payload: Vec<u8>,
     commitment: ConsistencyLevel,
-) -> solitaire::Result<(Pubkey, Instruction)> {
+) -> solitaire::Result<Instruction> {
     let bridge = Bridge::<'_, { AccountState::Uninitialized }>::key(None, &program_id);
     let fee_collector = FeeCollector::<'_>::key(None, &program_id);
     let sequence = Sequence::<'_>::key(
@@ -100,45 +101,32 @@ pub fn post_message(
         },
         &program_id,
     );
-    let message = Message::<'_, { AccountState::MaybeInitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: emitter.to_bytes(),
-            emitter_chain: CHAIN_ID_SOLANA,
-            nonce,
-            sequence: None,
-            payload: payload.clone(),
-        },
-        &program_id,
-    );
 
-    Ok((
-        message,
-        Instruction {
-            program_id,
-
-            accounts: vec![
-                AccountMeta::new(bridge, false),
-                AccountMeta::new(message, false),
-                AccountMeta::new_readonly(emitter, true),
-                AccountMeta::new(sequence, false),
-                AccountMeta::new(payer, true),
-                AccountMeta::new(fee_collector, false),
-                AccountMeta::new_readonly(sysvar::clock::id(), false),
-                AccountMeta::new_readonly(sysvar::rent::id(), false),
-                AccountMeta::new_readonly(solana_program::system_program::id(), false),
-            ],
-
-            data: (
-                crate::instruction::Instruction::PostMessage,
-                PostMessageData {
-                    nonce,
-                    payload: payload.clone(),
-                    consistency_level: commitment,
-                },
-            )
-                .try_to_vec()?,
-        },
-    ))
+    Ok(Instruction {
+        program_id,
+
+        accounts: vec![
+            AccountMeta::new(bridge, false),
+            AccountMeta::new(message, true),
+            AccountMeta::new_readonly(emitter, true),
+            AccountMeta::new(sequence, false),
+            AccountMeta::new(payer, true),
+            AccountMeta::new(fee_collector, false),
+            AccountMeta::new_readonly(sysvar::clock::id(), false),
+            AccountMeta::new_readonly(sysvar::rent::id(), false),
+            AccountMeta::new_readonly(solana_program::system_program::id(), false),
+        ],
+
+        data: (
+            crate::instruction::Instruction::PostMessage,
+            PostMessageData {
+                nonce,
+                payload: payload.clone(),
+                consistency_level: commitment,
+            },
+        )
+            .try_to_vec()?,
+    })
 }
 
 pub fn verify_signatures(
@@ -185,19 +173,12 @@ pub fn post_vaa(
         &program_id,
     );
 
-    let mut msg_derivation_data = MessageDerivationData {
-        emitter_key: vaa.emitter_address,
-        emitter_chain: vaa.emitter_chain,
-        nonce: vaa.nonce,
-        sequence: None,
-        payload: vaa.payload.clone(),
+    let mut msg_derivation_data = &PostedVAADerivationData {
+        payload_hash: hash_vaa(&vaa).to_vec(),
     };
-    if vaa.emitter_chain != CHAIN_ID_SOLANA {
-        msg_derivation_data.sequence = Some(vaa.sequence);
-    }
 
     let message =
-        Message::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &program_id);
+        PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(&msg_derivation_data, &program_id);
 
     Instruction {
         program_id,

+ 78 - 15
solana/bridge/program/src/types.rs

@@ -119,53 +119,116 @@ impl Owned for SignatureSet {
     }
 }
 
+// This is using the same payload as the PostedVAA for backwards compatibility.
+// This will be deprecated in a future release.
 #[repr(transparent)]
-pub struct PostedMessage(pub PostedMessageData);
+pub struct PostedMessageData(pub MessageData);
 
-impl BorshSerialize for PostedMessage {
+impl BorshSerialize for PostedMessageData {
     fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
         writer.write(b"msg")?;
         BorshSerialize::serialize(&self.0, writer)
     }
 }
 
-impl BorshDeserialize for PostedMessage {
+impl BorshDeserialize for PostedMessageData {
     fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
         *buf = &buf[3..];
-        Ok(PostedMessage(
-            <PostedMessageData as BorshDeserialize>::deserialize(buf)?,
+        Ok(PostedMessageData(
+            <MessageData as BorshDeserialize>::deserialize(buf)?,
         ))
     }
 }
 
-impl Deref for PostedMessage {
-    type Target = PostedMessageData;
+impl Deref for PostedMessageData {
+    type Target = MessageData;
 
     fn deref(&self) -> &Self::Target {
         unsafe { std::mem::transmute(&self.0) }
     }
 }
 
-impl DerefMut for PostedMessage {
+impl DerefMut for PostedMessageData {
     fn deref_mut(&mut self) -> &mut Self::Target {
         unsafe { std::mem::transmute(&mut self.0) }
     }
 }
 
-impl Default for PostedMessage {
+impl Default for PostedMessageData {
     fn default() -> Self {
-        PostedMessage(PostedMessageData::default())
+        PostedMessageData(MessageData::default())
     }
 }
 
-impl Clone for PostedMessage {
+impl Clone for PostedMessageData {
     fn clone(&self) -> Self {
-        PostedMessage(self.0.clone())
+        PostedMessageData(self.0.clone())
+    }
+}
+
+#[cfg(not(feature = "cpi"))]
+impl Owned for PostedMessageData {
+    fn owner(&self) -> AccountOwner {
+        AccountOwner::This
+    }
+}
+
+#[cfg(feature = "cpi")]
+impl Owned for PostedMessageData {
+    fn owner(&self) -> AccountOwner {
+        AccountOwner::Other(
+            Pubkey::from_str("Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o").unwrap(),
+        )
+    }
+}
+
+#[repr(transparent)]
+pub struct PostedVAAData(pub MessageData);
+
+impl BorshSerialize for PostedVAAData {
+    fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
+        writer.write(b"vaa")?;
+        BorshSerialize::serialize(&self.0, writer)
+    }
+}
+
+impl BorshDeserialize for PostedVAAData {
+    fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
+        *buf = &buf[3..];
+        Ok(PostedVAAData(
+            <MessageData as BorshDeserialize>::deserialize(buf)?,
+        ))
+    }
+}
+
+impl Deref for PostedVAAData {
+    type Target = MessageData;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe { std::mem::transmute(&self.0) }
+    }
+}
+
+impl DerefMut for PostedVAAData {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe { std::mem::transmute(&mut self.0) }
+    }
+}
+
+impl Default for PostedVAAData {
+    fn default() -> Self {
+        PostedVAAData(MessageData::default())
+    }
+}
+
+impl Clone for PostedVAAData {
+    fn clone(&self) -> Self {
+        PostedVAAData(self.0.clone())
     }
 }
 
 #[derive(Default, BorshSerialize, BorshDeserialize, Clone, Serialize, Deserialize)]
-pub struct PostedMessageData {
+pub struct MessageData {
     /// Header of the posted VAA
     pub vaa_version: u8,
 
@@ -198,14 +261,14 @@ pub struct PostedMessageData {
 }
 
 #[cfg(not(feature = "cpi"))]
-impl Owned for PostedMessage {
+impl Owned for PostedVAAData {
     fn owner(&self) -> AccountOwner {
         AccountOwner::This
     }
 }
 
 #[cfg(feature = "cpi")]
-impl Owned for PostedMessage {
+impl Owned for PostedVAAData {
     fn owner(&self) -> AccountOwner {
         AccountOwner::Other(
             Pubkey::from_str("Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o").unwrap(),

+ 27 - 8
solana/bridge/program/src/vaa.rs

@@ -3,14 +3,17 @@ use crate::{
         Claim,
         ClaimDerivationData,
     },
-    api::ForeignAddress,
+    api::{
+        post_vaa::PostVAAData,
+        ForeignAddress,
+    },
     error::Error::{
         InvalidGovernanceAction,
         InvalidGovernanceChain,
         InvalidGovernanceModule,
         VAAAlreadyExecuted,
     },
-    types::PostedMessage,
+    types::PostedVAAData,
     Result,
     CHAIN_ID_SOLANA,
 };
@@ -107,7 +110,7 @@ pub trait DeserializeGovernancePayload: DeserializePayload + SerializeGovernance
 }
 
 pub struct PayloadMessage<'b, T: DeserializePayload>(
-    Data<'b, PostedMessage, { AccountState::Initialized }>,
+    Data<'b, PostedVAAData, { AccountState::Initialized }>,
     T,
 );
 
@@ -117,13 +120,13 @@ impl<'a, 'b: 'a, 'c, T: DeserializePayload> Peel<'a, 'b, 'c> for PayloadMessage<
         Self: Sized,
     {
         // Deserialize wrapped payload
-        let data: Data<'b, PostedMessage, { AccountState::Initialized }> = Data::peel(ctx)?;
+        let data: Data<'b, PostedVAAData, { AccountState::Initialized }> = Data::peel(ctx)?;
         let payload = DeserializePayload::deserialize(&mut &data.payload[..])?;
         Ok(PayloadMessage(data, payload))
     }
 
     fn deps() -> Vec<Pubkey> {
-        Data::<'b, PostedMessage, { AccountState::Initialized }>::deps()
+        Data::<'b, PostedVAAData, { AccountState::Initialized }>::deps()
     }
 
     fn persist(&self, program_id: &Pubkey) -> Result<()> {
@@ -139,7 +142,7 @@ impl<'b, T: DeserializePayload> Deref for PayloadMessage<'b, T> {
 }
 
 impl<'b, T: DeserializePayload> PayloadMessage<'b, T> {
-    pub fn meta(&self) -> &PostedMessage {
+    pub fn meta(&self) -> &PostedVAAData {
         &self.0
     }
 }
@@ -211,13 +214,13 @@ pub struct SignatureItem {
     pub index: u8,
 }
 
-#[derive(Serialize, Deserialize, Default)]
+#[derive(Serialize, Deserialize, Default, Clone)]
 pub struct VAASignature {
     pub signature: Vec<u8>,
     pub guardian_index: u8,
 }
 
-#[derive(Serialize, Deserialize, Default)]
+#[derive(Serialize, Deserialize, Default, Clone)]
 pub struct VAA {
     // Header part
     pub version: u8,
@@ -274,3 +277,19 @@ impl VAA {
         Ok(v)
     }
 }
+
+impl From<VAA> for PostVAAData {
+    fn from(vaa: VAA) -> Self {
+        PostVAAData {
+            version: vaa.version,
+            guardian_set_index: vaa.guardian_set_index,
+            timestamp: vaa.timestamp,
+            nonce: vaa.nonce,
+            emitter_chain: vaa.emitter_chain,
+            emitter_address: vaa.emitter_address,
+            sequence: vaa.sequence,
+            consistency_level: vaa.consistency_level,
+            payload: vaa.payload,
+        }
+    }
+}

+ 20 - 61
solana/bridge/program/src/wasm.rs

@@ -22,8 +22,8 @@ use crate::{
     accounts::{
         GuardianSet,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
     },
     types::ConsistencyLevel,
     PostVAAData,
@@ -36,6 +36,7 @@ use crate::{
         FeeCollector,
     },
     instructions::{
+        hash_vaa,
         post_message,
         post_vaa,
         set_fees,
@@ -50,7 +51,7 @@ use crate::{
         GovernancePayloadTransferFees,
         GovernancePayloadUpgrade,
         GuardianSetData,
-        PostedMessage,
+        PostedVAAData,
     },
 };
 use byteorder::LittleEndian;
@@ -61,6 +62,7 @@ pub fn post_message_ix(
     program_id: String,
     payer: String,
     emitter: String,
+    message: String,
     nonce: u32,
     msg: Vec<u8>,
     consistency: String,
@@ -70,10 +72,11 @@ pub fn post_message_ix(
         "FINALIZED" => ConsistencyLevel::Finalized,
         _ => panic!("invalid consistency level"),
     };
-    let (_, ix) = post_message(
+    let ix = post_message(
         Pubkey::from_str(program_id.as_str()).unwrap(),
         Pubkey::from_str(payer.as_str()).unwrap(),
         Pubkey::from_str(emitter.as_str()).unwrap(),
+        Pubkey::from_str(message.as_str()).unwrap(),
         nonce,
         msg,
         consistency_level,
@@ -116,13 +119,9 @@ pub fn update_guardian_set_ix(program_id: String, payer: String, vaa: Vec<u8>) -
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload =
         GovernancePayloadGuardianSetChange::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload,
-            sequence: None,
+    let message_key = PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -142,13 +141,9 @@ pub fn update_guardian_set_ix(program_id: String, payer: String, vaa: Vec<u8>) -
 pub fn set_fees_ix(program_id: String, payer: String, vaa: Vec<u8>) -> JsValue {
     let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload,
-            sequence: None,
+    let message_key = PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -167,13 +162,9 @@ pub fn transfer_fees_ix(program_id: String, payer: String, vaa: Vec<u8>) -> JsVa
     let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = GovernancePayloadTransferFees::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload,
-            sequence: None,
+    let message_key = PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -199,13 +190,9 @@ pub fn upgrade_contract_ix(
     let spill = Pubkey::from_str(spill.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = GovernancePayloadUpgrade::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload,
-            sequence: None,
+    let message_key = PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -361,37 +348,9 @@ pub fn fee_collector_address(bridge: String) -> Vec<u8> {
     bridge_key.to_bytes().to_vec()
 }
 
-#[wasm_bindgen]
-pub fn posted_message_address(
-    bridge: String,
-    emitter_key: Vec<u8>,
-    emitter_chain: u16,
-    nonce: u32,
-    payload: Vec<u8>,
-    sequence: Option<u64>,
-) -> Vec<u8> {
-    let program_id = Pubkey::from_str(bridge.as_str()).unwrap();
-
-    let mut ek = [0u8; 32];
-    ek.copy_from_slice(emitter_key.as_slice());
-
-    let message_key = Message::<'_, { AccountState::Initialized }>::key(
-        &MessageDerivationData {
-            emitter_key: ek,
-            emitter_chain,
-            nonce,
-            payload,
-            sequence,
-        },
-        &program_id,
-    );
-
-    message_key.to_bytes().to_vec()
-}
-
 #[wasm_bindgen]
 pub fn parse_posted_message(data: Vec<u8>) -> JsValue {
-    JsValue::from_serde(&PostedMessage::try_from_slice(data.as_slice()).unwrap().0).unwrap()
+    JsValue::from_serde(&PostedVAAData::try_from_slice(data.as_slice()).unwrap().0).unwrap()
 }
 
 #[wasm_bindgen]

+ 8 - 5
solana/bridge/program/tests/common.rs

@@ -65,7 +65,7 @@ use bridge::{
         FeeCollector,
         GuardianSet,
         GuardianSetDerivationData,
-        MessageDerivationData,
+        PostedVAADerivationData,
         Sequence,
         SequenceDerivationData,
         SignatureSet,
@@ -75,7 +75,7 @@ use bridge::{
     types::{
         BridgeConfig,
         ConsistencyLevel,
-        PostedMessage,
+        PostedVAAData,
         SequenceTracker,
     },
     Initialize,
@@ -290,11 +290,14 @@ mod helpers {
         // Transfer money into the fee collector as it needs a balance/must exist.
         let fee_collector = FeeCollector::<'_>::key(None, program);
 
+        let message = Keypair::new();
+
         // Capture the resulting message, later functions will need this.
-        let (message_key, instruction) = instructions::post_message(
+        let instruction = instructions::post_message(
             *program,
             payer.pubkey(),
             emitter.pubkey(),
+            message.pubkey(),
             nonce,
             data,
             ConsistencyLevel::Confirmed,
@@ -304,7 +307,7 @@ mod helpers {
         execute(
             client,
             payer,
-            &[payer, emitter],
+            &[payer, emitter, message],
             &[
                 system_instruction::transfer(&payer.pubkey(), &fee_collector, fee),
                 instruction,
@@ -312,7 +315,7 @@ mod helpers {
             CommitmentConfig::processed(),
         )?;
 
-        Ok(message_key)
+        Ok(message.pubkey())
     }
 
     pub fn verify_signatures(

+ 18 - 18
solana/bridge/program/tests/integration.rs

@@ -60,11 +60,12 @@ use bridge::{
         FeeCollector,
         GuardianSet,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
         SignatureSet,
     },
     instruction,
+    instructions::hash_vaa,
     types::{
         BridgeConfig,
         BridgeData,
@@ -74,8 +75,8 @@ use bridge::{
         GovernancePayloadTransferFees,
         GovernancePayloadUpgrade,
         GuardianSetData,
-        PostedMessage,
-        PostedMessageData,
+        MessageData,
+        PostedVAAData,
         SequenceTracker,
         SignatureSet as SignatureSetData,
     },
@@ -86,6 +87,7 @@ use bridge::{
     Signature,
 };
 use primitive_types::U256;
+use solana_sdk::hash::hashv;
 
 mod common;
 
@@ -218,7 +220,7 @@ fn test_bridge_messages(context: &mut Context) {
         common::sync(client, payer);
 
         // Fetch chain accounts to verify state.
-        let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+        let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
         let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
         // Verify on chain Message
@@ -277,7 +279,7 @@ fn test_bridge_messages(context: &mut Context) {
     common::sync(client, payer);
 
     // Fetch chain accounts to verify state.
-    let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+    let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
     let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
     // Verify on chain Message
@@ -322,12 +324,14 @@ fn test_invalid_emitter(context: &mut Context) {
 
     let fee_collector = FeeCollector::key(None, &program);
 
+    let msg_account = Keypair::new();
     // Manually send a message that isn't signed by the emitter, which should be rejected to
     // prevent fraudulant transactions sent on behalf of an emitter.
-    let (message_key, mut instruction) = bridge::instructions::post_message(
+    let mut instruction = bridge::instructions::post_message(
         *program,
         payer.pubkey(),
         emitter.pubkey(),
+        msg_account.pubkey(),
         nonce,
         message,
         ConsistencyLevel::Confirmed,
@@ -484,7 +488,7 @@ fn test_guardian_set_change(context: &mut Context) {
     common::sync(client, payer);
 
     // Fetch chain accounts to verify state.
-    let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+    let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
     let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
     // Verify on chain Message
@@ -650,7 +654,7 @@ fn test_set_fees(context: &mut Context) {
     );
 
     // And that the new message is on chain.
-    let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+    let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
     let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
     // Verify on chain Message
@@ -792,7 +796,7 @@ fn test_free_fees(context: &mut Context) {
     );
 
     // And that the new message is on chain.
-    let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+    let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
     let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
     // Verify on chain Message
@@ -982,13 +986,9 @@ fn test_foreign_bridge_messages(context: &mut Context) {
     let (vaa, body, body_hash) = common::generate_vaa(&emitter, message.clone(), nonce, 0, 2);
 
     // Derive where we expect created accounts to be.
-    let message_key = Message::<'_, { AccountState::MaybeInitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: emitter.pubkey().to_bytes(),
-            emitter_chain: vaa.emitter_chain,
-            nonce,
-            sequence: Some(vaa.sequence),
-            payload: message.clone(),
+    let message_key = PostedVAA::<'_, { AccountState::MaybeInitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa).to_vec(),
         },
         &program,
     );
@@ -999,7 +999,7 @@ fn test_foreign_bridge_messages(context: &mut Context) {
     common::sync(client, payer);
 
     // Fetch chain accounts to verify state.
-    let posted_message: PostedMessage = common::get_account_data(client, &message_key);
+    let posted_message: PostedVAAData = common::get_account_data(client, &message_key);
     let signatures: SignatureSetData = common::get_account_data(client, &signature_set);
 
     assert_eq!(posted_message.0.vaa_version, 0);

+ 7 - 36
solana/bridge/program_stub/src/api/post_vaa.rs

@@ -13,9 +13,11 @@ use bridge::{
     accounts::{
         Bridge,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
     },
+    instructions::hash_vaa,
+    PostVAAData,
     CHAIN_ID_SOLANA,
 };
 use solitaire::{
@@ -23,14 +25,6 @@ use solitaire::{
     CreationLamports::Exempt,
 };
 
-impl From<&PostVAAData> for GuardianSetDerivationData {
-    fn from(data: &PostVAAData) -> Self {
-        GuardianSetDerivationData {
-            index: data.guardian_set_index,
-        }
-    }
-}
-
 #[derive(FromAccounts)]
 pub struct PostVAA<'b> {
     /// Information about the current guardian set.
@@ -43,7 +37,7 @@ pub struct PostVAA<'b> {
     pub signature_set: Info<'b>,
 
     /// Message the VAA is associated with.
-    pub message: Mut<Message<'b, { AccountState::MaybeInitialized }>>,
+    pub message: Mut<PostedVAA<'b, { AccountState::MaybeInitialized }>>,
 
     /// Account used to pay for auxillary instructions.
     pub payer: Mut<Signer<Info<'b>>>,
@@ -65,33 +59,10 @@ pub struct Signature {
 
 pub type ForeignAddress = [u8; 32];
 
-#[derive(Default, BorshSerialize, BorshDeserialize)]
-pub struct PostVAAData {
-    // Header part
-    pub version: u8,
-    pub guardian_set_index: u32,
-
-    // Body part
-    pub timestamp: u32,
-    pub nonce: u32,
-    pub emitter_chain: u16,
-    pub emitter_address: ForeignAddress,
-    pub sequence: u64,
-    pub consistency_level: u8,
-    pub payload: Vec<u8>,
-}
-
 pub fn post_vaa(ctx: &ExecutionContext, accs: &mut PostVAA, vaa: PostVAAData) -> Result<()> {
-    let mut msg_derivation = MessageDerivationData {
-        emitter_key: vaa.emitter_address,
-        emitter_chain: vaa.emitter_chain,
-        nonce: vaa.nonce,
-        payload: vaa.payload.clone(),
-        sequence: None,
+    let mut msg_derivation = PostedVAADerivationData {
+        payload_hash: hash_vaa(&vaa).to_vec(),
     };
-    if vaa.emitter_chain != CHAIN_ID_SOLANA {
-        msg_derivation.sequence = Some(vaa.sequence)
-    }
 
     accs.message
         .verify_derivation(ctx.program_id, &msg_derivation)?;

+ 2 - 1
solana/bridge/program_stub/src/lib.rs

@@ -15,11 +15,12 @@ pub use api::{
     PostMessage,
     PostMessageData,
     PostVAA,
-    PostVAAData,
     Signature,
     UninitializedMessage,
 };
 
+use bridge::PostVAAData;
+
 solitaire! {
     Initialize(InitializeData)                  => initialize,
     PostMessage(PostMessageData)                => post_message,

+ 10 - 36
solana/modules/token_bridge/program/src/instructions.rs

@@ -39,15 +39,16 @@ use bridge::{
         Claim,
         ClaimDerivationData,
         FeeCollector,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
         Sequence,
         SequenceDerivationData,
     },
     api::ForeignAddress,
+    instructions::hash_vaa,
     types::{
         BridgeConfig,
-        PostedMessage,
+        PostedVAAData,
     },
     vaa::{
         ClaimableVAA,
@@ -304,6 +305,7 @@ pub fn transfer_native(
     program_id: Pubkey,
     bridge_id: Pubkey,
     payer: Pubkey,
+    message_key: Pubkey,
     from: Pubkey,
     mint: Pubkey,
     data: TransferNativeData,
@@ -328,16 +330,6 @@ pub fn transfer_native(
         to_chain: data.target_chain,
         fee: U256::from(data.fee),
     };
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: emitter_key.to_bytes(),
-            emitter_chain: 1,
-            nonce: data.nonce,
-            payload: payload.try_to_vec().unwrap(),
-            sequence: None,
-        },
-        &bridge_id,
-    );
     let sequence_key = Sequence::key(
         &SequenceDerivationData {
             emitter_key: &emitter_key,
@@ -357,7 +349,7 @@ pub fn transfer_native(
             AccountMeta::new_readonly(authority_signer_key, false),
             AccountMeta::new_readonly(custody_signer_key, false),
             AccountMeta::new(bridge_config, false),
-            AccountMeta::new(message_key, false),
+            AccountMeta::new(message_key, true),
             AccountMeta::new_readonly(emitter_key, false),
             AccountMeta::new(sequence_key, false),
             AccountMeta::new(fee_collector_key, false),
@@ -377,6 +369,7 @@ pub fn transfer_wrapped(
     program_id: Pubkey,
     bridge_id: Pubkey,
     payer: Pubkey,
+    message_key: Pubkey,
     from: Pubkey,
     from_owner: Pubkey,
     token_chain: u16,
@@ -412,16 +405,6 @@ pub fn transfer_wrapped(
         to_chain: data.target_chain,
         fee: U256::from(data.fee),
     };
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: emitter_key.to_bytes(),
-            emitter_chain: 1,
-            nonce: data.nonce,
-            payload: payload.try_to_vec().unwrap(),
-            sequence: None,
-        },
-        &bridge_id,
-    );
     let sequence_key = Sequence::key(
         &SequenceDerivationData {
             emitter_key: &emitter_key,
@@ -441,7 +424,7 @@ pub fn transfer_wrapped(
             AccountMeta::new_readonly(wrapped_meta_key, false),
             AccountMeta::new_readonly(authority_signer, false),
             AccountMeta::new(bridge_config, false),
-            AccountMeta::new(message_key, false),
+            AccountMeta::new(message_key, true),
             AccountMeta::new_readonly(emitter_key, false),
             AccountMeta::new(sequence_key, false),
             AccountMeta::new(fee_collector_key, false),
@@ -461,6 +444,7 @@ pub fn attest(
     program_id: Pubkey,
     bridge_id: Pubkey,
     payer: Pubkey,
+    message_key: Pubkey,
     mint: Pubkey,
     decimals: u8,
     mint_meta: Pubkey,
@@ -481,16 +465,6 @@ pub fn attest(
         symbol,
         name,
     };
-    let message_key = Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: emitter_key.to_bytes(),
-            emitter_chain: 1,
-            nonce,
-            payload: payload.try_to_vec().unwrap(),
-            sequence: None,
-        },
-        &bridge_id,
-    );
     let sequence_key = Sequence::key(
         &SequenceDerivationData {
             emitter_key: &emitter_key,
@@ -509,7 +483,7 @@ pub fn attest(
             AccountMeta::new_readonly(spl_metadata, false),
             // Bridge accounts
             AccountMeta::new(bridge_config, false),
-            AccountMeta::new(message_key, false),
+            AccountMeta::new(message_key, true),
             AccountMeta::new_readonly(emitter_key, false),
             AccountMeta::new(sequence_key, false),
             AccountMeta::new(fee_collector_key, false),

+ 27 - 38
solana/modules/token_bridge/program/src/wasm.rs

@@ -1,6 +1,7 @@
 use crate::{
     accounts::{
         AuthoritySigner,
+        EmitterAccount,
         WrappedDerivationData,
         WrappedMetaDerivationData,
         WrappedMint,
@@ -35,7 +36,8 @@ use crate::{
 };
 use borsh::BorshDeserialize;
 use bridge::{
-    accounts::MessageDerivationData,
+    accounts::PostedVAADerivationData,
+    instructions::hash_vaa,
     vaa::VAA,
     DeserializePayload,
     PostVAAData,
@@ -47,13 +49,13 @@ use solitaire::{
 };
 use std::str::FromStr;
 use wasm_bindgen::prelude::*;
-use crate::accounts::EmitterAccount;
 
 #[wasm_bindgen]
 pub fn attest_ix(
     program_id: String,
     bridge_id: String,
     payer: String,
+    message: String,
     mint: String,
     decimals: u8,
     mint_meta: String,
@@ -62,11 +64,12 @@ pub fn attest_ix(
     let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
     let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
+    let message = Pubkey::from_str(message.as_str()).unwrap();
     let mint = Pubkey::from_str(mint.as_str()).unwrap();
     let mint_meta = Pubkey::from_str(mint_meta.as_str()).unwrap();
 
     let ix = attest(
-        program_id, bridge_id, payer, mint, decimals, mint_meta, nonce,
+        program_id, bridge_id, payer, message, mint, decimals, mint_meta, nonce,
     )
     .unwrap();
 
@@ -78,6 +81,7 @@ pub fn transfer_native_ix(
     program_id: String,
     bridge_id: String,
     payer: String,
+    message: String,
     from: String,
     mint: String,
     nonce: u32,
@@ -89,6 +93,7 @@ pub fn transfer_native_ix(
     let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
     let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
+    let message = Pubkey::from_str(message.as_str()).unwrap();
     let from = Pubkey::from_str(from.as_str()).unwrap();
     let mint = Pubkey::from_str(mint.as_str()).unwrap();
 
@@ -99,6 +104,7 @@ pub fn transfer_native_ix(
         program_id,
         bridge_id,
         payer,
+        message,
         from,
         mint,
         TransferNativeData {
@@ -119,6 +125,7 @@ pub fn transfer_wrapped_ix(
     program_id: String,
     bridge_id: String,
     payer: String,
+    message: String,
     from: String,
     from_owner: String,
     token_chain: u16,
@@ -132,6 +139,7 @@ pub fn transfer_wrapped_ix(
     let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
     let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
+    let message = Pubkey::from_str(message.as_str()).unwrap();
     let from = Pubkey::from_str(from.as_str()).unwrap();
     let from_owner = Pubkey::from_str(from_owner.as_str()).unwrap();
 
@@ -144,6 +152,7 @@ pub fn transfer_wrapped_ix(
         program_id,
         bridge_id,
         payer,
+        message,
         from,
         from_owner,
         token_chain,
@@ -173,13 +182,9 @@ pub fn complete_transfer_native_ix(
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = PayloadTransfer::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload.clone(),
-            sequence: None,
+    let message_key = bridge::accounts::PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -222,13 +227,9 @@ pub fn complete_transfer_wrapped_ix(
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = PayloadTransfer::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload.clone(),
-            sequence: None,
+    let message_key = bridge::accounts::PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -271,13 +272,9 @@ pub fn create_wrapped_ix(
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = PayloadAssetMeta::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload.clone(),
-            sequence: None,
+    let message_key = bridge::accounts::PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &program_id,
     );
@@ -320,13 +317,9 @@ pub fn upgrade_contract_ix(
     let spill = Pubkey::from_str(spill.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = GovernancePayloadUpgrade::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload,
-            sequence: None,
+    let message_key = bridge::accounts::PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &bridge_id,
     );
@@ -354,13 +347,9 @@ pub fn register_chain_ix(
     let payer = Pubkey::from_str(payer.as_str()).unwrap();
     let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
     let payload = PayloadGovernanceRegisterChain::deserialize(&mut vaa.payload.as_slice()).unwrap();
-    let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
-        &MessageDerivationData {
-            emitter_key: vaa.emitter_address,
-            emitter_chain: vaa.emitter_chain,
-            nonce: vaa.nonce,
-            payload: vaa.payload.clone(),
-            sequence: None,
+    let message_key = bridge::accounts::PostedVAA::<'_, { AccountState::Uninitialized }>::key(
+        &PostedVAADerivationData {
+            payload_hash: hash_vaa(&vaa.clone().into()).to_vec(),
         },
         &bridge_id,
     );

+ 4 - 4
solana/modules/token_bridge/program/tests/common.rs

@@ -102,7 +102,7 @@ pub fn execute(
 mod helpers {
     use bridge::types::{
         ConsistencyLevel,
-        PostedMessage,
+        PostedVAAData,
     };
     use token_bridge::{
         CompleteNativeData,
@@ -117,7 +117,7 @@ mod helpers {
     use bridge::{
         accounts::{
             FeeCollector,
-            MessageDerivationData,
+            PostedVAADerivationData,
         },
         PostVAAData,
     };
@@ -654,8 +654,8 @@ mod helpers {
         payer: &Keypair,
         vaa: PostVAAData,
     ) -> Result<Pubkey, ClientError> {
-        let msg_key = bridge::accounts::Message::<'_, { AccountState::Initialized }>::key(
-            &MessageDerivationData {
+        let msg_key = bridge::accounts::PostedVAA::<'_, { AccountState::Initialized }>::key(
+            &PostedVAADerivationData {
                 emitter_key: vaa.emitter_address,
                 emitter_chain: vaa.emitter_chain,
                 nonce: vaa.nonce,

+ 4 - 4
solana/modules/token_bridge/program/tests/integration.rs

@@ -62,8 +62,8 @@ use bridge::{
         FeeCollector,
         GuardianSet,
         GuardianSetDerivationData,
-        Message,
-        MessageDerivationData,
+        PostedVAA,
+        PostedVAADerivationData,
         SignatureSet,
     },
     instruction,
@@ -74,8 +74,8 @@ use bridge::{
         GovernancePayloadSetMessageFee,
         GovernancePayloadTransferFees,
         GuardianSetData,
-        PostedMessage,
-        PostedMessageData,
+        MessageData,
+        PostedVAAData,
         SequenceTracker,
         SignatureSet as SignatureSetData,
     },