Browse Source

Fix Governance Headers

Change-Id: If2026ff4a6107327f69c5d0675a736e6ab87f1bd
Reisen 4 years ago
parent
commit
99c3e40968

+ 6 - 3
solana/bridge/program/src/api/governance.rs

@@ -57,7 +57,7 @@ where
 #[derive(FromAccounts)]
 pub struct UpgradeContract<'b> {
     /// Payer for account creation (vaa-claim)
-    pub payer: Signer<Info<'b>>,
+    pub payer: Mut<Signer<Info<'b>>>,
 
     /// Upgrade VAA
     pub vaa: ClaimableVAA<'b, GovernancePayloadUpgrade>,
@@ -91,8 +91,10 @@ pub fn upgrade_contract(
         accs.spill.key,
     );
 
-    let _seeds = accs.upgrade_authority.self_seeds(None);
-    invoke_signed(&upgrade_ix, ctx.accounts, &[])?;
+    let seeds = accs.upgrade_authority.self_bumped_seeds(None, ctx.program_id);
+    let seeds: Vec<&[u8]> = seeds.iter().map(|item| item.as_slice()).collect();
+    let seeds = seeds.as_slice();
+    invoke_signed(&upgrade_ix, ctx.accounts, &[seeds])?;
 
     Ok(())
 }
