Browse Source

add share updates

Chelsea H. Komlo 5 years ago
parent
commit
3746a021cc
1 changed files with 74 additions and 13 deletions
  1. 74 13
      src/vss.rs

+ 74 - 13
src/vss.rs

@@ -110,19 +110,35 @@ pub fn reconstruct_secret(shares: &Vec<Share>) -> Result<Secret, &'static str> {
     return Ok(secret)
 }
 
-/// Create a proactive update.
-pub fn create_update(numshares: u32, threshold: u32) -> Result<(Commitment, Vec<Share>), &'static str> {
-    unimplemented!("Not yet implemented")
-}
+/// Create and apply a proactive update to a master commitment.
+pub fn update_shares(old_commitment: &Commitment, old_shares: &Vec<Share>) -> Result<(Commitment, Vec<Share>), &'static str> {
+    let num_shares = old_shares.len() as u32;
+    let threshold = old_commitment.coms.len() as u32;
+    let res = generate_shares(Scalar::zero(), num_shares, threshold);
+
+    if !res.is_ok() {
+        return res;
+    }
 
-/// Apply the commitment for the update to the master commitment.
-pub fn apply_commitment_update(oldcommitment: &Commitment, update: &Commitment) -> Result<Commitment, &'static str> {
-    unimplemented!("Not yet implemented")
-}
+    let (update_commitments, update_shares) = res.unwrap();
+
+    let mut new_shares: Vec<Share> = Vec::with_capacity(num_shares as usize);
+    for old_share in old_shares {
+        let update_share = update_shares[(old_share.index-1) as usize];
+        let new_share = Share{
+            index: old_share.index,
+            value: old_share.value + update_share.value,
+        };
+        new_shares.push(new_share);
+    }
 
-/// Apply the share update to an existing share
-pub fn apply_share_update(oldshare: &Share, update: &Share) -> Result<Share, &'static str> {
-    unimplemented!("Not yet implemented")
+    let mut new_commitments: Commitment = Commitment { coms: Vec::with_capacity(threshold as usize) };
+    for i in 0..old_commitment.coms.len() {
+        let new_commitment = old_commitment.coms[i] + update_commitments.coms[i];
+        new_commitments.coms.push(new_commitment);
+    }
+
+    Ok((new_commitments, new_shares))
 }
 
 #[cfg(test)]
@@ -137,6 +153,7 @@ mod tests {
         assert!(res.is_ok());
         let (com, shares) = res.unwrap();
         assert!(shares.len() == 5);
+        assert!(com.coms.len() == 2);
 
         let mut recshares: Vec<Share> = Vec::new();
         recshares.push(shares[1]);
@@ -152,7 +169,7 @@ mod tests {
 
         let res = generate_shares(s, 5, 2);
         assert!(res.is_ok());
-        let (com, shares) = res.unwrap();
+        let (_, shares) = res.unwrap();
 
         let mut recshares: Vec<Share> = Vec::new();
         recshares.push(shares[1]);
@@ -167,7 +184,7 @@ mod tests {
 
         let res = generate_shares(s, 5, 2);
         assert!(res.is_ok());
-        let (com, shares) = res.unwrap();
+        let (_, shares) = res.unwrap();
 
         let mut recshares: Vec<Share> = Vec::new();
         recshares.push(shares[1]);
@@ -233,4 +250,48 @@ mod tests {
             assert_ne!(is_valid.unwrap(), true);
         }
     }
+
+    #[test]
+    fn share_update_valid() {
+        let s = Secret::from(42u32);
+
+        let res = generate_shares(s, 5, 2);
+        assert!(res.is_ok());
+        let (com, shares) = res.unwrap();
+
+        let update_res = update_shares(&com, &shares);
+        assert!(update_res.is_ok());
+        let (update_com, update_shares) = update_res.unwrap();
+
+        for share in update_shares {
+            let is_valid = verify_share(share, &update_com);
+            assert!(is_valid.is_ok());
+            assert!(is_valid.unwrap());
+        }
+    }
+
+    #[test]
+    fn share_update_invalid() {
+        let s = Secret::from(42u32);
+
+        let res = generate_shares(s, 5, 2);
+        assert!(res.is_ok());
+        let (com, shares) = res.unwrap();
+
+        let update_res = update_shares(&com, &shares);
+        assert!(update_res.is_ok());
+        let (update_com, update_shares) = update_res.unwrap();
+
+        // test that the old shares are not valid with the updated commitment
+        for share in shares {
+            let is_valid = verify_share(share, &update_com);
+            assert!(is_valid.is_ok());
+            assert!(!is_valid.unwrap());
+        }
+
+        // assert that we can recover the original secret using the updated shares
+        let recres = reconstruct_secret(&update_shares);
+        assert!(recres.is_ok());
+        assert_eq!(recres.unwrap(), s);
+    }
 }