-
Notifications
You must be signed in to change notification settings - Fork 2
Simon/snapshots #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Simon/snapshots #218
Changes from 25 commits
edf21ec
ac58781
f8966a2
d35d317
11db1da
5bcd605
47f4fed
fab6283
a685499
63c02be
4bee396
f7a34c0
3720e8f
e3d3e15
09ad1ef
56654e3
05af30a
0433f71
fbecd8c
344b0b1
d15c9e1
10cad9a
5190b81
c1127b9
948ab62
0ea5e3e
9fbb034
a2ddf02
8c45ad0
da21da3
3ad84b2
8a7b1e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
SimonRastikian marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| use std::collections::HashMap; | ||
|
|
||
| use crate::{participants::Participant, protocol::MessageData}; | ||
|
|
||
| /// A single received message during a protocol run | ||
| #[derive(Debug, PartialEq, Clone)] | ||
| struct ReceivedMessageSnapshot { | ||
| from: Participant, | ||
| message: MessageData, | ||
| } | ||
|
|
||
| impl ReceivedMessageSnapshot { | ||
| fn new(from: Participant, message: MessageData) -> Self { | ||
| Self { from, message } | ||
| } | ||
| } | ||
|
|
||
| /// A participant's view of their received messages | ||
| struct ParticipantSnapshot { | ||
| // `snaps` is a list of (participant, messages) pairs | ||
| snaps: Vec<ReceivedMessageSnapshot>, | ||
| // `read_index` helps knowing which snap has been already | ||
| // output during the reading queries | ||
| read_index: usize, | ||
| } | ||
|
|
||
| impl ParticipantSnapshot { | ||
| pub fn new_empty() -> Self { | ||
| Self { | ||
| snaps: Vec::new(), | ||
| read_index: 0, | ||
| } | ||
| } | ||
SimonRastikian marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| fn push_received_message_snapshot(&mut self, snap: ReceivedMessageSnapshot) { | ||
| self.snaps.push(snap); | ||
| } | ||
|
|
||
| fn push_message(&mut self, from: Participant, message: MessageData) { | ||
| let snap = ReceivedMessageSnapshot::new(from, message); | ||
| self.push_received_message_snapshot(snap); | ||
| } | ||
|
|
||
| fn read_next_message(&mut self) -> Option<(Participant, MessageData)> { | ||
| if self.read_index >= self.snaps.len() { | ||
| return None; | ||
| } | ||
| let message_snap = &self.snaps[self.read_index]; | ||
| self.read_index += 1; | ||
| Some((message_snap.from, message_snap.message.clone())) | ||
| } | ||
|
|
||
| fn refresh_read_all(&mut self) { | ||
| self.read_index = 0; | ||
| } | ||
| } | ||
|
|
||
| /// Used to store the snapshot of all the messages sent during | ||
| /// the communication rounds of a certain protocol | ||
| pub struct ProtocolSnapshot { | ||
| snapshots: HashMap<Participant, ParticipantSnapshot>, | ||
| } | ||
|
|
||
| impl ProtocolSnapshot { | ||
| /// Creates an empty snapshot | ||
| pub fn new_empty(participants: Vec<Participant>) -> Self { | ||
| let snapshots = participants | ||
| .into_iter() | ||
| .map(|p| (p, ParticipantSnapshot::new_empty())) | ||
| .collect::<HashMap<_, _>>(); | ||
| Self { snapshots } | ||
| } | ||
|
|
||
| /// Adds a messages sent by a sender and to a receiver to the protocol snapshot | ||
| pub fn push_message( | ||
| &mut self, | ||
| to: Participant, | ||
| from: Participant, | ||
| message: MessageData, | ||
| ) -> Option<()> { | ||
| self.snapshots | ||
| .get_mut(&to) | ||
| .map(|snapshot| snapshot.push_message(from, message)) | ||
| } | ||
|
|
||
| /// Reads the next message stored in the snapshot of a particular participant given as input | ||
| pub fn read_next_message_for_participant( | ||
| &mut self, | ||
| participant: Participant, | ||
| ) -> Option<(Participant, MessageData)> { | ||
| self.snapshots | ||
| .get_mut(&participant) | ||
| .and_then(ParticipantSnapshot::read_next_message) | ||
| } | ||
|
|
||
| pub fn refresh_read_all(&mut self) { | ||
| for snapshot in self.snapshots.values_mut() { | ||
| snapshot.refresh_read_all(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod test { | ||
| use super::*; | ||
| use crate::ecdsa::{ | ||
| robust_ecdsa::{presign::presign, PresignArguments, PresignOutput}, | ||
| KeygenOutput, Polynomial, | ||
| }; | ||
| use crate::test_utils::{ | ||
| generate_participants, run_protocol_and_take_snapshots, GenProtocol, MockCryptoRng, | ||
| }; | ||
| use crate::SigningShare; | ||
| use frost_secp256k1::VerifyingKey; | ||
| use k256::ProjectivePoint; | ||
| use rand_core::CryptoRngCore; | ||
|
|
||
| fn generate_random_received_snap(rng: &mut impl CryptoRngCore) -> ReceivedMessageSnapshot { | ||
| let from = Participant::from(rng.next_u32()); | ||
| let mut message: [u8; 32] = [0u8; 32]; | ||
| rng.fill_bytes(&mut message); | ||
| let message = message.to_vec(); | ||
| ReceivedMessageSnapshot::new(from, message) | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_read_next_message() { | ||
| let mut psnap = ParticipantSnapshot::new_empty(); | ||
| let mut rvec = Vec::new(); | ||
| let mut rng = MockCryptoRng::seed_from_u64(123_123); | ||
| for _ in 0..50 { | ||
| let received_snap = generate_random_received_snap(&mut rng); | ||
| rvec.push(received_snap.clone()); | ||
| psnap.push_received_message_snapshot(received_snap); | ||
| } | ||
| for r in rvec { | ||
| let (from, message) = psnap.read_next_message().unwrap(); | ||
| let read_message = ReceivedMessageSnapshot::new(from, message); | ||
| assert_eq!(r, read_message); | ||
| } | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_refresh_read_all() { | ||
| let mut psnap = ParticipantSnapshot::new_empty(); | ||
| let mut rng = MockCryptoRng::seed_from_u64(123_123); | ||
| for _ in 0..50 { | ||
| let received_snap = generate_random_received_snap(&mut rng); | ||
| psnap.push_received_message_snapshot(received_snap); | ||
| } | ||
|
|
||
| let mut rvec = Vec::new(); | ||
| for _ in 0..50 { | ||
| let (from, message) = psnap.read_next_message().unwrap(); | ||
| let read_message = ReceivedMessageSnapshot::new(from, message); | ||
| rvec.push(read_message); | ||
SimonRastikian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| psnap.refresh_read_all(); | ||
| for r in rvec { | ||
| let (from, message) = psnap.read_next_message().unwrap(); | ||
| let read_message = ReceivedMessageSnapshot::new(from, message); | ||
| assert_eq!(r, read_message); | ||
| } | ||
| } | ||
|
|
||
| fn prepare_keys(p: Participant, f: &Polynomial, big_x: ProjectivePoint) -> KeygenOutput { | ||
| let private_share = f.eval_at_participant(p).unwrap(); | ||
| let verifying_key = VerifyingKey::new(big_x); | ||
| KeygenOutput { | ||
| private_share: SigningShare::new(private_share.0), | ||
| public_key: verifying_key, | ||
| } | ||
| } | ||
|
Comment on lines
+160
to
+167
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this function seems out of place, as it is not related to snapshots. Aren't we doing exactly the same thing elsewhere?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea of this function is to simplify the reading. Not sure there is a specific function like this one that does the exact same things.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, what I am saying is that it should not leave here, seems like a function that could be easily reused in other places as well
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this means that the PR would refactor all the implementation (where the function can be called). I do not think it's a great idea to handle this in this PR tho.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, we could add a TODO comment here linked to an issue, so that in the next refactor this is easy to find. But in general I hope that soon enough this type of thing is not needed anymore :) |
||
|
|
||
| fn compare_presign_outputs(o1: &PresignOutput, o2: &PresignOutput) -> bool { | ||
| o1.alpha == o2.alpha | ||
| && o1.beta == o2.beta | ||
| && o1.c == o2.c | ||
| && o1.e == o2.e | ||
| && o1.big_r == o2.big_r | ||
| } | ||
SimonRastikian marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #[test] | ||
| fn ecdsa_presign_should_return_same_snapshot_when_executed_twice() { | ||
| let max_malicious = 2; | ||
| let participants = generate_participants(5); | ||
|
|
||
| let mut rng = MockCryptoRng::seed_from_u64(42u64); | ||
| let f = Polynomial::generate_polynomial(None, max_malicious, &mut rng).unwrap(); | ||
| let big_x = ProjectivePoint::GENERATOR * f.eval_at_zero().unwrap().0; | ||
|
|
||
| // create rngs for first and second snapshots | ||
| let rngs = crate::test_utils::mockrng::test::create_rngs(&participants, &mut rng); | ||
|
|
||
| let mut results = Vec::new(); | ||
| let mut snapshots = Vec::new(); | ||
|
|
||
| // Running the protocol twice | ||
| for _ in 0..2 { | ||
| let mut protocols: GenProtocol<PresignOutput> = Vec::with_capacity(participants.len()); | ||
| for (i, p) in participants.iter().enumerate() { | ||
| // simulating the key packages for each participant | ||
| let keygen_out = prepare_keys(*p, &f, big_x); | ||
| let protocol = presign( | ||
| &participants[..], | ||
| *p, | ||
| PresignArguments { | ||
| keygen_out, | ||
| threshold: max_malicious, | ||
| }, | ||
| rngs[i].clone(), | ||
| ) | ||
| .unwrap(); | ||
| protocols.push((*p, Box::new(protocol))); | ||
| } | ||
| let (result, snapshot) = run_protocol_and_take_snapshots(protocols).unwrap(); | ||
| results.push(result); | ||
| snapshots.push(snapshot); | ||
| } | ||
|
|
||
| // Check the results are the same | ||
| assert!(results[0].iter().all(|(p1, o1)| { | ||
| results[1] | ||
| .iter() | ||
| .any(|(p2, o2)| p1 == p2 && compare_presign_outputs(o1, o2)) | ||
| })); | ||
|
|
||
| // Check the messages sent per participants are the same | ||
| for p in participants { | ||
| while let Some((sender1, msg1)) = snapshots[0].read_next_message_for_participant(p) { | ||
| let (sender2, msg2) = snapshots[1].read_next_message_for_participant(p).unwrap(); | ||
| assert!(sender1 == sender2 && msg1 == msg2); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.