@@ -138,6 +140,7 @@ pub fn upgrade_guardian_set(
     _data: UpgradeGuardianSetData,
 ) -> Result<()> {
     verify_claim(&accs.vaa)?;
+
     accs.guardian_set_old.verify_derivation(
         ctx.program_id,
         &GuardianSetDerivationData {

+ 0 - 2
solana/bridge/program/src/api/verify_signature.rs

@@ -62,8 +62,6 @@ pub struct VerifySignaturesData {
     pub hash: [u8; 32],
     /// instruction indices of signers (-1 for missing)
     pub signers: [i8; MAX_LEN_GUARDIAN_KEYS],
-    /// indicates whether this verification should only succeed if the sig account does not exist
-    pub initial_creation: bool,
 }
 
 /// SigInfo contains metadata about signers in a VerifySignature ix

+ 3 - 3
solana/bridge/program/src/instructions.rs

@@ -240,10 +240,10 @@ pub fn upgrade_contract(
 
         accounts: vec![
             AccountMeta::new(payer, true),
-            AccountMeta::new(payload_message, false),
+            AccountMeta::new_readonly(payload_message, false),
             AccountMeta::new(claim, false),
-            AccountMeta::new(upgrade_authority, false),
-            AccountMeta::new(spill, false),
+            AccountMeta::new_readonly(upgrade_authority, false),
+            AccountMeta::new_readonly(spill, false),
         ],
 
         data: (crate::instruction::Instruction::UpgradeContract, UpgradeContractData {})

+ 11 - 2
solana/bridge/program/src/types.rs

@@ -251,6 +251,7 @@ where
 {
     fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
         let mut c = Cursor::new(buf);
+        Self::check_governance_header(&mut c)?;
 
         let new_index = c.read_u32::<BigEndian>()?;
 
@@ -270,7 +271,7 @@ where
 }
 
 impl DeserializeGovernancePayload for GovernancePayloadGuardianSetChange {
-    const MODULE: &'static str = "CORE";
+    const MODULE: &'static str = "Core";
     const ACTION: u8 = 1;
 }
 
@@ -279,13 +280,19 @@ pub struct GovernancePayloadUpgrade {
     pub new_contract: Pubkey,
 }
 
+impl SerializePayload for GovernancePayloadUpgrade {
+    fn serialize<W: Write>(&self, v: &mut W) -> std::result::Result<(), SolitaireError> {
+        v.write(&self.new_contract.to_bytes())?;
+        Ok(())
+    }
+}
+
 impl DeserializePayload for GovernancePayloadUpgrade
 where
     Self: DeserializeGovernancePayload,
 {
     fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
         let mut c = Cursor::new(buf);
-
         Self::check_governance_header(&mut c)?;
 
         let mut addr = [0u8; 32];
@@ -329,6 +336,7 @@ where
 {
     fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
         let mut c = Cursor::new(buf);
+        Self::check_governance_header(&mut c)?;
 
         let mut fee_data: [u8; 32] = [0; 32];
         c.read_exact(&mut fee_data)?;
@@ -374,6 +382,7 @@ where
 {
     fn deserialize(buf: &mut &[u8]) -> Result<Self, SolitaireError> {
         let mut c = Cursor::new(buf);
+        Self::check_governance_header(&mut c)?;
 
         let mut amount_data: [u8; 32] = [0; 32];
         c.read_exact(&mut amount_data)?;

+ 15 - 1
solana/bridge/program/src/vaa.rs

@@ -39,13 +39,27 @@ use std::{
     ops::Deref,
 };
 
-pub trait SerializePayload: Sized {
+pub trait SerializePayload: Sized + DeserializeGovernancePayload {
     fn serialize<W: Write>(&self, writer: &mut W) -> std::result::Result<(), SolitaireError>;
     fn try_to_vec(&self) -> std::result::Result<Vec<u8>, SolitaireError> {
         let mut result = Vec::with_capacity(256);
+        self.write_governance_header(&mut result)?;
         self.serialize(&mut result)?;
         Ok(result)
     }
+
+    fn write_governance_header<W: Write>(
+        &self,
+        c: &mut W,
+    ) -> std::result::Result<(), SolitaireError> {
+        use byteorder::WriteBytesExt;
+        let module = format!("{:\0>32}", Self::MODULE);
+        let module = module.as_bytes();
+        c.write(&module)?;
+        c.write_u8(Self::ACTION)?;
+        c.write_u16::<BigEndian>(CHAIN_ID_SOLANA)?;
+        Ok(())
+    }
 }
 
 pub trait DeserializePayload: Sized {

+ 18 - 13
solana/bridge/program/tests/common.rs

@@ -75,6 +75,7 @@ use bridge::{
     instructions,
     types::{
         BridgeConfig,
+        ConsistencyLevel,
         PostedMessage,
         SequenceTracker,
     },
@@ -207,6 +208,7 @@ mod helpers {
                 .unwrap()
                 .as_secs() as u32,
             nonce,
+            consistency_level: ConsistencyLevel::Confirmed as u8,
         };
 
         // Hash data, the thing we wish to actually sign.
@@ -217,6 +219,7 @@ mod helpers {
             v.write_u16::<BigEndian>(vaa.emitter_chain).unwrap();
             v.write(&vaa.emitter_address).unwrap();
             v.write_u64::<BigEndian>(vaa.sequence).unwrap();
+            v.write_u8(vaa.consistency_level).unwrap();
             v.write(&vaa.payload).unwrap();
             v.into_inner()
         };
@@ -293,6 +296,7 @@ mod helpers {
             nonce,
             data,
             persist,
+            ConsistencyLevel::Confirmed,
         )
         .unwrap();
 
@@ -337,7 +341,6 @@ mod helpers {
                         guardian_set_version,
                         VerifySignaturesData {
                             hash: body_hash,
-                            initial_creation: true,
                             signers,
                         },
                     )
@@ -364,49 +367,51 @@ mod helpers {
         )
     }
 
-    pub fn upgrade_contract(
+    pub fn upgrade_guardian_set(
         client: &RpcClient,
         program: &Pubkey,
         payer: &Keypair,
         payload_message: Pubkey,
-        spill: Pubkey,
+        emitter: Pubkey,
+        old_index: u32,
+        new_index: u32,
+        sequence: u64,
     ) -> Result<Signature, ClientError> {
         execute(
             client,
             payer,
             &[payer],
-            &[instructions::upgrade_contract(
+            &[instructions::upgrade_guardian_set(
                 *program,
                 payer.pubkey(),
                 payload_message,
-                spill,
+                emitter,
+                old_index,
+                new_index,
+                sequence,
             )],
             CommitmentConfig::processed(),
         )
     }
 
-    pub fn upgrade_guardian_set(
+    pub fn upgrade_contract(
         client: &RpcClient,
         program: &Pubkey,
         payer: &Keypair,
         payload_message: Pubkey,
         emitter: Pubkey,
-        old_index: u32,
-        new_index: u32,
+        spill: Pubkey,
         sequence: u64,
     ) -> Result<Signature, ClientError> {
         execute(
             client,
             payer,
             &[payer],
-            &[instructions::upgrade_guardian_set(
+            &[instructions::upgrade_contract(
                 *program,
                 payer.pubkey(),
                 payload_message,
-                emitter,
-                old_index,
-                new_index,
-                sequence,
+                spill,
             )],
             CommitmentConfig::processed(),
         )

+ 48 - 0
solana/bridge/program/tests/integration.rs

@@ -69,9 +69,11 @@ use bridge::{
     types::{
         BridgeConfig,
         BridgeData,
+        ConsistencyLevel,
         GovernancePayloadGuardianSetChange,
         GovernancePayloadSetMessageFee,
         GovernancePayloadTransferFees,
+        GovernancePayloadUpgrade,
         GuardianSetData,
         PostedMessage,
         PostedMessageData,
@@ -140,6 +142,7 @@ fn run_integration_tests() {
     test_persistent_bridge_messages(&mut context);
     test_invalid_emitter(&mut context);
     test_duplicate_messages_fail(&mut context);
+    test_upgrade_contract(&mut context);
     test_guardian_set_change(&mut context);
     test_guardian_set_change_fails(&mut context);
     test_set_fees(&mut context);
@@ -444,6 +447,7 @@ fn test_invalid_emitter(context: &mut Context) {
         nonce,
         message,
         false,
+        ConsistencyLevel::Confirmed,
     )
     .unwrap();
 
@@ -1255,3 +1259,47 @@ fn test_transfer_total_fails(context: &mut Context) {
         account_balance + 10_000
     );
 }
+
+fn test_upgrade_contract(context: &mut Context) {
+    // Initialize a wormhole bridge on Solana to test with.
+    let (ref payer, ref client, ref program) = common::setup();
+
+    // Upgrade the guardian set with a new set of guardians.
+    let (new_public_keys, new_secret_keys) = common::generate_keys(1);
+
+    let nonce = rand::thread_rng().gen();
+    let emitter = Keypair::from_bytes(&GOVERNANCE_KEY).unwrap();
+    let sequence = context.seq.next(emitter.pubkey().to_bytes());
+    let message = GovernancePayloadUpgrade {
+        new_contract: Pubkey::new_unique(),
+    }
+    .try_to_vec()
+    .unwrap();
+
+    let message_key = common::post_message(
+        client,
+        program,
+        payer,
+        &emitter,
+        nonce,
+        message.clone(),
+        10_000,
+        false,
+    )
+    .unwrap();
+
+    let (vaa, body, body_hash) = common::generate_vaa(&emitter, message.clone(), nonce, 0, 1);
+    common::verify_signatures(client, program, payer, body, body_hash, &context.secret, 0).unwrap();
+    common::post_vaa(client, program, payer, vaa).unwrap();
+    common::upgrade_contract(
+        client,
+        program,
+        payer,
+        message_key,
+        emitter.pubkey(),
+        Pubkey::new_unique(),
+        sequence,
+    )
+    .unwrap();
+    common::sync(client, payer);
+}

+ 12 - 0
solana/modules/token_bridge/Cargo.lock

@@ -1189,6 +1189,12 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
+[[package]]
+name = "hex-literal"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76505e26b6ca3bbdbbb360b68472abbb80998c5fa5dc43672eca34f28258e138"
+
 [[package]]
 name = "hidapi"
 version = "1.2.6"
@@ -3442,10 +3448,16 @@ dependencies = [
  "borsh",
  "bridge",
  "byteorder",
+ "hex",
+ "hex-literal",
+ "libsecp256k1",
  "primitive-types",
+ "rand 0.7.3",
  "rocksalt",
  "sha3",
+ "solana-client",
  "solana-program",
+ "solana-sdk",
  "solitaire",
  "solitaire-client",
  "spl-token",

+ 0 - 0
solana/bridge/rustfmt.toml → solana/rustfmt.toml