Add DKG example

This commit is contained in:
Luke Parker 2023-01-25 23:46:21 -05:00
parent d97890dee4
commit 8d1052f08f
No known key found for this signature in database
5 changed files with 95 additions and 16 deletions

1
Cargo.lock generated
View file

@ -1883,6 +1883,7 @@ dependencies = [
"schnorr-signatures",
"subtle",
"thiserror",
"tokio",
"zeroize",
]

View file

@ -32,6 +32,8 @@ ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std"] }
schnorr = { package = "schnorr-signatures", path = "../schnorr", version = "0.2" }
dleq = { path = "../dleq", version = "0.2", features = ["serialize"] }
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std", "ristretto"] }

View file

@ -0,0 +1,73 @@
use std::collections::HashMap;
use rand_core::OsRng;
use ciphersuite::{Ciphersuite, Ristretto};
use tokio::sync::mpsc::{self, UnboundedSender, UnboundedReceiver};
use dkg::{
ThresholdParams,
encryption::{EncryptionKeyMessage, EncryptedMessage},
frost::{Commitments, SecretShare, KeyGenMachine},
};
async fn dkg<C: Ciphersuite>(
i: u16,
send: UnboundedSender<Vec<u8>>,
mut recv: UnboundedReceiver<Vec<u8>>,
) {
// Calculate the other participant's i
let other_i = i ^ 0b11;
// A 2-of-2 multisig
let params = ThresholdParams::new(2, 2, i).unwrap();
// Create a key gen machine
let machine = KeyGenMachine::new(params, "DKG Example".to_string());
// Generate coefficients
let (machine, commitments) = machine.generate_coefficients(&mut OsRng);
// Send everyone our commitments
send.send(commitments.serialize()).unwrap();
// Receive everyone else's commitments
let other_commitments = EncryptionKeyMessage::<C, Commitments<C>>::read::<&[u8]>(
&mut recv.recv().await.unwrap().as_ref(),
params,
)
.unwrap();
let mut all_commitments = HashMap::new();
all_commitments.insert(other_i, other_commitments);
// Generate secret shares
let (machine, shares) = machine.generate_secret_shares(&mut OsRng, all_commitments).unwrap();
// Send everyone else their secret shares
send.send(shares[&other_i].serialize()).unwrap();
// Receive our shares from everyone else
let share = EncryptedMessage::<C, SecretShare<C::F>>::read::<&[u8]>(
&mut recv.recv().await.unwrap().as_ref(),
params,
)
.unwrap();
let mut all_shares = HashMap::new();
all_shares.insert(other_i, share);
// Calculate our share
let (machine, _key) = machine.calculate_share(&mut OsRng, all_shares).unwrap();
// Assume the process succeeded, though this should only be done ater everyone votes on the key
let _keys = machine.complete();
}
#[tokio::main]
async fn main() {
// Create a pair of channels
let (alice_send, alice_recv) = mpsc::unbounded_channel();
let (bob_send, bob_recv) = mpsc::unbounded_channel();
// Spawn Alice
let alice = dkg::<Ristretto>(1, alice_send, bob_recv);
// Spawn Bob
let bob = dkg::<Ristretto>(2, bob_send, alice_recv);
tokio::join!(alice, bob);
}

View file

@ -370,7 +370,7 @@ impl<C: Ciphersuite> KeyMachine<C> {
mut self,
rng: &mut R,
mut shares: HashMap<u16, EncryptedMessage<C, SecretShare<C::F>>>,
) -> Result<BlameMachine<C>, FrostError<C>> {
) -> Result<(BlameMachine<C>, C::G), FrostError<C>> {
validate_map(&shares, &(1 ..= self.params.n()).collect::<Vec<_>>(), self.params.i())?;
let mut batch = BatchVerifier::new(shares.len());
@ -423,16 +423,19 @@ impl<C: Ciphersuite> KeyMachine<C> {
}
let KeyMachine { commitments, encryption, params, secret } = self;
Ok(BlameMachine {
commitments,
encryption,
result: ThresholdCore {
params,
secret_share: secret,
group_key: stripes[0],
verification_shares,
Ok((
BlameMachine {
commitments,
encryption,
result: ThresholdCore {
params,
secret_share: secret,
group_key: stripes[0],
verification_shares,
},
},
})
stripes[0],
))
}
}

View file

@ -93,7 +93,7 @@ pub fn frost_gen<R: RngCore + CryptoRng, C: Ciphersuite>(
.drain()
.map(|(i, machine)| {
let our_secret_shares = generate_secret_shares(&secret_shares, i);
let these_keys = machine.calculate_share(rng, our_secret_shares).unwrap().complete();
let these_keys = machine.calculate_share(rng, our_secret_shares).unwrap().0.complete();
// Verify the verification_shares are agreed upon
if verification_shares.is_none() {
@ -157,7 +157,7 @@ mod literal {
blame = Some(None);
None
} else {
Some(machine.unwrap())
Some(machine.unwrap().0)
}
})
.collect::<Vec<_>>();
@ -191,7 +191,7 @@ mod literal {
});
None
} else {
Some(machine.unwrap())
Some(machine.unwrap().0)
}
})
.collect::<Vec<_>>();
@ -221,7 +221,7 @@ mod literal {
});
None
} else {
Some(machine.unwrap())
Some(machine.unwrap().0)
}
})
.collect::<Vec<_>>();
@ -255,7 +255,7 @@ mod literal {
});
None
} else {
Some(machine.unwrap())
Some(machine.unwrap().0)
}
})
.collect::<Vec<_>>();
@ -288,7 +288,7 @@ mod literal {
});
None
} else {
Some(machine.unwrap())
Some(machine.unwrap().0)
}
})
.collect::<Vec<_>>();