Merge pull request #227 from erickt/keyid-order

Preserve the order of key ids in the root metadata
diff --git a/src/interchange/cjson/shims.rs b/src/interchange/cjson/shims.rs
index 84bf28e..d916318 100644
--- a/src/interchange/cjson/shims.rs
+++ b/src/interchange/cjson/shims.rs
@@ -107,12 +107,11 @@
 
 impl RoleDefinition {
     pub fn from(role: &metadata::RoleDefinition) -> Result<Self> {
-        let mut key_ids = role
+        let key_ids = role
             .key_ids()
             .iter()
             .cloned()
             .collect::<Vec<crypto::KeyId>>();
-        key_ids.sort();
 
         Ok(RoleDefinition {
             threshold: role.threshold(),
@@ -120,7 +119,7 @@
         })
     }
 
-    pub fn try_into(mut self) -> Result<metadata::RoleDefinition> {
+    pub fn try_into(self) -> Result<metadata::RoleDefinition> {
         let vec_len = self.key_ids.len();
         if vec_len < 1 {
             return Err(Error::Encoding(
@@ -128,8 +127,13 @@
             ));
         }
 
-        let key_ids = self.key_ids.drain(0..).collect::<HashSet<crypto::KeyId>>();
-        let dupes = vec_len - key_ids.len();
+        let mut seen = HashSet::new();
+        let mut dupes = 0;
+        for key_id in self.key_ids.iter() {
+            if !seen.insert(key_id) {
+                dupes += 1;
+            }
+        }
 
         if dupes != 0 {
             return Err(Error::Encoding(format!(
@@ -138,7 +142,7 @@
             )));
         }
 
-        Ok(metadata::RoleDefinition::new(self.threshold, key_ids)?)
+        Ok(metadata::RoleDefinition::new(self.threshold, self.key_ids)?)
     }
 }
 
diff --git a/src/metadata.rs b/src/metadata.rs
index 3c7d72c..c2db2ef 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -489,13 +489,13 @@
     consistent_snapshot: bool,
     keys: HashMap<KeyId, PublicKey>,
     root_threshold: u32,
-    root_key_ids: HashSet<KeyId>,
+    root_key_ids: Vec<KeyId>,
     snapshot_threshold: u32,
-    snapshot_key_ids: HashSet<KeyId>,
+    snapshot_key_ids: Vec<KeyId>,
     targets_threshold: u32,
-    targets_key_ids: HashSet<KeyId>,
+    targets_key_ids: Vec<KeyId>,
     timestamp_threshold: u32,
-    timestamp_key_ids: HashSet<KeyId>,
+    timestamp_key_ids: Vec<KeyId>,
 }
 
 impl RootMetadataBuilder {
@@ -512,13 +512,13 @@
             consistent_snapshot: false,
             keys: HashMap::new(),
             root_threshold: 1,
-            root_key_ids: HashSet::new(),
+            root_key_ids: Vec::new(),
             snapshot_threshold: 1,
-            snapshot_key_ids: HashSet::new(),
+            snapshot_key_ids: Vec::new(),
             targets_threshold: 1,
-            targets_key_ids: HashSet::new(),
+            targets_key_ids: Vec::new(),
             timestamp_threshold: 1,
-            timestamp_key_ids: HashSet::new(),
+            timestamp_key_ids: Vec::new(),
         }
     }
 
@@ -550,7 +550,7 @@
     pub fn root_key(mut self, public_key: PublicKey) -> Self {
         let key_id = public_key.key_id().clone();
         self.keys.insert(key_id.clone(), public_key);
-        self.root_key_ids.insert(key_id);
+        self.root_key_ids.push(key_id);
         self
     }
 
@@ -564,7 +564,7 @@
     pub fn snapshot_key(mut self, public_key: PublicKey) -> Self {
         let key_id = public_key.key_id().clone();
         self.keys.insert(key_id.clone(), public_key);
-        self.snapshot_key_ids.insert(key_id);
+        self.snapshot_key_ids.push(key_id);
         self
     }
 
@@ -578,7 +578,7 @@
     pub fn targets_key(mut self, public_key: PublicKey) -> Self {
         let key_id = public_key.key_id().clone();
         self.keys.insert(key_id.clone(), public_key);
-        self.targets_key_ids.insert(key_id);
+        self.targets_key_ids.push(key_id);
         self
     }
 
