From 28e525a891ea2f00ed946e94e633ce96b616f0fc Mon Sep 17 00:00:00 2001 From: Peter Nose Date: Tue, 7 May 2024 13:00:11 +0200 Subject: [PATCH 1/2] secret-sharing/src/churp: Rename player to shareholder --- go/keymanager/churp/status.go | 4 +- keymanager/src/churp/errors.rs | 8 +- keymanager/src/churp/handler.rs | 137 ++++++++++++++-------------- secret-sharing/src/churp/handoff.rs | 114 +++++++++++------------ secret-sharing/src/churp/player.rs | 24 ++--- secret-sharing/src/churp/switch.rs | 109 +++++++++++----------- 6 files changed, 200 insertions(+), 196 deletions(-) diff --git a/go/keymanager/churp/status.go b/go/keymanager/churp/status.go index 3209fe0954a..3f80a014704 100644 --- a/go/keymanager/churp/status.go +++ b/go/keymanager/churp/status.go @@ -176,8 +176,8 @@ func (s *Status) MinApplicants() int { switch s.HandoffKind() { case HandoffKindDealingPhase: // The number of nodes must be at least t+2, ensuring that even if - // t Byzantine dealers reveal their secret, an honest player cannot - // compute the combined bivariate polynomial. + // t Byzantine dealers reveal their secret, an honest shareholder + // cannot compute the combined bivariate polynomial. return max(t+e+1, t+2) case HandoffKindCommitteeUnchanged: return t + e + 1 diff --git a/keymanager/src/churp/errors.rs b/keymanager/src/churp/errors.rs index cfd6c7b18b3..288f5d82c25 100644 --- a/keymanager/src/churp/errors.rs +++ b/keymanager/src/churp/errors.rs @@ -43,10 +43,6 @@ pub enum Error { NotAuthorized, #[error("not in committee")] NotInCommittee, - #[error("player mismatch")] - PlayerMismatch, - #[error("player not found")] - PlayerNotFound, #[error("point decoding failed")] PointDecodingFailed, #[error("policy rollback")] @@ -55,6 +51,10 @@ pub enum Error { PolynomialDecodingFailed, #[error("runtime mismatch")] RuntimeMismatch, + #[error("shareholder mismatch")] + ShareholderMismatch, + #[error("shareholder not found")] + ShareholderNotFound, #[error("status not published")] StatusNotPublished, #[error("verification matrix decoding failed")] diff --git a/keymanager/src/churp/handler.rs b/keymanager/src/churp/handler.rs index 0971083e74e..a9795ae73dd 100644 --- a/keymanager/src/churp/handler.rs +++ b/keymanager/src/churp/handler.rs @@ -36,7 +36,7 @@ use oasis_core_runtime::{ }; use secret_sharing::{ - churp::{Dealer, Handoff, HandoffKind, Player, ShareholderId}, + churp::{Dealer, Handoff, HandoffKind, Shareholder, ShareholderId}, suites::{p384, Suite}, vss::{ matrix::VerificationMatrix, @@ -108,9 +108,9 @@ pub struct Churp { #[cfg_attr(not(target_env = "sgx"), allow(unused))] registry_state: RegistryState, - /// Players with secret shares for the last successfully completed handoff, - /// one per scheme. - players: Mutex>, + /// Shareholders with secret shares for the last successfully completed + /// handoff, one per scheme. + shareholders: Mutex>, /// Dealers of bivariate shares for the next handoff, one per scheme. dealers: Mutex>, /// Next handoffs, limited to one per scheme. @@ -138,7 +138,7 @@ impl Churp { let churp_state = ChurpState::new(consensus_verifier.clone()); let registry_state = RegistryState::new(consensus_verifier.clone()); - let players = Mutex::new(HashMap::new()); + let shareholders = Mutex::new(HashMap::new()); let dealers = Mutex::new(HashMap::new()); let handoffs = Mutex::new(HashMap::new()); @@ -153,7 +153,7 @@ impl Churp { consensus_verifier, storage, beacon_state, - players, + shareholders, churp_state, registry_state, dealers, @@ -191,10 +191,12 @@ impl Churp { /// of the matrix should always be verified against the consensus layer. pub fn verification_matrix(&self, req: &QueryRequest) -> Result> { let status = self.verify_last_handoff(req.id, req.runtime_id, req.epoch)?; - let player = match status.suite_id { - SuiteId::NistP384Sha3_384 => self.get_player::(req.id, req.epoch)?, + let shareholder = match status.suite_id { + SuiteId::NistP384Sha3_384 => { + self.get_shareholder::(req.id, req.epoch)? + } }; - let vm = player.verification_matrix().to_bytes(); + let vm = shareholder.verification_matrix().to_bytes(); Ok(vm) } @@ -253,8 +255,8 @@ impl Churp { S: Suite + 'static, { let id = ShareholderId(node_id.0); - let player = self.get_player::(status.id, status.handoff)?; - let point = player.switch_point(id)?; + let shareholder = self.get_shareholder::(status.id, status.handoff)?; + let point = shareholder.switch_point(id)?; let point = scalar_to_bytes(&point); Ok(point) @@ -319,8 +321,8 @@ impl Churp { { let id = ShareholderId(node_id.0); let handoff = self.get_handoff::(status.id, status.next_handoff)?; - let player = handoff.get_reduced_player()?; - let point = player.switch_point(id)?; + let shareholder = handoff.get_reduced_shareholder()?; + let point = shareholder.switch_point(id)?; let point = scalar_to_bytes(&point); Ok(point) @@ -541,12 +543,12 @@ impl Churp { // Fetch from the host node. if node_id == self.node_id { - let player = self.get_player::(status.id, status.handoff)?; - let point = player.switch_point(id)?; + let shareholder = self.get_shareholder::(status.id, status.handoff)?; + let point = shareholder.switch_point(id)?; if handoff.needs_verification_matrix()? { // Local verification matrix is trusted. - let vm = player.verification_matrix().clone(); + let vm = shareholder.verification_matrix().clone(); handoff.set_verification_matrix(vm)?; } @@ -644,8 +646,8 @@ impl Churp { // Fetch from the host node. if node_id == self.node_id { - let player = handoff.get_reduced_player()?; - let point = player.switch_point(id)?; + let shareholder = handoff.get_reduced_shareholder()?; + let point = shareholder.switch_point(id)?; return handoff.add_full_share_distribution_switch_point(id, point); } @@ -772,15 +774,15 @@ impl Churp { S: Suite + 'static, { let handoff = self.get_handoff::(status.id, status.next_handoff)?; - let player = handoff.get_full_player()?; - let share = player.secret_share(); + let shareholder = handoff.get_full_shareholder()?; + let share = shareholder.secret_share(); // Before overwriting the next secret share, make sure it was copied - // and used to construct the last player. + // and used to construct the last shareholder. let _ = self - .get_player::(status.id, status.handoff) + .get_shareholder::(status.id, status.handoff) .map(Some) - .or_else(|err| ignore_error(err, Error::PlayerNotFound))?; // Ignore if we don't have the correct share. + .or_else(|err| ignore_error(err, Error::ShareholderNotFound))?; // Ignore if we don't have the correct share. // Always persist the secret share before sending confirmation. self.storage @@ -808,8 +810,9 @@ impl Churp { } /// Finalizes the specified scheme by cleaning up obsolete dealers, - /// handoffs, and players. If the handoff was just completed, the player - /// is made available, and its share is persisted to the local storage. + /// handoffs, and shareholders. If the handoff was just completed, + /// the shareholder is made available, and its share is persisted + /// to the local storage. pub fn finalize(&self, req: &HandoffRequest) -> Result<()> { let status = self.verify_last_handoff(req.id, req.runtime_id, req.epoch)?; @@ -822,7 +825,7 @@ impl Churp { where S: Suite + 'static, { - // Move the player if the handoff was completed. + // Move the shareholder if the handoff was completed. let handoff = self.get_handoff::(status.id, status.handoff); let handoff = match handoff { Ok(handoff) => Some(handoff), @@ -832,16 +835,16 @@ impl Churp { }, }; if let Some(handoff) = handoff { - let player = handoff.get_full_player()?; - let share = player.secret_share(); + let shareholder = handoff.get_full_shareholder()?; + let share = shareholder.secret_share(); self.storage .store_secret_share(share, status.id, status.handoff)?; - self.add_player(player, status.id, status.handoff); + self.add_shareholder(shareholder, status.id, status.handoff); } // Cleanup. let max_epoch = status.handoff.saturating_sub(1); - self.remove_player(status.id, max_epoch); + self.remove_shareholder(status.id, max_epoch); let max_epoch = status.next_handoff.saturating_sub(1); self.remove_dealer(status.id, max_epoch); @@ -850,35 +853,35 @@ impl Churp { Ok(()) } - /// Returns the player for the specified scheme and handoff epoch. - fn get_player(&self, churp_id: u8, epoch: EpochTime) -> Result>> + /// Returns the shareholder for the specified scheme and handoff epoch. + fn get_shareholder(&self, churp_id: u8, epoch: EpochTime) -> Result>> where S: Suite + 'static, { - // Check the memory first. Make sure to lock the new players so that we - // don't create two players for the same handoff. - let mut players = self.players.lock().unwrap(); + // Check the memory first. Make sure to lock the new shareholders + // so that we don't create two shareholders for the same handoff. + let mut shareholders = self.shareholders.lock().unwrap(); - if let Some(data) = players.get(&churp_id) { + if let Some(data) = shareholders.get(&churp_id) { match epoch.cmp(&data.epoch) { cmp::Ordering::Less => return Err(Error::InvalidHandoff.into()), cmp::Ordering::Equal => { - // Downcasting should never fail because the consensus ensures that - // the group ID cannot change. - let player = data + // Downcasting should never fail because the consensus + // ensures that the suite ID cannot change. + let shareholder = data .object .clone() - .downcast::>() - .or(Err(Error::PlayerMismatch))?; + .downcast::>() + .or(Err(Error::ShareholderMismatch))?; - return Ok(player); + return Ok(shareholder); } cmp::Ordering::Greater => (), } } - // Fetch player's secret share from the local storage and use it to - // restore the internal state upon restarts, unless a malicious + // Fetch shareholder's secret share from the local storage and use it + // to restore the internal state upon restarts, unless a malicious // host has cleared the storage. let share = self .storage @@ -903,27 +906,27 @@ impl Churp { share } }; - let share = share.ok_or(Error::PlayerNotFound)?; + let share = share.ok_or(Error::ShareholderNotFound)?; - // Create a new player. - let player = Arc::new(Player::from(share)); + // Create a new shareholder. + let shareholder = Arc::new(Shareholder::from(share)); let data = HandoffData { epoch, - object: player.clone(), + object: shareholder.clone(), }; - players.insert(churp_id, data); + shareholders.insert(churp_id, data); - Ok(player) + Ok(shareholder) } - /// Adds a player for the specified scheme and handoff epoch. - fn add_player(&self, player: Arc>, churp_id: u8, epoch: EpochTime) + /// Adds a shareholder for the specified scheme and handoff epoch. + fn add_shareholder(&self, shareholder: Arc>, churp_id: u8, epoch: EpochTime) where S: Suite + 'static, { - let mut players = self.players.lock().unwrap(); + let mut shareholders = self.shareholders.lock().unwrap(); - if let Some(data) = players.get(&churp_id) { + if let Some(data) = shareholders.get(&churp_id) { if epoch <= data.epoch { return; } @@ -931,16 +934,16 @@ impl Churp { let data = HandoffData { epoch, - object: player, + object: shareholder, }; - players.insert(churp_id, data); + shareholders.insert(churp_id, data); } - /// Removes player for the specified scheme if the player belongs + /// Removes shareholder for the specified scheme if the shareholder belongs /// to a handoff that happened at or before the given epoch. - fn remove_player(&self, churp_id: u8, max_epoch: EpochTime) { - let mut players = self.players.lock().unwrap(); - let data = match players.get(&churp_id) { + fn remove_shareholder(&self, churp_id: u8, max_epoch: EpochTime) { + let mut shareholders = self.shareholders.lock().unwrap(); + let data = match shareholders.get(&churp_id) { Some(data) => data, None => return, }; @@ -949,7 +952,7 @@ impl Churp { return; } - players.remove(&churp_id); + shareholders.remove(&churp_id); } /// Returns the dealer for the specified scheme and handoff epoch. @@ -993,8 +996,8 @@ impl Churp { match epoch.cmp(&data.epoch) { cmp::Ordering::Less => return Err(Error::InvalidHandoff.into()), cmp::Ordering::Equal => { - // Downcasting should never fail because the consensus ensures that - // the group ID cannot change. + // Downcasting should never fail because the consensus + // ensures that the suite ID cannot change. let dealer = data .object .clone() @@ -1107,8 +1110,8 @@ impl Churp { match epoch.cmp(&data.epoch) { cmp::Ordering::Less => return Err(Error::InvalidHandoff.into()), cmp::Ordering::Equal => { - // Downcasting should never fail because the consensus ensures that - // the group ID cannot change. + // Downcasting should never fail because the consensus + // ensures that the suite ID cannot change. let handoff = data .object .clone() @@ -1137,8 +1140,8 @@ impl Churp { let handoff = Handoff::new(threshold, me, shareholders, kind)?; if kind == HandoffKind::CommitteeUnchanged { - let player = self.get_player(churp_id, status.handoff)?; - handoff.set_player(player)?; + let shareholder = self.get_shareholder(churp_id, status.handoff)?; + handoff.set_shareholder(shareholder)?; } let handoff = Arc::new(handoff); diff --git a/secret-sharing/src/churp/handoff.rs b/secret-sharing/src/churp/handoff.rs index 5b9f27cafb3..06811951fed 100644 --- a/secret-sharing/src/churp/handoff.rs +++ b/secret-sharing/src/churp/handoff.rs @@ -7,7 +7,7 @@ use crate::{ vss::{matrix::VerificationMatrix, polynomial::Polynomial}, }; -use super::{player::Player, DimensionSwitch, Error, ShareholderId}; +use super::{DimensionSwitch, Error, Shareholder, ShareholderId}; /// Handoff kind. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -24,7 +24,7 @@ pub enum HandoffKind { /// bivariate polynomial, the combined bivariate polynomial `B(x,y)` /// cannot be known by any single party. It's important to note that /// if only threshold + 1 shares have been combined, then the secret - /// could be known by one honest player. + /// could be known by one honest shareholder. /// /// In this phase, dimension switching is not needed, so the handoff /// can be simplified. The share reduction phase is skipped entirely, @@ -180,8 +180,8 @@ where .start_accumulating(vm) } - /// Checks if the handoff needs the player from the previous handoff. - pub fn needs_player(&self) -> Result { + /// Checks if the handoff needs the shareholder from the previous handoff. + pub fn needs_shareholder(&self) -> Result { if self.kind != HandoffKind::CommitteeUnchanged { return Err(Error::InvalidKind.into()); } @@ -190,13 +190,13 @@ where .share_distribution .as_ref() .ok_or(Error::InvalidState)? - .is_waiting_for_player(); + .is_waiting_for_shareholder(); Ok(needs) } - /// Sets the player from the previous handoff. - pub fn set_player(&self, player: Arc>) -> Result<()> { + /// Sets the shareholder from the previous handoff. + pub fn set_shareholder(&self, shareholder: Arc>) -> Result<()> { if self.kind != HandoffKind::CommitteeUnchanged { return Err(Error::InvalidKind.into()); } @@ -204,7 +204,7 @@ where self.share_distribution .as_ref() .ok_or(Error::InvalidState)? - .start_merging(Some(player)) + .start_merging(Some(shareholder)) } /// Checks if share reduction needs a switch point from the given @@ -302,7 +302,7 @@ where .share_reduction .as_ref() .ok_or(Error::InvalidState)? - .get_player()? + .get_shareholder()? .verification_matrix() .clone(); @@ -315,8 +315,8 @@ where res } - /// Returns the player resulting from share reduction. - pub fn get_reduced_player(&self) -> Result>> { + /// Returns the shareholder resulting from share reduction. + pub fn get_reduced_shareholder(&self) -> Result>> { if self.kind != HandoffKind::CommitteeChanged { return Err(Error::InvalidKind.into()); } @@ -324,15 +324,15 @@ where self.share_reduction .as_ref() .ok_or(Error::InvalidState)? - .get_player() + .get_shareholder() } - /// Returns the player resulting from full share distribution. - pub fn get_full_player(&self) -> Result>> { + /// Returns the shareholder resulting from full share distribution. + pub fn get_full_shareholder(&self) -> Result>> { self.share_distribution .as_ref() .ok_or(Error::InvalidState)? - .get_player() + .get_shareholder() } } @@ -352,25 +352,25 @@ mod tests { type Dealer = churp::Dealer; type Handoff = churp::Handoff; - type Player = churp::Player; + type Shareholder = churp::Shareholder; - fn shareholder(id: u8) -> ShareholderId { + fn shareholder_id(id: u8) -> ShareholderId { ShareholderId([id; 32]) } - fn shareholders(ids: Vec) -> Vec { - ids.into_iter().map(shareholder).collect() + fn shareholder_ids(ids: Vec) -> Vec { + ids.into_iter().map(shareholder_id).collect() } - fn verify_players(players: &HashMap>) { - // Verify that all players have the same matrix. + fn verify_shareholders(shareholders: &HashMap>) { + // Verify that all shareholders have the same matrix. let mut vms = HashSet::new(); - for player in players.values() { - let bytes = player.verification_matrix().to_bytes(); + for shareholder in shareholders.values() { + let bytes = shareholder.verification_matrix().to_bytes(); vms.insert(bytes); if vms.len() != 1 { - panic!("players verification failed: inconsistent matrices"); + panic!("shareholders verification failed: inconsistent matrices"); } } } @@ -395,7 +395,7 @@ mod tests { let threshold = 2; // Handoff 0: Dealing phase. - let committee = shareholders(vec![1, 2, 3, 4]); // At least 4 (threshold + 2). + let committee = shareholder_ids(vec![1, 2, 3, 4]); // At least 4 (threshold + 2). let committee: HashSet<_> = committee.iter().cloned().collect(); let kind = HandoffKind::DealingPhase; @@ -427,18 +427,18 @@ mod tests { handoffs.insert(alice.clone(), handoff); } - // Extract and verify players. - let mut players = HashMap::new(); + // Extract and verify shareholders. + let mut shareholders = HashMap::new(); for (alice, handoff) in handoffs.iter() { // Share reduction should be skipped. - assert!(handoff.get_reduced_player().is_err()); + assert!(handoff.get_reduced_shareholder().is_err()); // Full share distribution should be completed. - let player = handoff.get_full_player().unwrap(); - players.insert(alice.clone(), player); + let shareholder = handoff.get_full_shareholder().unwrap(); + shareholders.insert(alice.clone(), shareholder); } - verify_players(&players); + verify_shareholders(&shareholders); // Handoff 1: Committee remains unchanged. let kind = HandoffKind::CommitteeUnchanged; @@ -454,10 +454,10 @@ mod tests { ) .unwrap(); - let player = players.get(&alice).unwrap().clone(); + let shareholder = shareholders.get(&alice).unwrap().clone(); - assert!(handoff.needs_player().unwrap()); - handoff.set_player(player).unwrap(); + assert!(handoff.needs_shareholder().unwrap()); + handoff.set_shareholder(shareholder).unwrap(); // Proactivization. for (i, (bob, dealer)) in dealers.iter().enumerate() { @@ -481,21 +481,21 @@ mod tests { handoffs.insert(alice.clone(), handoff); } - // Extract and verify players. - let mut players = HashMap::new(); + // Extract and verify shareholders. + let mut shareholders = HashMap::new(); for (alice, handoff) in handoffs.iter() { // Share reduction should be skipped. - assert!(handoff.get_reduced_player().is_err()); + assert!(handoff.get_reduced_shareholder().is_err()); // Full share distribution should be completed. - let player = handoff.get_full_player().unwrap(); - players.insert(alice.clone(), player); + let shareholder = handoff.get_full_shareholder().unwrap(); + shareholders.insert(alice.clone(), shareholder); } - verify_players(&players); + verify_shareholders(&shareholders); // Handoff 2: Committee changed. - let committee = shareholders(vec![3, 4, 5, 6, 7]); // At least 5 (2 * threshold + 1). + let committee = shareholder_ids(vec![3, 4, 5, 6, 7]); // At least 5 (2 * threshold + 1). let committee: HashSet<_> = committee.iter().cloned().collect(); let kind = HandoffKind::CommitteeChanged; @@ -513,7 +513,7 @@ mod tests { // Fetch verification matrix from the old committee. assert!(handoff.needs_verification_matrix().unwrap()); - let vm = players + let vm = shareholders .iter() .nth(0) .unwrap() @@ -524,9 +524,9 @@ mod tests { // Share reduction. let num_points = threshold as usize + 1; - for (i, (bob, player)) in players.iter().take(num_points).enumerate() { + for (i, (bob, shareholder)) in shareholders.iter().take(num_points).enumerate() { assert!(handoff.needs_share_reduction_switch_point(bob).unwrap()); - let bij = player.switch_point(alice.clone()).unwrap(); + let bij = shareholder.switch_point(alice.clone()).unwrap(); let done = handoff .add_share_reduction_switch_point(bob.clone(), bij) .unwrap(); @@ -564,29 +564,29 @@ mod tests { handoffs.insert(alice.clone(), handoff); } - // Extract and verify reduced players. - let mut players = HashMap::new(); + // Extract and verify reduced shareholders. + let mut shareholders = HashMap::new(); for (alice, handoff) in handoffs.iter() { // Share reduction should be completed. - let player = handoff.get_reduced_player().unwrap(); - players.insert(alice.clone(), player); + let shareholder = handoff.get_reduced_shareholder().unwrap(); + shareholders.insert(alice.clone(), shareholder); // Full share distribution hasn't started. - assert!(handoff.get_full_player().is_err()); + assert!(handoff.get_full_shareholder().is_err()); } - verify_players(&players); + verify_shareholders(&shareholders); for alice in committee.iter() { let handoff = handoffs.get(alice).unwrap(); // Share distribution. let num_points = 2 * threshold as usize + 1; - for (i, (bob, player)) in players.iter().take(num_points).enumerate() { + for (i, (bob, shareholder)) in shareholders.iter().take(num_points).enumerate() { assert!(handoff .needs_full_share_distribution_switch_point(bob) .unwrap()); - let bij = player.switch_point(alice.clone()).unwrap(); + let bij = shareholder.switch_point(alice.clone()).unwrap(); let done = handoff .add_full_share_distribution_switch_point(bob.clone(), bij) .unwrap(); @@ -607,14 +607,14 @@ mod tests { } } - // Extract and verify full players. - let mut players = HashMap::new(); + // Extract and verify full shareholders. + let mut shareholders = HashMap::new(); for (alice, handoff) in handoffs.iter() { // Full share distribution should be completed. - let player = handoff.get_full_player().unwrap(); - players.insert(alice.clone(), player); + let shareholder = handoff.get_full_shareholder().unwrap(); + shareholders.insert(alice.clone(), shareholder); } - verify_players(&players); + verify_shareholders(&shareholders); } } diff --git a/secret-sharing/src/churp/player.rs b/secret-sharing/src/churp/player.rs index 98dffce4dee..b71491c736f 100644 --- a/secret-sharing/src/churp/player.rs +++ b/secret-sharing/src/churp/player.rs @@ -1,4 +1,4 @@ -//! CHURP player. +//! CHURP shareholder. use anyhow::Result; use group::{Group, GroupEncoding}; @@ -10,19 +10,19 @@ use crate::{ use super::{Error, ShareholderId}; -/// Player is responsible for deriving key shares and generating +/// Shareholder is responsible for deriving key shares and generating /// switch points during handoffs when the committee is trying /// to switch to the other dimension. -pub struct Player { +pub struct Shareholder { /// Secret (full or reduced) share of the shared secret. share: SecretShare, } -impl Player +impl Shareholder where S: Suite, { - /// Creates a new player. + /// Creates a new shareholder. pub fn new(p: Polynomial, vm: VerificationMatrix) -> Self { SecretShare::new(p, vm).into() } @@ -58,12 +58,12 @@ where .unwrap_or(S::Group::identity()) } - /// Creates a new player with a proactivized secret polynomial. + /// Creates a new shareholder with a proactivized secret polynomial. pub fn proactivize( &self, p: &Polynomial, vm: &VerificationMatrix, - ) -> Result> { + ) -> Result> { if p.degree() != self.share.p.degree() { return Err(Error::PolynomialDegreeMismatch.into()); } @@ -76,18 +76,18 @@ where let p = p + &self.share.p; let vm = vm + &self.share.vm; - let player = Player::new(p, vm); + let shareholder = Shareholder::new(p, vm); - Ok(player) + Ok(shareholder) } } -impl From> for Player +impl From> for Shareholder where S: Suite, { - fn from(state: SecretShare) -> Player { - Player { share: state } + fn from(share: SecretShare) -> Shareholder { + Shareholder { share } } } diff --git a/secret-sharing/src/churp/switch.rs b/secret-sharing/src/churp/switch.rs index 44f8de485d2..1e2744acaf5 100644 --- a/secret-sharing/src/churp/switch.rs +++ b/secret-sharing/src/churp/switch.rs @@ -13,7 +13,7 @@ use crate::{ }, }; -use super::{Error, HandoffKind, Player, ShareholderId}; +use super::{Error, HandoffKind, Shareholder, ShareholderId}; /// Dimension switch kind. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -45,21 +45,22 @@ where /// state if proactivization is required, or directly to the Serving state. Accumulating(SwitchPoints), - /// Represents the state where the dimension switch is waiting for a player - /// to be proactivized with bivariate shares. The player can be constructed - /// from received switch points, transferred from a previous handoff, or - /// omitted if we want to construct a new one. - WaitingForPlayer, - - /// Represents the state where the dimension switch is merging bivariate - /// shares. Once enough shares are collected, the player is proactivized, - /// and the state transitions to the Serving state. If no player was - /// given, the combined shares define a new one. + /// Represents the state where the dimension switch is waiting + /// for a shareholder to be proactivized with bivariate shares. + /// The shareholder can be constructed from received switch points, + /// transferred from a previous handoff, or omitted if we want + /// to construct a new one. + WaitingForShareholder, + + /// Represents the state where the dimension switch is merging + /// bivariate shares. Once enough shares are collected, the shareholder + /// is proactivized, and the state transitions to the Serving state. + /// If no shareholder was given, the combined shares define a new one. Merging(BivariateShares), /// Represents the state where the dimension switch is completed, - /// and a new player is available to serve requests. - Serving(Arc>), + /// and a new shareholder is available to serve requests. + Serving(Arc>), } /// A dimension switch based on a share resharing technique. @@ -148,7 +149,7 @@ where _ => return Err(Error::InvalidState.into()), }; - *state = DimensionSwitchState::WaitingForPlayer; + *state = DimensionSwitchState::WaitingForShareholder; Ok(()) } @@ -193,11 +194,11 @@ where let done = sp.add_point(id, bij)?; if done { - let player = sp.reconstruct_player()?; - let player = Arc::new(player); + let shareholder = sp.reconstruct_shareholder()?; + let shareholder = Arc::new(shareholder); if self.shareholders.is_empty() { - *state = DimensionSwitchState::Serving(player); + *state = DimensionSwitchState::Serving(shareholder); } else { let bs = BivariateShares::new( self.threshold, @@ -205,7 +206,7 @@ where self.shareholders.clone(), self.kind, self.handoff, - Some(player), + Some(shareholder), )?; *state = DimensionSwitchState::Merging(bs); } @@ -214,18 +215,18 @@ where Ok(done) } - /// Checks if the switch is waiting for a player. - pub(crate) fn is_waiting_for_player(&self) -> bool { + /// Checks if the switch is waiting for a shareholder. + pub(crate) fn is_waiting_for_shareholder(&self) -> bool { let state = self.state.lock().unwrap(); - matches!(&*state, DimensionSwitchState::WaitingForPlayer) + matches!(&*state, DimensionSwitchState::WaitingForShareholder) } /// Starts merging bivariate shares to be used for proactivization - /// of the provided player. - pub(crate) fn start_merging(&self, player: Option>>) -> Result<()> { + /// of the provided shareholder. + pub(crate) fn start_merging(&self, shareholder: Option>>) -> Result<()> { let mut state = self.state.lock().unwrap(); match &*state { - DimensionSwitchState::WaitingForPlayer => (), + DimensionSwitchState::WaitingForShareholder => (), _ => return Err(Error::InvalidState.into()), }; @@ -235,7 +236,7 @@ where self.shareholders.clone(), self.kind, self.handoff, - player, + shareholder, )?; *state = DimensionSwitchState::Merging(bs); @@ -272,23 +273,23 @@ where let done = shares.add_bivariate_share(id, q, vm)?; if done { - let player = shares.proactivize_player()?; - let player = Arc::new(player); - *state = DimensionSwitchState::Serving(player); + let shareholder = shares.proactivize_shareholder()?; + let shareholder = Arc::new(shareholder); + *state = DimensionSwitchState::Serving(shareholder); } Ok(done) } - /// Returns the player if the switch has completed. - pub(crate) fn get_player(&self) -> Result>> { + /// Returns the shareholder if the switch has completed. + pub(crate) fn get_shareholder(&self) -> Result>> { let state = self.state.lock().unwrap(); - let player = match &*state { + let shareholder = match &*state { DimensionSwitchState::Serving(p) => p.clone(), _ => return Err(Error::InvalidState.into()), }; - Ok(player) + Ok(shareholder) } } @@ -364,7 +365,7 @@ where }; // Wrap the matrix in an option so that we can take it when creating - // a player. + // a shareholder. let vm = Some(vm); // We need at least n points to reconstruct the polynomial share. @@ -420,11 +421,11 @@ where Ok(done) } - /// Reconstructs the player from the received switch points. + /// Reconstructs the shareholder from the received switch points. /// - /// The player can be reconstructed only once, which avoids copying + /// The shareholder can be reconstructed only once, which avoids copying /// the verification matrix. - fn reconstruct_player(&mut self) -> Result> { + fn reconstruct_shareholder(&mut self) -> Result> { if self.shareholders.len() < self.n { return Err(Error::NotEnoughSwitchPoints.into()); } @@ -438,9 +439,9 @@ where } let vm = self.vm.take().ok_or(Error::VerificationMatrixRequired)?; - let player = Player::new(p, vm); + let shareholder = Shareholder::new(p, vm); - Ok(player) + Ok(shareholder) } } @@ -479,8 +480,8 @@ where /// The sum of the verification matrices of the received bivariate shares. vm: Option>, - /// The player to be proactivized with bivariate shares. - player: Option>>, + /// The shareholder to be proactivized with bivariate shares. + shareholder: Option>>, } impl BivariateShares @@ -494,11 +495,11 @@ where shareholders: HashSet, kind: DimensionSwitchKind, handoff: HandoffKind, - player: Option>>, + shareholder: Option>>, ) -> Result { // During the dealing phase, the number of shares must be at least // threshold + 2, ensuring that even if t Byzantine dealers reveal - // their secret, an honest player cannot compute the combined + // their secret, an honest shareholder cannot compute the combined // bivariate polynomial. let min = match handoff { HandoffKind::DealingPhase => threshold as usize + 2, @@ -525,7 +526,7 @@ where pending_shareholders, p: None, vm: None, - player, + shareholder, }) } @@ -595,9 +596,9 @@ where Ok(done) } - /// Proactivizes the player with the combined polynomial and verification - /// matrix. - fn proactivize_player(&mut self) -> Result> { + /// Proactivizes the shareholder with the combined polynomial + /// and verification matrix. + fn proactivize_shareholder(&mut self) -> Result> { if !self.pending_shareholders.is_empty() { return Err(Error::NotEnoughBivariateShares.into()); } @@ -607,12 +608,12 @@ where let p = self.p.take().unwrap(); let vm = self.vm.take().unwrap(); - let player = match &self.player { - Some(player) => player.proactivize(&p, &vm)?, - None => Player::new(p, vm), + let shareholder = match &self.shareholder { + Some(shareholder) => shareholder.proactivize(&p, &vm)?, + None => Shareholder::new(p, vm), }; - Ok(player) + Ok(shareholder) } } @@ -709,7 +710,7 @@ mod tests { sh += 1; // Try to reconstruct the polynomial. - let res = sp.reconstruct_player(); + let res = sp.reconstruct_shareholder(); assert!(res.is_err()); unsafe { assert_eq!( @@ -746,7 +747,7 @@ mod tests { ); // Try to reconstruct the polynomial again. - let res = sp.reconstruct_player(); + let res = sp.reconstruct_shareholder(); assert!(res.is_ok()); } } @@ -852,7 +853,7 @@ mod tests { sh += 1; // Try to collect the polynomial and verification matrix. - let res = bs.proactivize_player(); + let res = bs.proactivize_shareholder(); assert!(res.is_err()); unsafe { assert_eq!( @@ -878,7 +879,7 @@ mod tests { ); // Try to collect the polynomial and verification matrix again. - let res = bs.proactivize_player(); + let res = bs.proactivize_shareholder(); assert!(res.is_ok()); } } From 3ede60ddfd2c14970c66c2621f924b559746cee5 Mon Sep 17 00:00:00 2001 From: Peter Nose Date: Tue, 7 May 2024 13:02:01 +0200 Subject: [PATCH 2/2] secret-sharing/src/churp: Merge shareholder code --- .changelog/5689.trivial.md | 0 secret-sharing/src/churp/mod.rs | 3 +- secret-sharing/src/churp/player.rs | 124 ------------------------ secret-sharing/src/churp/shareholder.rs | 120 ++++++++++++++++++++++- 4 files changed, 120 insertions(+), 127 deletions(-) create mode 100644 .changelog/5689.trivial.md delete mode 100644 secret-sharing/src/churp/player.rs diff --git a/.changelog/5689.trivial.md b/.changelog/5689.trivial.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/secret-sharing/src/churp/mod.rs b/secret-sharing/src/churp/mod.rs index 92acc81129f..edda40e346f 100644 --- a/secret-sharing/src/churp/mod.rs +++ b/secret-sharing/src/churp/mod.rs @@ -3,9 +3,8 @@ mod dealer; mod errors; mod handoff; -mod player; mod shareholder; mod switch; // Re-exports. -pub use self::{dealer::*, errors::*, handoff::*, player::*, shareholder::*, switch::*}; +pub use self::{dealer::*, errors::*, handoff::*, shareholder::*, switch::*}; diff --git a/secret-sharing/src/churp/player.rs b/secret-sharing/src/churp/player.rs deleted file mode 100644 index b71491c736f..00000000000 --- a/secret-sharing/src/churp/player.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! CHURP shareholder. - -use anyhow::Result; -use group::{Group, GroupEncoding}; - -use crate::{ - suites::Suite, - vss::{matrix::VerificationMatrix, polynomial::Polynomial}, -}; - -use super::{Error, ShareholderId}; - -/// Shareholder is responsible for deriving key shares and generating -/// switch points during handoffs when the committee is trying -/// to switch to the other dimension. -pub struct Shareholder { - /// Secret (full or reduced) share of the shared secret. - share: SecretShare, -} - -impl Shareholder -where - S: Suite, -{ - /// Creates a new shareholder. - pub fn new(p: Polynomial, vm: VerificationMatrix) -> Self { - SecretShare::new(p, vm).into() - } - - /// Returns the secret share. - pub fn secret_share(&self) -> &SecretShare { - &self.share - } - - /// Returns the polynomial. - pub fn polynomial(&self) -> &Polynomial { - &self.share.p - } - - /// Returns the verification matrix. - pub fn verification_matrix(&self) -> &VerificationMatrix { - &self.share.vm - } - - /// Computes switch point for the given shareholder. - pub fn switch_point(&self, id: ShareholderId) -> Result { - let x = id.encode::()?; - let point = self.share.p.eval(&x); - Ok(point) - } - - /// Computes key share from the given hash. - pub fn key_share(&self, hash: S::Group) -> S::Group { - self.share - .p - .coefficient(0) - .map(|s| hash * s) - .unwrap_or(S::Group::identity()) - } - - /// Creates a new shareholder with a proactivized secret polynomial. - pub fn proactivize( - &self, - p: &Polynomial, - vm: &VerificationMatrix, - ) -> Result> { - if p.degree() != self.share.p.degree() { - return Err(Error::PolynomialDegreeMismatch.into()); - } - if !vm.is_zero_hole() { - return Err(Error::VerificationMatrixZeroHoleMismatch.into()); - } - if vm.dimensions() != self.share.vm.dimensions() { - return Err(Error::VerificationMatrixDimensionMismatch.into()); - } - - let p = p + &self.share.p; - let vm = vm + &self.share.vm; - let shareholder = Shareholder::new(p, vm); - - Ok(shareholder) - } -} - -impl From> for Shareholder -where - S: Suite, -{ - fn from(share: SecretShare) -> Shareholder { - Shareholder { share } - } -} - -/// Secret share of the shared secret. -pub struct SecretShare -where - G: Group + GroupEncoding, -{ - /// Secret polynomial. - p: Polynomial, - - /// Verification matrix. - vm: VerificationMatrix, -} - -impl SecretShare -where - G: Group + GroupEncoding, -{ - /// Creates a new secret share. - pub fn new(p: Polynomial, vm: VerificationMatrix) -> Self { - Self { p, vm } - } - - /// Returns the polynomial. - pub fn polynomial(&self) -> &Polynomial { - &self.p - } - - /// Returns the verification matrix. - pub fn verification_matrix(&self) -> &VerificationMatrix { - &self.vm - } -} diff --git a/secret-sharing/src/churp/shareholder.rs b/secret-sharing/src/churp/shareholder.rs index 39bb4c2ac6e..67d6ad18a09 100644 --- a/secret-sharing/src/churp/shareholder.rs +++ b/secret-sharing/src/churp/shareholder.rs @@ -1,7 +1,12 @@ //! CHURP shareholder. use anyhow::Result; -use group::ff::Field; +use group::{ff::Field, Group, GroupEncoding}; + +use crate::{ + suites::Suite, + vss::{matrix::VerificationMatrix, polynomial::Polynomial}, +}; use crate::suites::FieldDigest; @@ -27,3 +32,116 @@ impl ShareholderId { Ok(s) } } + +/// Shareholder is responsible for deriving key shares and generating +/// switch points during handoffs when the committee is trying +/// to switch to the other dimension. +pub struct Shareholder { + /// Secret (full or reduced) share of the shared secret. + share: SecretShare, +} + +impl Shareholder +where + S: Suite, +{ + /// Creates a new shareholder. + pub fn new(p: Polynomial, vm: VerificationMatrix) -> Self { + SecretShare::new(p, vm).into() + } + + /// Returns the secret share. + pub fn secret_share(&self) -> &SecretShare { + &self.share + } + + /// Returns the polynomial. + pub fn polynomial(&self) -> &Polynomial { + &self.share.p + } + + /// Returns the verification matrix. + pub fn verification_matrix(&self) -> &VerificationMatrix { + &self.share.vm + } + + /// Computes switch point for the given shareholder. + pub fn switch_point(&self, id: ShareholderId) -> Result { + let x = id.encode::()?; + let point = self.share.p.eval(&x); + Ok(point) + } + + /// Computes key share from the given hash. + pub fn key_share(&self, hash: S::Group) -> S::Group { + self.share + .p + .coefficient(0) + .map(|s| hash * s) + .unwrap_or(S::Group::identity()) + } + + /// Creates a new shareholder with a proactivized secret polynomial. + pub fn proactivize( + &self, + p: &Polynomial, + vm: &VerificationMatrix, + ) -> Result> { + if p.degree() != self.share.p.degree() { + return Err(Error::PolynomialDegreeMismatch.into()); + } + if !vm.is_zero_hole() { + return Err(Error::VerificationMatrixZeroHoleMismatch.into()); + } + if vm.dimensions() != self.share.vm.dimensions() { + return Err(Error::VerificationMatrixDimensionMismatch.into()); + } + + let p = p + &self.share.p; + let vm = vm + &self.share.vm; + let shareholder = Shareholder::new(p, vm); + + Ok(shareholder) + } +} + +impl From> for Shareholder +where + S: Suite, +{ + fn from(share: SecretShare) -> Shareholder { + Shareholder { share } + } +} + +/// Secret share of the shared secret. +pub struct SecretShare +where + G: Group + GroupEncoding, +{ + /// Secret polynomial. + p: Polynomial, + + /// Verification matrix. + vm: VerificationMatrix, +} + +impl SecretShare +where + G: Group + GroupEncoding, +{ + /// Creates a new secret share. + pub fn new(p: Polynomial, vm: VerificationMatrix) -> Self { + Self { p, vm } + } + + /// Returns the polynomial. + pub fn polynomial(&self) -> &Polynomial { + &self.p + } + + /// Returns the verification matrix. + pub fn verification_matrix(&self) -> &VerificationMatrix { + &self.vm + } +}