From 2a5f9f1bfea57ff8d0efc4fa67130b1d10f058c1 Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Mon, 25 Jun 2018 21:09:45 +0200 Subject: [PATCH 1/4] Allow observer nodes in all algorithms. This allows nodes to join the network without sending any messages themselves. They can't give any input and just observe the outcome. Closes #81 --- src/agreement/mod.rs | 24 ++++++++++++------ src/broadcast.rs | 27 +++++++++++++-------- src/common_coin.rs | 27 +++++++++++++-------- src/common_subset.rs | 3 +++ src/honey_badger.rs | 55 +++++++++++++++++++++++++++--------------- src/messaging.rs | 9 ++++--- tests/agreement.rs | 1 + tests/broadcast.rs | 1 + tests/common_coin.rs | 16 +++++------- tests/common_subset.rs | 1 + tests/network/mod.rs | 20 ++++++++++----- 11 files changed, 118 insertions(+), 66 deletions(-) diff --git a/src/agreement/mod.rs b/src/agreement/mod.rs index dc2e103..6a3245c 100644 --- a/src/agreement/mod.rs +++ b/src/agreement/mod.rs @@ -227,12 +227,14 @@ impl Agreement { self.decision = Some(input); self.output = Some(input); self.terminated = true; + self.send_bval(input)?; + self.send_aux(input) + } else { + // Set the initial estimated value to the input value. + self.estimated = Some(input); + // Record the input value as sent. + self.send_bval(input) } - - // Set the initial estimated value to the input value. - self.estimated = Some(input); - // Record the input value as sent. - self.send_bval(input) } /// Acceptance check to be performed before setting the input value. @@ -305,6 +307,9 @@ impl Agreement { } fn send_bval(&mut self, b: bool) -> AgreementResult<()> { + if !self.netinfo.is_full_node() { + return Ok(()); + } // Record the value `b` as sent. self.sent_bval.insert(b); // Multicast `BVal`. @@ -321,12 +326,17 @@ impl Agreement { return Ok(()); } + // Trigger the start of the `Conf` round. + self.conf_round = true; + + if !self.netinfo.is_full_node() { + return Ok(()); + } + let v = self.bin_values; // Multicast `Conf`. self.messages .push_back(AgreementContent::Conf(v).with_epoch(self.epoch)); - // Trigger the start of the `Conf` round. - self.conf_round = true; // Receive the `Conf` message locally. let our_uid = &self.netinfo.our_uid().clone(); self.handle_conf(our_uid, v) diff --git a/src/broadcast.rs b/src/broadcast.rs index 8e477bc..60d244a 100644 --- a/src/broadcast.rs +++ b/src/broadcast.rs @@ -293,10 +293,12 @@ impl Broadcast { // Otherwise multicast the proof in an `Echo` message, and handle it ourselves. self.echo_sent = true; - let our_uid = &self.netinfo.our_uid().clone(); - self.handle_echo(our_uid, p.clone())?; - let echo_msg = Target::All.message(BroadcastMessage::Echo(p)); - self.messages.push_back(echo_msg); + if self.netinfo.is_full_node() { + let our_uid = &self.netinfo.our_uid().clone(); + self.handle_echo(our_uid, p.clone())?; + let echo_msg = Target::All.message(BroadcastMessage::Echo(p)); + self.messages.push_back(echo_msg); + } Ok(()) } @@ -328,10 +330,13 @@ impl Broadcast { // Upon receiving `N - f` `Echo`s with this root hash, multicast `Ready`. self.ready_sent = true; - let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.clone())); - self.messages.push_back(ready_msg); - let our_uid = &self.netinfo.our_uid().clone(); - self.handle_ready(our_uid, &hash) + if self.netinfo.is_full_node() { + let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.clone())); + self.messages.push_back(ready_msg); + let our_uid = &self.netinfo.our_uid().clone(); + self.handle_ready(our_uid, &hash)?; + } + Ok(()) } /// Handles a received `Ready` message. @@ -353,8 +358,10 @@ impl Broadcast { if self.count_readys(hash) == self.netinfo.num_faulty() + 1 && !self.ready_sent { // Enqueue a broadcast of a Ready message. self.ready_sent = true; - let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.to_vec())); - self.messages.push_back(ready_msg); + if self.netinfo.is_full_node() { + let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.to_vec())); + self.messages.push_back(ready_msg); + } } self.compute_output(&hash) } diff --git a/src/common_coin.rs b/src/common_coin.rs index b1fc4de..093ac4d 100644 --- a/src/common_coin.rs +++ b/src/common_coin.rs @@ -126,6 +126,9 @@ where } fn get_coin(&mut self) -> Result<()> { + if !self.netinfo.is_full_node() { + return self.try_output(); + } let share = self.netinfo.secret_key().sign(&self.nonce); self.messages.push_back(CommonCoinMessage(share.clone())); let id = self.netinfo.our_uid().clone(); @@ -140,18 +143,22 @@ where return Ok(()); } self.received_shares.insert(sender_id.clone(), share); - let received_shares = &self.received_shares; - if self.had_input && received_shares.len() > self.netinfo.num_faulty() { - let sig = self.combine_and_verify_sig()?; - // Output the parity of the verified signature. - let parity = sig.parity(); - self.output = Some(parity); - self.terminated = true; - } - Ok(()) } else { - Err(ErrorKind::UnknownSender.into()) + return Err(ErrorKind::UnknownSender.into()); } + self.try_output() + } + + fn try_output(&mut self) -> Result<()> { + let received_shares = &self.received_shares; + if self.had_input && received_shares.len() > self.netinfo.num_faulty() { + let sig = self.combine_and_verify_sig()?; + // Output the parity of the verified signature. + let parity = sig.parity(); + self.output = Some(parity); + self.terminated = true; + } + Ok(()) } fn combine_and_verify_sig(&self) -> Result { diff --git a/src/common_subset.rs b/src/common_subset.rs index 9859cf4..3333681 100644 --- a/src/common_subset.rs +++ b/src/common_subset.rs @@ -180,6 +180,9 @@ impl CommonSubset { /// Common Subset input message handler. It receives a value for broadcast /// and redirects it to the corresponding broadcast instance. pub fn send_proposed_value(&mut self, value: ProposedValue) -> CommonSubsetResult<()> { + if !self.netinfo.is_full_node() { + return Ok(()); + } let uid = self.netinfo.our_uid().clone(); // Upon receiving input v_i , input v_i to RBC_i. See Figure 2. self.process_broadcast(&uid, |bc| bc.input(value)) diff --git a/src/honey_badger.rs b/src/honey_badger.rs index ab2fa3c..7a537e6 100644 --- a/src/honey_badger.rs +++ b/src/honey_badger.rs @@ -28,6 +28,7 @@ error_chain!{ errors { UnknownSender + ObserverCannotPropose } } @@ -151,8 +152,12 @@ where &mut self, txs: I, ) -> HoneyBadgerResult<()> { - self.buffer.extend(txs); - Ok(()) + if self.netinfo.is_full_node() { + self.buffer.extend(txs); + Ok(()) + } else { + Err(ErrorKind::ObserverCannotPropose.into()) + } } /// Empties and returns the transaction buffer. @@ -162,6 +167,9 @@ where /// Proposes a new batch in the current epoch. fn propose(&mut self) -> HoneyBadgerResult<()> { + if !self.netinfo.is_full_node() { + return Ok(()); + } let proposal = self.choose_transactions()?; let cs = match self.common_subsets.entry(self.epoch) { Entry::Occupied(entry) => entry.into_mut(), @@ -420,24 +428,31 @@ where self.verify_pending_decryption_shares(&proposer_id, &ciphertext); self.remove_incorrect_decryption_shares(&proposer_id, incorrect_senders); - if let Some(share) = self.netinfo.secret_key().decrypt_share(&ciphertext) { - // Send the share to remote nodes. - self.messages.0.push_back( - Target::All.message( - MessageContent::DecryptionShare { - proposer_id: proposer_id.clone(), - share: share.clone(), - }.with_epoch(self.epoch), - ), - ); - let our_id = self.netinfo.our_uid().clone(); - let epoch = self.epoch; - // Receive the share locally. - self.handle_decryption_share_message(&our_id, epoch, proposer_id.clone(), share)?; - } else { - warn!("Share decryption failed for proposer {:?}", proposer_id); - // TODO: Log the decryption failure. - continue; + if self.netinfo.is_full_node() { + if let Some(share) = self.netinfo.secret_key().decrypt_share(&ciphertext) { + // Send the share to remote nodes. + self.messages.0.push_back( + Target::All.message( + MessageContent::DecryptionShare { + proposer_id: proposer_id.clone(), + share: share.clone(), + }.with_epoch(self.epoch), + ), + ); + let our_id = self.netinfo.our_uid().clone(); + let epoch = self.epoch; + // Receive the share locally. + self.handle_decryption_share_message( + &our_id, + epoch, + proposer_id.clone(), + share, + )?; + } else { + warn!("Share decryption failed for proposer {:?}", proposer_id); + // TODO: Log the decryption failure. + continue; + } } let ciphertexts = self .ciphertexts diff --git a/src/messaging.rs b/src/messaging.rs index f243725..3c9536a 100644 --- a/src/messaging.rs +++ b/src/messaging.rs @@ -154,9 +154,6 @@ impl NetworkInfo { secret_key: ClearOnDrop>, public_key_set: PublicKeySet, ) -> Self { - if !all_uids.contains(&our_uid) { - panic!("Missing own ID"); - } let num_nodes = all_uids.len(); let node_indices = all_uids .iter() @@ -218,4 +215,10 @@ impl NetworkInfo { pub fn invocation_id(&self) -> Vec { self.public_key_set.public_key().to_bytes() } + + /// Returns `true` if this node takes part in the consensus itself. If not, it is only an + /// observer. + pub fn is_full_node(&self) -> bool { + self.all_uids.contains(&self.our_uid) + } } diff --git a/tests/agreement.rs b/tests/agreement.rs index f0df5cf..d68cd2f 100644 --- a/tests/agreement.rs +++ b/tests/agreement.rs @@ -57,6 +57,7 @@ fn test_agreement>>( expected = Some(node.outputs()[0]); } } + assert!(expected.iter().eq(network.observer.outputs())); } fn test_agreement_different_sizes(new_adversary: F) diff --git a/tests/broadcast.rs b/tests/broadcast.rs index 8931b89..393f321 100644 --- a/tests/broadcast.rs +++ b/tests/broadcast.rs @@ -107,6 +107,7 @@ fn test_broadcast>>( for node in network.nodes.values() { assert!(once(&proposed_value.to_vec()).eq(node.outputs())); } + assert!(once(&proposed_value.to_vec()).eq(network.observer.outputs())); } fn new_broadcast(netinfo: Rc>) -> Broadcast { diff --git a/tests/common_coin.rs b/tests/common_coin.rs index fa7eb37..7b0e9d3 100644 --- a/tests/common_coin.rs +++ b/tests/common_coin.rs @@ -21,23 +21,18 @@ use network::{Adversary, MessageScheduler, NodeUid, SilentAdversary, TestNetwork /// Tests a network of Common Coin instances with an optional expected value. Outputs the computed /// common coin value if the test is successful. -fn test_common_coin( - mut network: TestNetwork>, - expected_coin: Option, -) -> bool +fn test_common_coin(mut network: TestNetwork>) -> bool where A: Adversary>, { - let ids: Vec = network.nodes.keys().cloned().collect(); - for id in ids { - network.input(id, ()); - } + network.input_all(()); + network.observer.input(()); // Observer will only return after `input` was called. // Handle messages until all good nodes have terminated. while !network.nodes.values().all(TestNode::terminated) { network.step(); } - let mut expected = expected_coin; + let mut expected = None; // Verify that all instances output the same value. for node in network.nodes.values() { if let Some(b) = expected { @@ -48,6 +43,7 @@ where } } // Now `expected` is the unique output of all good nodes. + assert!(expected.iter().eq(network.observer.outputs())); expected.unwrap() } @@ -109,7 +105,7 @@ where let new_common_coin = |netinfo: _| CommonCoin::new(netinfo, nonce.clone()); let network = TestNetwork::new(num_good_nodes, num_faulty_nodes, adversary, new_common_coin); - let coin = test_common_coin(network, None); + let coin = test_common_coin(network); if coin { count_true += 1; } else { diff --git a/tests/common_subset.rs b/tests/common_subset.rs index 9c2e040..52d992a 100644 --- a/tests/common_subset.rs +++ b/tests/common_subset.rs @@ -49,6 +49,7 @@ fn test_common_subset>>( expected = Some(node.outputs()[0].clone()); } let output = expected.unwrap(); + assert!(once(&output).eq(network.observer.outputs())); // The Common Subset algorithm guarantees that more than two thirds of the proposed elements // are in the set. assert!(output.len() * 3 > inputs.len() * 2); diff --git a/tests/network/mod.rs b/tests/network/mod.rs index 32f7639..cade247 100644 --- a/tests/network/mod.rs +++ b/tests/network/mod.rs @@ -36,6 +36,12 @@ impl TestNode { self.algo.terminated() } + /// Inputs a value into the instance. + pub fn input(&mut self, input: D::Input) { + self.algo.input(input).expect("input"); + self.outputs.extend(self.algo.output_iter()); + } + /// Creates a new test node with the given broadcast instance. fn new(mut algo: D) -> TestNode { let outputs = algo.output_iter().collect(); @@ -56,12 +62,6 @@ impl TestNode { .expect("handling message"); self.outputs.extend(self.algo.output_iter()); } - - /// Inputs a value into the instance. - fn input(&mut self, input: D::Input) { - self.algo.input(input).expect("input"); - self.outputs.extend(self.algo.output_iter()); - } } /// A strategy for picking the next good node to handle a message. @@ -148,6 +148,7 @@ where ::NodeUid: Hash, { pub nodes: BTreeMap>, + pub observer: TestNode, pub adv_nodes: BTreeMap>>, adversary: A, } @@ -202,6 +203,7 @@ where .collect(); let mut network = TestNetwork { nodes: (0..good_num).map(NodeUid).map(new_node_by_id).collect(), + observer: new_node_by_id(NodeUid(good_num + adv_num)).1, adversary: adversary(adv_nodes.clone()), adv_nodes, }; @@ -232,6 +234,9 @@ where node.queue.push_back((sender_id, msg.message.clone())) } } + self.observer + .queue + .push_back((sender_id, msg.message.clone())); self.adversary.push_message(sender_id, msg); } Target::Node(to_id) => { @@ -247,6 +252,9 @@ where } } } + while !self.observer.queue.is_empty() { + self.observer.handle_message(); + } } /// Handles a queued message in a randomly selected node and returns the selected node's ID. From 2db67df3253d52f5c3f00ab1d3d212884e3b3b71 Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Tue, 26 Jun 2018 10:57:44 +0200 Subject: [PATCH 2/4] Rename is_full_node to is_peer. --- src/agreement/mod.rs | 4 ++-- src/broadcast.rs | 6 +++--- src/common_coin.rs | 2 +- src/common_subset.rs | 2 +- src/honey_badger.rs | 6 +++--- src/messaging.rs | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/agreement/mod.rs b/src/agreement/mod.rs index 6a3245c..270d57f 100644 --- a/src/agreement/mod.rs +++ b/src/agreement/mod.rs @@ -307,7 +307,7 @@ impl Agreement { } fn send_bval(&mut self, b: bool) -> AgreementResult<()> { - if !self.netinfo.is_full_node() { + if !self.netinfo.is_peer() { return Ok(()); } // Record the value `b` as sent. @@ -329,7 +329,7 @@ impl Agreement { // Trigger the start of the `Conf` round. self.conf_round = true; - if !self.netinfo.is_full_node() { + if !self.netinfo.is_peer() { return Ok(()); } diff --git a/src/broadcast.rs b/src/broadcast.rs index 60d244a..6ee5163 100644 --- a/src/broadcast.rs +++ b/src/broadcast.rs @@ -293,7 +293,7 @@ impl Broadcast { // Otherwise multicast the proof in an `Echo` message, and handle it ourselves. self.echo_sent = true; - if self.netinfo.is_full_node() { + if self.netinfo.is_peer() { let our_uid = &self.netinfo.our_uid().clone(); self.handle_echo(our_uid, p.clone())?; let echo_msg = Target::All.message(BroadcastMessage::Echo(p)); @@ -330,7 +330,7 @@ impl Broadcast { // Upon receiving `N - f` `Echo`s with this root hash, multicast `Ready`. self.ready_sent = true; - if self.netinfo.is_full_node() { + if self.netinfo.is_peer() { let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.clone())); self.messages.push_back(ready_msg); let our_uid = &self.netinfo.our_uid().clone(); @@ -358,7 +358,7 @@ impl Broadcast { if self.count_readys(hash) == self.netinfo.num_faulty() + 1 && !self.ready_sent { // Enqueue a broadcast of a Ready message. self.ready_sent = true; - if self.netinfo.is_full_node() { + if self.netinfo.is_peer() { let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.to_vec())); self.messages.push_back(ready_msg); } diff --git a/src/common_coin.rs b/src/common_coin.rs index 093ac4d..efcc383 100644 --- a/src/common_coin.rs +++ b/src/common_coin.rs @@ -126,7 +126,7 @@ where } fn get_coin(&mut self) -> Result<()> { - if !self.netinfo.is_full_node() { + if !self.netinfo.is_peer() { return self.try_output(); } let share = self.netinfo.secret_key().sign(&self.nonce); diff --git a/src/common_subset.rs b/src/common_subset.rs index 3333681..1fad9c6 100644 --- a/src/common_subset.rs +++ b/src/common_subset.rs @@ -180,7 +180,7 @@ impl CommonSubset { /// Common Subset input message handler. It receives a value for broadcast /// and redirects it to the corresponding broadcast instance. pub fn send_proposed_value(&mut self, value: ProposedValue) -> CommonSubsetResult<()> { - if !self.netinfo.is_full_node() { + if !self.netinfo.is_peer() { return Ok(()); } let uid = self.netinfo.our_uid().clone(); diff --git a/src/honey_badger.rs b/src/honey_badger.rs index 7a537e6..49b8ccb 100644 --- a/src/honey_badger.rs +++ b/src/honey_badger.rs @@ -152,7 +152,7 @@ where &mut self, txs: I, ) -> HoneyBadgerResult<()> { - if self.netinfo.is_full_node() { + if self.netinfo.is_peer() { self.buffer.extend(txs); Ok(()) } else { @@ -167,7 +167,7 @@ where /// Proposes a new batch in the current epoch. fn propose(&mut self) -> HoneyBadgerResult<()> { - if !self.netinfo.is_full_node() { + if !self.netinfo.is_peer() { return Ok(()); } let proposal = self.choose_transactions()?; @@ -428,7 +428,7 @@ where self.verify_pending_decryption_shares(&proposer_id, &ciphertext); self.remove_incorrect_decryption_shares(&proposer_id, incorrect_senders); - if self.netinfo.is_full_node() { + if self.netinfo.is_peer() { if let Some(share) = self.netinfo.secret_key().decrypt_share(&ciphertext) { // Send the share to remote nodes. self.messages.0.push_back( diff --git a/src/messaging.rs b/src/messaging.rs index 3c9536a..99c5503 100644 --- a/src/messaging.rs +++ b/src/messaging.rs @@ -218,7 +218,7 @@ impl NetworkInfo { /// Returns `true` if this node takes part in the consensus itself. If not, it is only an /// observer. - pub fn is_full_node(&self) -> bool { + pub fn is_peer(&self) -> bool { self.all_uids.contains(&self.our_uid) } } From aaec3d4074417f5cbd014e3ac251ee43b9c83f6c Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Tue, 26 Jun 2018 14:50:06 +0200 Subject: [PATCH 3/4] Simplify observer/peer-specific code. Extract some methods to make the branches more readable. --- src/broadcast.rs | 50 ++++++++++++++++++++++------------------ src/honey_badger.rs | 56 +++++++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/broadcast.rs b/src/broadcast.rs index 6ee5163..0e31e50 100644 --- a/src/broadcast.rs +++ b/src/broadcast.rs @@ -292,14 +292,7 @@ impl Broadcast { } // Otherwise multicast the proof in an `Echo` message, and handle it ourselves. - self.echo_sent = true; - if self.netinfo.is_peer() { - let our_uid = &self.netinfo.our_uid().clone(); - self.handle_echo(our_uid, p.clone())?; - let echo_msg = Target::All.message(BroadcastMessage::Echo(p)); - self.messages.push_back(echo_msg); - } - Ok(()) + self.send_echo(p) } /// Handles a received `Echo` message. @@ -329,14 +322,7 @@ impl Broadcast { } // Upon receiving `N - f` `Echo`s with this root hash, multicast `Ready`. - self.ready_sent = true; - if self.netinfo.is_peer() { - let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.clone())); - self.messages.push_back(ready_msg); - let our_uid = &self.netinfo.our_uid().clone(); - self.handle_ready(our_uid, &hash)?; - } - Ok(()) + self.send_ready(&hash) } /// Handles a received `Ready` message. @@ -357,13 +343,33 @@ impl Broadcast { // has not yet been sent, multicast Ready(h). if self.count_readys(hash) == self.netinfo.num_faulty() + 1 && !self.ready_sent { // Enqueue a broadcast of a Ready message. - self.ready_sent = true; - if self.netinfo.is_peer() { - let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.to_vec())); - self.messages.push_back(ready_msg); - } + self.send_ready(hash)?; } - self.compute_output(&hash) + self.compute_output(hash) + } + + /// Sends an `Echo` message and handles it. Does nothing if we are only an observer. + fn send_echo(&mut self, p: Proof>) -> BroadcastResult<()> { + self.echo_sent = true; + if !self.netinfo.is_peer() { + return Ok(()); + } + let echo_msg = Target::All.message(BroadcastMessage::Echo(p.clone())); + self.messages.push_back(echo_msg); + let our_uid = &self.netinfo.our_uid().clone(); + self.handle_echo(our_uid, p) + } + + /// Sends a `Ready` message and handles it. Does nothing if we are only an observer. + fn send_ready(&mut self, hash: &[u8]) -> BroadcastResult<()> { + self.ready_sent = true; + if !self.netinfo.is_peer() { + return Ok(()); + } + let ready_msg = Target::All.message(BroadcastMessage::Ready(hash.to_vec())); + self.messages.push_back(ready_msg); + let our_uid = &self.netinfo.our_uid().clone(); + self.handle_ready(our_uid, hash) } /// Checks whether the condition for output are met for this hash, and if so, sets the output diff --git a/src/honey_badger.rs b/src/honey_badger.rs index 49b8ccb..ebc8345 100644 --- a/src/honey_badger.rs +++ b/src/honey_badger.rs @@ -428,31 +428,10 @@ where self.verify_pending_decryption_shares(&proposer_id, &ciphertext); self.remove_incorrect_decryption_shares(&proposer_id, incorrect_senders); - if self.netinfo.is_peer() { - if let Some(share) = self.netinfo.secret_key().decrypt_share(&ciphertext) { - // Send the share to remote nodes. - self.messages.0.push_back( - Target::All.message( - MessageContent::DecryptionShare { - proposer_id: proposer_id.clone(), - share: share.clone(), - }.with_epoch(self.epoch), - ), - ); - let our_id = self.netinfo.our_uid().clone(); - let epoch = self.epoch; - // Receive the share locally. - self.handle_decryption_share_message( - &our_id, - epoch, - proposer_id.clone(), - share, - )?; - } else { - warn!("Share decryption failed for proposer {:?}", proposer_id); - // TODO: Log the decryption failure. - continue; - } + if !self.send_decryption_share(&proposer_id, &ciphertext)? { + warn!("Share decryption failed for proposer {:?}", proposer_id); + // TODO: Log the decryption failure. + continue; } let ciphertexts = self .ciphertexts @@ -463,6 +442,33 @@ where Ok(()) } + /// Verifies the ciphertext and sends decryption shares. Returns whether it is valid. + fn send_decryption_share( + &mut self, + proposer_id: &NodeUid, + ciphertext: &Ciphertext, + ) -> HoneyBadgerResult { + if !self.netinfo.is_peer() { + return Ok(ciphertext.verify()); + } + let share = match self.netinfo.secret_key().decrypt_share(&ciphertext) { + None => return Ok(false), + Some(share) => share, + }; + // Send the share to remote nodes. + let content = MessageContent::DecryptionShare { + proposer_id: proposer_id.clone(), + share: share.clone(), + }; + let message = Target::All.message(content.with_epoch(self.epoch)); + self.messages.0.push_back(message); + let our_id = self.netinfo.our_uid().clone(); + let epoch = self.epoch; + // Receive the share locally. + self.handle_decryption_share_message(&our_id, epoch, proposer_id.clone(), share)?; + Ok(true) + } + /// Verifies the shares of the current epoch that are pending verification. Returned are the /// senders with incorrect pending shares. fn verify_pending_decryption_shares( From f202ccfeb890b687c1b736fe09ea7bd0d89d874f Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Tue, 26 Jun 2018 14:52:53 +0200 Subject: [PATCH 4/4] Compute is_peer on NetworkInfo creation. --- src/messaging.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/messaging.rs b/src/messaging.rs index 99c5503..b0c4152 100644 --- a/src/messaging.rs +++ b/src/messaging.rs @@ -142,6 +142,7 @@ pub struct NetworkInfo { all_uids: BTreeSet, num_nodes: usize, num_faulty: usize, + is_peer: bool, secret_key: ClearOnDrop>, public_key_set: PublicKeySet, node_indices: BTreeMap, @@ -155,6 +156,7 @@ impl NetworkInfo { public_key_set: PublicKeySet, ) -> Self { let num_nodes = all_uids.len(); + let is_peer = all_uids.contains(&our_uid); let node_indices = all_uids .iter() .cloned() @@ -166,6 +168,7 @@ impl NetworkInfo { all_uids, num_nodes, num_faulty: (num_nodes - 1) / 3, + is_peer, secret_key, public_key_set, node_indices, @@ -219,6 +222,6 @@ impl NetworkInfo { /// Returns `true` if this node takes part in the consensus itself. If not, it is only an /// observer. pub fn is_peer(&self) -> bool { - self.all_uids.contains(&self.our_uid) + self.is_peer } }