@@ -592,7 +592,7 @@
     pub fn timestamp_key(mut self, public_key: PublicKey) -> Self {
         let key_id = public_key.key_id().clone();
         self.keys.insert(key_id.clone(), public_key);
-        self.timestamp_key_ids.insert(key_id);
+        self.timestamp_key_ids.push(key_id);
         self
     }
 
@@ -756,12 +756,12 @@
 #[derive(Clone, Debug, PartialEq)]
 pub struct RoleDefinition {
     threshold: u32,
-    key_ids: HashSet<KeyId>,
+    key_ids: Vec<KeyId>,
 }
 
 impl RoleDefinition {
     /// Create a new `RoleDefinition` with a given threshold and set of authorized `KeyID`s.
-    pub fn new(threshold: u32, key_ids: HashSet<KeyId>) -> Result<Self> {
+    pub fn new(threshold: u32, key_ids: Vec<KeyId>) -> Result<Self> {
         if threshold < 1 {
             return Err(Error::IllegalArgument(format!("Threshold: {}", threshold)));
         }
@@ -789,7 +789,7 @@
     }
 
     /// An immutable reference to the set of `KeyID`s that are authorized to sign the role.
-    pub fn key_ids(&self) -> &HashSet<KeyId> {
+    pub fn key_ids(&self) -> &[KeyId] {
         &self.key_ids
     }
 }
@@ -2025,18 +2025,20 @@
 
     #[test]
     fn serde_role_definition() {
-        let hashes = hashset!(
-            "01892c662c8cd79fab20edec21de1dcb8b75d9353103face7fe086ff5c0098e4",
-            "4750eaf6878740780d6f97b12dbad079fb012bec88c78de2c380add56d3f51db",
-        )
-        .iter()
-        .map(|k| KeyId::from_str(*k).unwrap())
-        .collect();
-        let role_def = RoleDefinition::new(2, hashes).unwrap();
+        // keyid ordering must be preserved.
+        let keyids = vec![
+            KeyId::from_str("40e35e8f6003ab90d104710cf88901edab931597401f91c19eeb366060ab3d53")
+                .unwrap(),
+            KeyId::from_str("01892c662c8cd79fab20edec21de1dcb8b75d9353103face7fe086ff5c0098e4")
+                .unwrap(),
+            KeyId::from_str("4750eaf6878740780d6f97b12dbad079fb012bec88c78de2c380add56d3f51db")
+                .unwrap(),
+        ];
+        let role_def = RoleDefinition::new(3, keyids).unwrap();
         let jsn = json!({
-            "threshold": 2,
+            "threshold": 3,
             "keyids": [
-                // these need to be sorted for determinism
+                "40e35e8f6003ab90d104710cf88901edab931597401f91c19eeb366060ab3d53",
                 "01892c662c8cd79fab20edec21de1dcb8b75d9353103face7fe086ff5c0098e4",
                 "4750eaf6878740780d6f97b12dbad079fb012bec88c78de2c380add56d3f51db",
             ],
@@ -2045,7 +2047,10 @@
         assert_eq!(encoded, jsn);
         let decoded: RoleDefinition = serde_json::from_value(encoded).unwrap();
         assert_eq!(decoded, role_def);
+    }
 
+    #[test]
+    fn serde_invalid_role_definitions() {
         let jsn = json!({
             "threshold": 0,
             "keyids": [
@@ -2748,12 +2753,12 @@
     fn deserialize_json_role_definition_illegal_threshold() {
         let role_def = RoleDefinition::new(
             1,
-            hashset!(
+            vec![
                 PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519)
                     .unwrap()
                     .key_id()
-                    .clone()
-            ),
+                    .clone(),
+            ],
         )
         .unwrap();
 
@@ -2767,7 +2772,7 @@
 
         let role_def = RoleDefinition::new(
             2,
-            hashset!(
+            vec![
                 PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519)
                     .unwrap()
                     .key_id()
@@ -2776,7 +2781,7 @@
                     .unwrap()
                     .key_id()
                     .clone(),
-            ),
+            ],
         )
         .unwrap();
 
@@ -2814,7 +2819,7 @@
             .unwrap()
             .key_id()
             .clone();
-        let role_def = RoleDefinition::new(1, hashset!(key_id.clone())).unwrap();
+        let role_def = RoleDefinition::new(1, vec![key_id.clone()]).unwrap();
         let mut jsn = serde_json::to_value(&role_def).unwrap();
 
         match jsn.as_object_mut() {