|
@@ -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);
|
|
|
+ }
|
|
|
}
|