소스 검색

Fixed guardian set expiration and quorum logic, tests updated

Yuriy Savchenko 5 년 전
부모
커밋
eaee9c0638
3개의 변경된 파일55개의 추가작업 그리고 7개의 파일을 삭제
  1. 12 6
      terra/contracts/wormhole/src/contract.rs
  2. 42 0
      terra/contracts/wormhole/src/state.rs
  3. 1 1
      terra/tools/prepare-wormhole.ts

+ 12 - 6
terra/contracts/wormhole/src/contract.rs

@@ -132,17 +132,16 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
     if vaa_archive_check(&deps.storage, &hash) {
         return ContractError::VaaAlreadyExecuted.std_err();
     }
-    vaa_archive_add(&mut deps.storage, &hash)?;
-
+    
     // Load and check guardian set
     let guardian_set = guardian_set_get(&deps.storage, vaa_guardian_set_index);
     let guardian_set: GuardianSetInfo =
         guardian_set.or(ContractError::InvalidGuardianSetIndex.std_err())?;
 
-    if guardian_set.expiration_time == 0 || guardian_set.expiration_time > env.block.time {
+    if guardian_set.expiration_time == 0 || guardian_set.expiration_time < env.block.time {
         return ContractError::GuardianSetExpired.std_err();
     }
-    if len_signers < (guardian_set.addresses.len() / 4) * 3 + 1 {
+    if len_signers < guardian_set.quorum() {
         return ContractError::NoQuorum.std_err();
     }
 
@@ -176,7 +175,7 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
     let action = data.get_u8(body_offset + 4);
     let payload = &data[body_offset + 5..];
 
-    match action {
+    let result = match action {
         0x01 => {
             if vaa_guardian_set_index != state.guardian_set_index {
                 return ContractError::NotCurrentGuardianSet.std_err();
@@ -185,7 +184,13 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
         }
         0x10 => vaa_transfer(deps, env, payload),
         _ => ContractError::InvalidVAAAction.std_err(),
+    };
+
+    if result.is_ok() {
+        vaa_archive_add(&mut deps.storage, &hash)?;
     }
+
+    result
 }
 
 /// Handle wrapped asset registration messages
@@ -554,6 +559,7 @@ fn keys_equal(a: &VerifyKey, b: &GuardianAddress) -> bool {
 
 #[cfg(test)]
 mod tests {
+    use std::time::{UNIX_EPOCH, SystemTime};
     use super::*;
     use crate::state::GuardianSetInfo;
     use cosmwasm_std::testing::{mock_dependencies, mock_env};
@@ -577,7 +583,7 @@ mod tests {
         let init_msg = InitMsg {
             initial_guardian_set: GuardianSetInfo {
                 addresses: guardians.clone(),
-                expiration_time: 100,
+                expiration_time: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 1000,
             },
             guardian_set_expirity: 50,
             wrapped_asset_code_id: 999,

+ 42 - 0
terra/contracts/wormhole/src/state.rs

@@ -55,6 +55,12 @@ pub struct GuardianSetInfo {
     pub expiration_time: u64,            // Guardian set expiration time
 }
 
+impl GuardianSetInfo {
+    pub fn quorum(&self) -> usize {
+        ((self.addresses.len() * 10 / 3) * 2) / 10 + 1
+    }
+}
+
 // Wormhole contract generic information
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
 pub struct WormholeInfo {
@@ -108,3 +114,39 @@ pub fn wrapped_asset_address<S: Storage>(storage: &mut S) -> Bucket<S, Vec<u8>>
 pub fn wrapped_asset_address_read<S: Storage>(storage: &S) -> ReadonlyBucket<S, Vec<u8>> {
     bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage)
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn build_guardian_set(length: usize) -> GuardianSetInfo {
+        let mut addresses: Vec<GuardianAddress> = Vec::with_capacity(length);
+        for _ in 0..length {
+            addresses.push(GuardianAddress{bytes: vec![].into()});
+        }
+
+        GuardianSetInfo {
+            addresses,
+            expiration_time: 0,
+        }
+    }
+
+    #[test]
+    fn quardian_set_quorum() {
+        assert_eq!(build_guardian_set(1).quorum(), 1);
+        assert_eq!(build_guardian_set(2).quorum(), 2);
+        assert_eq!(build_guardian_set(3).quorum(), 3);
+        assert_eq!(build_guardian_set(4).quorum(), 3);
+        assert_eq!(build_guardian_set(5).quorum(), 4);
+        assert_eq!(build_guardian_set(6).quorum(), 5);
+        assert_eq!(build_guardian_set(7).quorum(), 5);
+        assert_eq!(build_guardian_set(8).quorum(), 6);
+        assert_eq!(build_guardian_set(9).quorum(), 7);
+        assert_eq!(build_guardian_set(10).quorum(), 7);
+        assert_eq!(build_guardian_set(11).quorum(), 8);
+        assert_eq!(build_guardian_set(12).quorum(), 9);
+        assert_eq!(build_guardian_set(20).quorum(), 14);
+        assert_eq!(build_guardian_set(25).quorum(), 17);
+        assert_eq!(build_guardian_set(100).quorum(), 67);
+    }
+}

+ 1 - 1
terra/tools/prepare-wormhole.ts

@@ -15,7 +15,7 @@ async function script() {
             addresses: [
                 { bytes: Buffer.from('beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe', 'hex').toString('base64') }
             ],
-            expiration_time: 1000 * 60 * 60
+            expiration_time: Math.floor(Date.now() / 1000) + 1000 * 60 * 60
         },
         guardian_set_expirity: 0,
         wrapped_asset_code_id: wrapped_code_id,