#![allow( clippy::type_complexity, clippy::too_many_arguments, clippy::large_enum_variant )] use mpstthree::binary::struct_trait::end::End; use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; use mpstthree::generate_atmp; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{random, thread_rng, Rng}; use std::collections::HashMap; use std::error::Error; use std::time::Instant; // See the folder scribble_protocols for the related Scribble protocol // Create the new MeshedChannels for three participants and the close and fork functions generate_atmp!(MeshedChannels, A, C, S); // Types type RS = RecvTimed>; // C0 type Choose0fromCtoA = SendTimed; type Choose0fromCtoS = SendTimed; // C1 type Choose1fromCtoA = SendTimed; type Choose1fromCtoS = SendTimed; // A enum Branching0fromCtoA { Select(MeshedChannels, NameA>), Loops( MeshedChannels< RS, SendTimed, RolesCCSC, NameA, >, ), } type RolesCCSC = RoleC>>>; type Choice0fromCtoA = RecvTimed; enum Branching1fromCtoA { Yes( MeshedChannels< RecvTimed< i32, 'a', 0, true, 10, true, ' ', RecvTimed, >, SendTimed, RoleC>>, NameA, >, ), No( MeshedChannels< RecvTimed< i32, 'a', 0, true, 10, true, ' ', RecvTimed, >, SendTimed, RoleC>>, NameA, >, ), } type Choice1fromCtoA = RecvTimed; // S enum Branching0fromCtoS { Select(MeshedChannels, NameS>), Loops( MeshedChannels< RecvTimed, Choice0fromCtoS, RolesAC, NameS, >, ), } type RolesAC = RoleA>; type Choice0fromCtoS = RecvTimed; enum Branching1fromCtoS { Yes(MeshedChannels, RS, RolesACC, NameS>), No( MeshedChannels< RecvTimed, End, RoleA, NameS, >, ), } type RolesACC = RoleA>>; type Choice1fromCtoS = RecvTimed; // Creating the MP sessions // A type ChoiceA = MeshedChannels, NameA>; type EndpointA = MeshedChannels, NameA>; // C type ChoiceC = MeshedChannels; type EndpointC = MeshedChannels; type EndpointCSelect = MeshedChannels< SendTimed, SendTimed, RoleBroadcast, NameC, >; type EndpointCLoops = MeshedChannels< SendTimed< i32, 'a', 0, true, 10, true, ' ', RecvTimed< i32, 'a', 0, true, 10, true, ' ', SendTimed, >, >, SendTimed, RoleA>, NameC, >; type EndpointCYes = MeshedChannels< SendTimed>, SendTimed>, RoleA>>>, NameC, >; type EndpointCNo = MeshedChannels< SendTimed>, End, RoleA>, NameC, >; // S type ChoiceS = MeshedChannels, NameS>; type EndpointS = MeshedChannels, NameS>; // Functions // A fn endpoint_a(s: EndpointA, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); offer_mpst!(s, all_clocks, { Branching0fromCtoA::Select(s) => { choice_a(s, all_clocks) }, Branching0fromCtoA::Loops(s) => { let (query, s) = s.recv(all_clocks)?; let s = s.send(query, all_clocks)?; let s = s.send(random(), all_clocks)?; endpoint_a(s, all_clocks) }, }) } fn choice_a(s: ChoiceA, all_clocks: &mut HashMap) -> Result<(), Box> { offer_mpst!(s, all_clocks, { Branching1fromCtoA::Yes(s) => { let (yes, s) = s.recv(all_clocks)?; let s = s.send(yes, all_clocks)?; let (_yes, s) = s.recv(all_clocks)?; s.close() }, Branching1fromCtoA::No(s) => { let (no, s) = s.recv(all_clocks)?; let s = s.send(no, all_clocks)?; let (_yes, s) = s.recv(all_clocks)?; s.close() }, }) } fn endpoint_c(s: EndpointC, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let choice: i32 = thread_rng().gen_range(1..=3); if choice != 1 { let s: EndpointCSelect = choose_mpst_c_to_all!( s, all_clocks, Branching0fromCtoA::Select, Branching0fromCtoS::Select, ); choice_c(s, all_clocks) } else { let s: EndpointCLoops = choose_mpst_c_to_all!( s, all_clocks, Branching0fromCtoA::Loops, Branching0fromCtoS::Loops, ); let s = s.send(random(), all_clocks)?; let (_quote, s) = s.recv(all_clocks)?; endpoint_c(s, all_clocks) } } fn choice_c(s: ChoiceC, all_clocks: &mut HashMap) -> Result<(), Box> { let choice: i32 = thread_rng().gen_range(1..=3); if choice != 1 { let s: EndpointCYes = choose_mpst_c_to_all!( s, all_clocks, Branching1fromCtoA::Yes, Branching1fromCtoS::Yes, ); let s = s.send(random(), all_clocks)?; let s = s.send(random(), all_clocks)?; let (_ack, s) = s.recv(all_clocks)?; let s = s.send(random(), all_clocks)?; s.close() } else { let s: EndpointCNo = choose_mpst_c_to_all!( s, all_clocks, Branching1fromCtoA::No, Branching1fromCtoS::No, ); let s = s.send(0, all_clocks)?; let s = s.send(random(), all_clocks)?; s.close() } } fn endpoint_s(s: EndpointS, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); offer_mpst!(s, all_clocks, { Branching0fromCtoS::Select(s) => { choice_s(s, all_clocks) }, Branching0fromCtoS::Loops(s) => { let (_dummy, s) = s.recv(all_clocks)?; endpoint_s(s, all_clocks) }, }) } fn choice_s(s: ChoiceS, all_clocks: &mut HashMap) -> Result<(), Box> { offer_mpst!(s, all_clocks, { Branching1fromCtoS::Yes(s) => { let (_yes, s) = s.recv(all_clocks)?; let (payment, s) = s.recv(all_clocks)?; let s = s.send(payment, all_clocks)?; s.close() }, Branching1fromCtoS::No(s) => { let (_no, s) = s.recv(all_clocks)?; s.close() }, }) } fn main() { let (thread_a, thread_c, thread_s) = fork_mpst(endpoint_a, endpoint_c, endpoint_s); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); }