mirror of https://github.com/poanetwork/hbbft.git
Replace Coin with ThresholdSign. (#280)
* Avoid redundant hashing in Coin. * Return the full signature from Coin. * Rename Coin to ThresholdSign.
This commit is contained in:
parent
13308906aa
commit
6bcd6bc499
|
@ -32,7 +32,7 @@ rand_derive = "0.3.1"
|
|||
reed-solomon-erasure = "3.1.0"
|
||||
serde = "1.0.55"
|
||||
serde_derive = "1.0.55"
|
||||
threshold_crypto = "0.2"
|
||||
threshold_crypto = "0.2.1"
|
||||
tiny-keccak = "1.4"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -37,7 +37,8 @@ In addition to **validators**, the algorithms support **observers**: These don't
|
|||
|
||||
- **[Binary Agreement](src/binary_agreement/binary_agreement.rs):** Each node inputs a binary value. The nodes agree on a value that was input by at least one correct node.
|
||||
|
||||
- **[Coin](src/coin.rs):** A pseudorandom binary value used by the Binary Agreement protocol.
|
||||
- **[Threshold Sign](src/threshold_sign.rs):**
|
||||
Each node inputs the same data to be signed, and outputs the unique valid signature matching the public master key. It is used as a pseudorandom value in the Binary Agreement protocol.
|
||||
|
||||
- **[Threshold Decryption](src/threshold_decryption.rs):**
|
||||
Each node inputs the same ciphertext, encrypted to the public master key, and outputs the decrypted data.
|
||||
|
@ -147,7 +148,6 @@ We have simplified algorithm naming conventions from the original paper.
|
|||
| Subset | Asynchronous Common Subset (ACS) |
|
||||
| Broadcast | Reliable Broadcast (RBC) |
|
||||
| Binary Agreement | Binary Byzantine Agreement (BBA) |
|
||||
| Coin | Common Coin |
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use super::bool_multimap::BoolMultimap;
|
|||
use super::bool_set::BoolSet;
|
||||
use super::sbv_broadcast::{self, SbvBroadcast};
|
||||
use super::{Error, Message, MessageContent, Nonce, Result, Step};
|
||||
use coin::{self, Coin, CoinMessage};
|
||||
use threshold_sign::{self, ThresholdSign};
|
||||
use {DistAlgorithm, NetworkInfo, NodeIdT, Target};
|
||||
|
||||
/// The state of the current epoch's coin. In some epochs this is fixed, in others it starts
|
||||
|
@ -15,7 +15,7 @@ enum CoinState<N> {
|
|||
/// The value was fixed in the current epoch, or the coin has already terminated.
|
||||
Decided(bool),
|
||||
/// The coin value is not known yet.
|
||||
InProgress(Coin<N, Nonce>),
|
||||
InProgress(Box<ThresholdSign<N>>),
|
||||
}
|
||||
|
||||
impl<N> CoinState<N> {
|
||||
|
@ -221,16 +221,16 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles a Coin message. If there is output from Coin, starts the next
|
||||
/// epoch. The function may output a decision value.
|
||||
fn handle_coin(&mut self, sender_id: &N, msg: CoinMessage) -> Result<Step<N>> {
|
||||
let coin_step = match self.coin_state {
|
||||
/// Handles a `ThresholdSign` message. If there is output, starts the next epoch. The function
|
||||
/// may output a decision value.
|
||||
fn handle_coin(&mut self, sender_id: &N, msg: threshold_sign::Message) -> Result<Step<N>> {
|
||||
let ts_step = match self.coin_state {
|
||||
CoinState::Decided(_) => return Ok(Step::default()), // Coin value is already decided.
|
||||
CoinState::InProgress(ref mut coin) => coin
|
||||
CoinState::InProgress(ref mut ts) => ts
|
||||
.handle_message(sender_id, msg)
|
||||
.map_err(Error::HandleCoin)?,
|
||||
.map_err(Error::HandleThresholdSign)?,
|
||||
};
|
||||
self.on_coin_step(coin_step)
|
||||
self.on_coin_step(ts_step)
|
||||
}
|
||||
|
||||
/// Multicasts a `Conf(values)` message, and handles it.
|
||||
|
@ -263,14 +263,15 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
Ok(step)
|
||||
}
|
||||
|
||||
/// Handles a step returned from the `Coin`.
|
||||
fn on_coin_step(&mut self, coin_step: coin::Step<N, Nonce>) -> Result<Step<N>> {
|
||||
/// Handles a step returned from the `ThresholdSign`.
|
||||
fn on_coin_step(&mut self, ts_step: threshold_sign::Step<N>) -> Result<Step<N>> {
|
||||
let mut step = Step::default();
|
||||
let epoch = self.epoch;
|
||||
let to_msg = |c_msg| MessageContent::Coin(Box::new(c_msg)).with_epoch(epoch);
|
||||
let coin_output = step.extend_with(coin_step, to_msg);
|
||||
if let Some(coin) = coin_output.into_iter().next() {
|
||||
self.coin_state = coin.into();
|
||||
let ts_output = step.extend_with(ts_step, to_msg);
|
||||
if let Some(sig) = ts_output.into_iter().next() {
|
||||
// Take the parity of the signature as the coin value.
|
||||
self.coin_state = sig.parity().into();
|
||||
step.extend(self.try_update_epoch()?);
|
||||
}
|
||||
Ok(step)
|
||||
|
@ -304,7 +305,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
}
|
||||
|
||||
/// Creates the initial coin state for the current epoch, i.e. sets it to the predetermined
|
||||
/// value, or initializes a `Coin` instance.
|
||||
/// value, or initializes a `ThresholdSign` instance.
|
||||
fn coin_state(&self) -> CoinState<N> {
|
||||
match self.epoch % 3 {
|
||||
0 => CoinState::Decided(true),
|
||||
|
@ -316,7 +317,7 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
self.netinfo.node_index(&self.proposer_id).unwrap(),
|
||||
self.epoch,
|
||||
);
|
||||
CoinState::InProgress(Coin::new(self.netinfo.clone(), nonce))
|
||||
CoinState::InProgress(Box::new(ThresholdSign::new(self.netinfo.clone(), nonce)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -352,13 +353,11 @@ impl<N: NodeIdT> BinaryAgreement<N> {
|
|||
}
|
||||
|
||||
// Invoke the coin.
|
||||
let coin_step = match self.coin_state {
|
||||
let ts_step = match self.coin_state {
|
||||
CoinState::Decided(_) => return Ok(Step::default()), // Coin has already decided.
|
||||
CoinState::InProgress(ref mut coin) => coin
|
||||
.handle_input(())
|
||||
.map_err(Error::TryFinishConfRoundCoin)?,
|
||||
CoinState::InProgress(ref mut ts) => ts.handle_input(()).map_err(Error::InvokeCoin)?,
|
||||
};
|
||||
let mut step = self.on_coin_step(coin_step)?;
|
||||
let mut step = self.on_coin_step(ts_step)?;
|
||||
step.extend(self.try_update_epoch()?);
|
||||
Ok(step)
|
||||
}
|
||||
|
|
|
@ -71,17 +71,17 @@ mod sbv_broadcast;
|
|||
use rand;
|
||||
|
||||
use self::bool_set::BoolSet;
|
||||
use coin::{self, CoinMessage};
|
||||
use threshold_sign;
|
||||
|
||||
pub use self::binary_agreement::BinaryAgreement;
|
||||
|
||||
/// An Binary Agreement error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "HandleCoin error: {}", _0)]
|
||||
HandleCoin(coin::Error),
|
||||
#[fail(display = "TryFinishConfRoundCoin error: {}", _0)]
|
||||
TryFinishConfRoundCoin(coin::Error),
|
||||
#[fail(display = "Error handling threshold sign message: {}", _0)]
|
||||
HandleThresholdSign(threshold_sign::Error),
|
||||
#[fail(display = "Error invoking the common coin: {}", _0)]
|
||||
InvokeCoin(threshold_sign::Error),
|
||||
#[fail(display = "Unknown proposer")]
|
||||
UnknownProposer,
|
||||
#[fail(display = "Input not accepted")]
|
||||
|
@ -101,8 +101,8 @@ pub enum MessageContent {
|
|||
Conf(BoolSet),
|
||||
/// `Term` message.
|
||||
Term(bool),
|
||||
/// Coin message,
|
||||
Coin(Box<CoinMessage>),
|
||||
/// `ThresholdSign` message used for the common coin,
|
||||
Coin(Box<threshold_sign::Message>),
|
||||
}
|
||||
|
||||
impl MessageContent {
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -85,12 +85,11 @@
|
|||
//! This is used in Subset to decide whether each node's proposal should be included in the subset
|
||||
//! or not.
|
||||
//!
|
||||
//! [**Coin**](coin/index.html)
|
||||
//! [**Threshold Sign**](threshold_sign/index.html)
|
||||
//!
|
||||
//! Each node inputs `()` to initiate a coin flip. Once _f + 1_ nodes have input, either all nodes
|
||||
//! receive `true` or all nodes receive `false`. The outcome cannot be known by the adversary
|
||||
//! before at least one correct node has provided input, and is uniformly distributed and
|
||||
//! pseudorandom.
|
||||
//! Each node inputs `()` to broadcast signature shares. Once _f + 1_ nodes have input, all nodes
|
||||
//! receive a valid signature. The outcome cannot be known by the adversary before at least one
|
||||
//! correct node has provided input, and can be used as a source of pseudorandomness.
|
||||
//!
|
||||
//! [**Threshold Decryption**](threshold_decryption/index.html)
|
||||
//!
|
||||
|
@ -144,13 +143,13 @@ mod traits;
|
|||
|
||||
pub mod binary_agreement;
|
||||
pub mod broadcast;
|
||||
pub mod coin;
|
||||
pub mod dynamic_honey_badger;
|
||||
pub mod honey_badger;
|
||||
pub mod queueing_honey_badger;
|
||||
pub mod subset;
|
||||
pub mod sync_key_gen;
|
||||
pub mod threshold_decryption;
|
||||
pub mod threshold_sign;
|
||||
pub mod transaction_queue;
|
||||
pub mod util;
|
||||
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
//! # A Cryptographic Coin
|
||||
//! # Collaborative Threshold Signing
|
||||
//!
|
||||
//! The Coin produces a pseudorandom binary value that the correct nodes agree on, and that
|
||||
//! cannot be known beforehand.
|
||||
//! The algorithm is instantiated with data to sign, and waits for the input (no data, just `()`),
|
||||
//! then sends a signature share to the others. When at least _f + 1_ correct validators have done
|
||||
//! so, each node outputs the same, valid signature of the data.
|
||||
//!
|
||||
//! Every Coin instance has a _nonce_ that determines the value, without giving it away: It
|
||||
//! is not feasible to compute the output from the nonce alone, and the output is uniformly
|
||||
//! distributed.
|
||||
//!
|
||||
//! The nodes input a signal (no data, just `()`), and after _2 f + 1_ nodes have provided input,
|
||||
//! everyone receives the output value. In particular, the adversary cannot know the output value
|
||||
//! before at least one correct node has provided input.
|
||||
//! In addition to signing, this can also be used as a source of pseudorandomness: The signature
|
||||
//! cannot be known until more than _f_ validators have contributed their shares.
|
||||
//!
|
||||
//! ## How it works
|
||||
//!
|
||||
//! The algorithm uses a threshold signature scheme with the uniqueness property: For each public
|
||||
//! key and message, there is exactly one valid signature. This group signature is produced using
|
||||
//! signature shares from any combination of _2 f + 1_ secret key share holders.
|
||||
//!
|
||||
//! * On input, a node signs the nonce and sends its signature share to everyone else.
|
||||
//! * When a node has received _2 f + 1_ shares, it computes the main signature and outputs the XOR
|
||||
//! of its bits.
|
||||
//! signature shares from any combination of _f + 1_ secret key share holders.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crypto::{self, Signature, SignatureShare};
|
||||
use crypto::{self, hash_g2, Signature, SignatureShare, G2};
|
||||
use fault_log::{Fault, FaultKind};
|
||||
use {DistAlgorithm, NetworkInfo, NodeIdT, Target};
|
||||
|
||||
/// A coin error.
|
||||
/// A threshold signing error.
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum Error {
|
||||
#[fail(display = "CombineAndVerifySigCrypto error: {}", _0)]
|
||||
|
@ -39,15 +31,15 @@ pub enum Error {
|
|||
VerificationFailed,
|
||||
}
|
||||
|
||||
/// A coin result.
|
||||
/// A threshold signing result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Rand)]
|
||||
pub struct CoinMessage(SignatureShare);
|
||||
pub struct Message(SignatureShare);
|
||||
|
||||
impl CoinMessage {
|
||||
impl Message {
|
||||
pub fn new(sig: SignatureShare) -> Self {
|
||||
CoinMessage(sig)
|
||||
Message(sig)
|
||||
}
|
||||
|
||||
pub fn to_sig(&self) -> &SignatureShare {
|
||||
|
@ -55,43 +47,34 @@ impl CoinMessage {
|
|||
}
|
||||
}
|
||||
|
||||
/// A coin algorithm instance. On input, broadcasts our threshold signature share. Upon
|
||||
/// A threshold signing algorithm instance. On input, broadcasts our threshold signature share. Upon
|
||||
/// receiving at least `num_faulty + 1` shares, attempts to combine them into a signature. If that
|
||||
/// signature is valid, the instance outputs it and terminates; otherwise the instance aborts.
|
||||
#[derive(Debug)]
|
||||
pub struct Coin<N, T> {
|
||||
pub struct ThresholdSign<N> {
|
||||
netinfo: Arc<NetworkInfo<N>>,
|
||||
/// The name of this coin. It is required to be unique for each coin round.
|
||||
nonce: T,
|
||||
/// The hash of the data to be signed.
|
||||
msg_hash: G2,
|
||||
/// All received threshold signature shares.
|
||||
received_shares: BTreeMap<N, SignatureShare>,
|
||||
/// Whether we provided input to the coin.
|
||||
/// Whether we already sent our shares.
|
||||
had_input: bool,
|
||||
/// Termination flag.
|
||||
terminated: bool,
|
||||
}
|
||||
|
||||
pub type Step<N, T> = ::Step<Coin<N, T>>;
|
||||
pub type Step<N> = ::Step<ThresholdSign<N>>;
|
||||
|
||||
impl<N, T> DistAlgorithm for Coin<N, T>
|
||||
where
|
||||
N: NodeIdT,
|
||||
T: Clone + AsRef<[u8]> + Send + Sync,
|
||||
{
|
||||
impl<N: NodeIdT> DistAlgorithm for ThresholdSign<N> {
|
||||
type NodeId = N;
|
||||
type Input = ();
|
||||
type Output = bool;
|
||||
type Message = CoinMessage;
|
||||
type Output = Signature;
|
||||
type Message = Message;
|
||||
type Error = Error;
|
||||
|
||||
/// Sends our threshold signature share if not yet sent.
|
||||
fn handle_input(&mut self, _input: Self::Input) -> Result<Step<N, T>> {
|
||||
if !self.had_input {
|
||||
self.had_input = true;
|
||||
self.get_coin()
|
||||
} else {
|
||||
Ok(Step::default())
|
||||
}
|
||||
fn handle_input(&mut self, _input: Self::Input) -> Result<Step<N>> {
|
||||
self.get_sig()
|
||||
}
|
||||
|
||||
/// Receives input from a remote node.
|
||||
|
@ -99,9 +82,9 @@ where
|
|||
&mut self,
|
||||
sender_id: &Self::NodeId,
|
||||
message: Self::Message,
|
||||
) -> Result<Step<N, T>> {
|
||||
) -> Result<Step<N>> {
|
||||
if !self.terminated {
|
||||
let CoinMessage(share) = message;
|
||||
let Message(share) = message;
|
||||
self.handle_share(sender_id, share)
|
||||
} else {
|
||||
Ok(Step::default())
|
||||
|
@ -118,35 +101,35 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<N, T> Coin<N, T>
|
||||
where
|
||||
N: NodeIdT,
|
||||
T: Clone + AsRef<[u8]> + Send + Sync,
|
||||
{
|
||||
pub fn new(netinfo: Arc<NetworkInfo<N>>, nonce: T) -> Self {
|
||||
Coin {
|
||||
impl<N: NodeIdT> ThresholdSign<N> {
|
||||
pub fn new<M: AsRef<[u8]>>(netinfo: Arc<NetworkInfo<N>>, msg: M) -> Self {
|
||||
ThresholdSign {
|
||||
netinfo,
|
||||
nonce,
|
||||
msg_hash: hash_g2(msg),
|
||||
received_shares: BTreeMap::new(),
|
||||
had_input: false,
|
||||
terminated: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_coin(&mut self) -> Result<Step<N, T>> {
|
||||
fn get_sig(&mut self) -> Result<Step<N>> {
|
||||
if self.had_input {
|
||||
return Ok(Step::default());
|
||||
}
|
||||
self.had_input = true;
|
||||
if !self.netinfo.is_validator() {
|
||||
return self.try_output();
|
||||
}
|
||||
let share = self.netinfo.secret_key_share().sign(&self.nonce);
|
||||
let mut step: Step<_, _> = Target::All.message(CoinMessage(share.clone())).into();
|
||||
let share = self.netinfo.secret_key_share().sign_g2(self.msg_hash);
|
||||
let mut step: Step<_> = Target::All.message(Message(share.clone())).into();
|
||||
let id = self.netinfo.our_id().clone();
|
||||
step.extend(self.handle_share(&id, share)?);
|
||||
Ok(step)
|
||||
}
|
||||
|
||||
fn handle_share(&mut self, sender_id: &N, share: SignatureShare) -> Result<Step<N, T>> {
|
||||
fn handle_share(&mut self, sender_id: &N, share: SignatureShare) -> Result<Step<N>> {
|
||||
if let Some(pk_i) = self.netinfo.public_key_share(sender_id) {
|
||||
if !pk_i.verify(&share, &self.nonce) {
|
||||
if !pk_i.verify_g2(&share, self.msg_hash) {
|
||||
// Log the faulty node and ignore the invalid share.
|
||||
let fault_kind = FaultKind::UnverifiedSignatureShareSender;
|
||||
return Ok(Fault::new(sender_id.clone(), fault_kind).into());
|
||||
|
@ -158,7 +141,7 @@ where
|
|||
self.try_output()
|
||||
}
|
||||
|
||||
fn try_output(&mut self) -> Result<Step<N, T>> {
|
||||
fn try_output(&mut self) -> Result<Step<N>> {
|
||||
debug!(
|
||||
"{:?} received {} shares, had_input = {}",
|
||||
self.netinfo.our_id(),
|
||||
|
@ -167,12 +150,10 @@ where
|
|||
);
|
||||
if self.had_input && self.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();
|
||||
debug!("{:?} output {}", self.netinfo.our_id(), parity);
|
||||
debug!("{:?} output {:?}", self.netinfo.our_id(), sig);
|
||||
self.terminated = true;
|
||||
let step = self.handle_input(())?; // Before terminating, make sure we sent our share.
|
||||
Ok(step.with_output(parity))
|
||||
Ok(step.with_output(sig))
|
||||
} else {
|
||||
Ok(Step::default())
|
||||
}
|
||||
|
@ -191,7 +172,7 @@ where
|
|||
.netinfo
|
||||
.public_key_set()
|
||||
.public_key()
|
||||
.verify(&sig, &self.nonce)
|
||||
.verify_g2(&sig, self.msg_hash)
|
||||
{
|
||||
// Abort
|
||||
error!(
|
|
@ -1,5 +1,5 @@
|
|||
#![deny(unused_must_use)]
|
||||
//! Coin tests
|
||||
//! Threshold signing tests
|
||||
|
||||
extern crate env_logger;
|
||||
extern crate hbbft;
|
||||
|
@ -18,15 +18,16 @@ use std::iter::once;
|
|||
|
||||
use rand::Rng;
|
||||
|
||||
use hbbft::coin::Coin;
|
||||
use crypto::Signature;
|
||||
use hbbft::threshold_sign::ThresholdSign;
|
||||
|
||||
use network::{Adversary, MessageScheduler, NodeId, SilentAdversary, TestNetwork, TestNode};
|
||||
|
||||
/// Tests a network of Coin instances with an optional expected value. Outputs the computed
|
||||
/// coin value if the test is successful.
|
||||
fn test_coin<A>(mut network: TestNetwork<A, Coin<NodeId, String>>) -> bool
|
||||
/// Tests a network of threshold signing instances with an optional expected value. Outputs the
|
||||
/// computed signature if the test is successful.
|
||||
fn test_threshold_sign<A>(mut network: TestNetwork<A, ThresholdSign<NodeId>>) -> Signature
|
||||
where
|
||||
A: Adversary<Coin<NodeId, String>>,
|
||||
A: Adversary<ThresholdSign<NodeId>>,
|
||||
{
|
||||
network.input_all(());
|
||||
network.observer.handle_input(()); // Observer will only return after `input` was called.
|
||||
|
@ -38,11 +39,11 @@ where
|
|||
let mut expected = None;
|
||||
// Verify that all instances output the same value.
|
||||
for node in network.nodes.values() {
|
||||
if let Some(b) = expected {
|
||||
assert!(once(&b).eq(node.outputs()));
|
||||
if let Some(ref b) = expected {
|
||||
assert!(once(b).eq(node.outputs()));
|
||||
} else {
|
||||
assert_eq!(1, node.outputs().len());
|
||||
expected = Some(node.outputs()[0]);
|
||||
expected = Some(node.outputs()[0].clone());
|
||||
}
|
||||
}
|
||||
// Now `expected` is the unique output of all good nodes.
|
||||
|
@ -71,9 +72,9 @@ fn check_coin_distribution(num_samples: usize, count_true: usize, count_false: u
|
|||
assert!(count_false > min_throws);
|
||||
}
|
||||
|
||||
fn test_coin_different_sizes<A, F>(new_adversary: F, num_samples: usize)
|
||||
fn test_threshold_sign_different_sizes<A, F>(new_adversary: F, num_samples: usize)
|
||||
where
|
||||
A: Adversary<Coin<NodeId, String>>,
|
||||
A: Adversary<ThresholdSign<NodeId>>,
|
||||
F: Fn(usize, usize) -> A,
|
||||
{
|
||||
assert!(num_samples > 0);
|
||||
|
@ -105,9 +106,9 @@ where
|
|||
let adversary = |_| new_adversary(num_good_nodes, num_faulty_nodes);
|
||||
let nonce = format!("My very unique nonce {:x}:{}", unique_id, i);
|
||||
info!("Nonce: {}", nonce);
|
||||
let new_coin = |netinfo: _| Coin::new(netinfo, nonce.clone());
|
||||
let new_coin = |netinfo: _| ThresholdSign::new(netinfo, nonce.clone());
|
||||
let network = TestNetwork::new(num_good_nodes, num_faulty_nodes, adversary, new_coin);
|
||||
let coin = test_coin(network);
|
||||
let coin = test_threshold_sign(network).parity();
|
||||
if coin {
|
||||
count_true += 1;
|
||||
} else {
|
||||
|
@ -119,13 +120,13 @@ where
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_coin_random_silent_200_samples() {
|
||||
fn test_threshold_sign_random_silent_200_samples() {
|
||||
let new_adversary = |_: usize, _: usize| SilentAdversary::new(MessageScheduler::Random);
|
||||
test_coin_different_sizes(new_adversary, 200);
|
||||
test_threshold_sign_different_sizes(new_adversary, 200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_coin_first_silent_50_samples() {
|
||||
fn test_threshold_sign_first_silent_50_samples() {
|
||||
let new_adversary = |_: usize, _: usize| SilentAdversary::new(MessageScheduler::First);
|
||||
test_coin_different_sizes(new_adversary, 50);
|
||||
test_threshold_sign_different_sizes(new_adversary, 50);
|
||||
}
|
Loading…
Reference in New Issue