#![allow( clippy::large_enum_variant, clippy::type_complexity, clippy::too_many_arguments )] use criterion::{black_box, criterion_group, criterion_main, Criterion}; use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use mpstthree::{ bundle_struct_fork_close_multi, choose_mpst_multi_to_all, create_multiple_normal_name, create_multiple_normal_role, create_recv_mpst_session_bundle, create_send_mpst_session_bundle, offer_mpst, }; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use std::error::Error; // See the folder scribble_protocols for the related Scribble protocol // Create the new MeshedChannels for three participants and the close and fork functions bundle_struct_fork_close_multi!(close_mpst_multi, fork_mpst, MeshedChannels, 3); // Create new roles // normal create_multiple_normal_role!( RoleA, RoleADual | RoleC, RoleCDual | RoleS, RoleSDual | ); // Create new names create_multiple_normal_name!(NameA, NameC, NameS); // Create new send functions // A create_send_mpst_session_bundle!( send_mpst_a_to_c, RoleC, 1 | send_mpst_a_to_s, RoleS, 2 | => NameA, MeshedChannels, 3 ); // C create_send_mpst_session_bundle!( send_mpst_c_to_a, RoleA, 1 | send_mpst_c_to_s, RoleS, 2 | => NameC, MeshedChannels, 3 ); // S create_send_mpst_session_bundle!( send_mpst_s_to_c, RoleC, 2 | => NameS, MeshedChannels, 3 ); // Create new recv functions and related types // A create_recv_mpst_session_bundle!( recv_mpst_a_from_c, RoleC, 1 | => NameA, MeshedChannels, 3 ); // C create_recv_mpst_session_bundle!( recv_mpst_c_from_a, RoleA, 1 | recv_mpst_c_from_s, RoleS, 2 | => NameC, MeshedChannels, 3 ); // S create_recv_mpst_session_bundle!( recv_mpst_s_from_a, RoleA, 1 | recv_mpst_s_from_c, RoleC, 2 | => NameS, MeshedChannels, 3 ); // Types // A type Choose0fromAtoS = ::Dual; type Choose0fromAtoC = ::Dual; enum Branching1fromCtoA { Pay(MeshedChannels, NameA>), Quit(MeshedChannels), } type Recurs1AtoC = Recv; // S enum Branching0fromAtoS { Login( MeshedChannels< Recv<(), End>, Send<(i64, i64), Recurs1StoC>, RoleA>>, NameS, >, ), Fail(MeshedChannels, End, RoleA, NameS>), } type Recurs0StoA = Recv; enum Branching1fromCtoS { Pay( MeshedChannels< End, Recv<(String, i64), Send<(i64, i64), Recurs1StoC>>, RoleC>>, NameS, >, ), Quit(MeshedChannels, RoleC, NameS>), } type Recurs1StoC = Recv; // C enum Branching0fromAtoC { Login( MeshedChannels< Recv<(), Choose1fromCtoA>, Recv<(i64, i64), Choose1fromCtoS>, RoleA>, NameC, >, ), Fail(MeshedChannels, End, RoleA, NameC>), } type Recurs0CtoA = Recv; type Choose1fromCtoA = ::Dual; type Choose1fromCtoS = ::Dual; // Creating the MP sessions // Step 1 type EndpointA1 = MeshedChannels, NameA>; type EndpointC1 = MeshedChannels, RoleS, NameC>; type EndpointS1 = MeshedChannels, RoleC>, NameS>; // Step 0 type EndpointA0 = MeshedChannels< Recv<(String, String), Choose0fromAtoC>, Choose0fromAtoS, RoleC, NameA, >; type EndpointC0 = MeshedChannels, End, RoleA>, NameC>; type EndpointS0 = MeshedChannels, NameS>; // Functions fn endpoint_a(s: EndpointA0) -> Result<(), Box> { let ((id, pw), s) = recv_mpst_a_from_c(s)?; if id != pw { let s = choose_mpst_multi_to_all!( s, Branching0fromAtoC::Fail, Branching0fromAtoS::Fail, => NameA, MeshedChannels, 1 ); let s = send_mpst_a_to_c("Fail".to_string(), s); let s = send_mpst_a_to_s("Fail".to_string(), s); close_mpst_multi(s) } else { let s = choose_mpst_multi_to_all!( s, Branching0fromAtoC::Login, Branching0fromAtoS::Login, => NameA, MeshedChannels, 1 ); let s = send_mpst_a_to_c((), s); let s = send_mpst_a_to_s((), s); recurs_a(s) } } fn recurs_a(s: EndpointA1) -> Result<(), Box> { offer_mpst!(s, recv_mpst_a_from_c, { Branching1fromCtoA::Quit(s) => { close_mpst_multi(s) }, Branching1fromCtoA::Pay(s) => { recurs_a(s) }, }) } fn endpoint_s(s: EndpointS0) -> Result<(), Box> { offer_mpst!(s, recv_mpst_s_from_a, { Branching0fromAtoS::Fail(s) => { let (_, s) = recv_mpst_s_from_a(s)?; close_mpst_multi(s) }, Branching0fromAtoS::Login(s) => { let (_, s) = recv_mpst_s_from_a(s)?; recurs_s(s) }, }) } fn recurs_s(s: EndpointS1) -> Result<(), Box> { let s = send_mpst_s_to_c( ( thread_rng().gen_range(1..=100) as i64, thread_rng().gen_range(1..=100) as i64, ), s, ); offer_mpst!(s, recv_mpst_s_from_c, { Branching1fromCtoS::Quit(s) => { let (_, s) = recv_mpst_s_from_c(s)?; close_mpst_multi(s) }, Branching1fromCtoS::Pay(s) => { let (_, s) = recv_mpst_s_from_c(s)?; recurs_s(s) }, }) } fn endpoint_c(s: EndpointC0) -> Result<(), Box> { let id = String::from("id"); let pw = String::from("pw"); let s = send_mpst_c_to_a((id, pw), s); offer_mpst!(s, recv_mpst_c_from_a, { Branching0fromAtoC::Fail(s) => { let (_, s) = recv_mpst_c_from_a(s)?; close_mpst_multi(s) }, Branching0fromAtoC::Login(s) => { let (_, s) = recv_mpst_c_from_a(s)?; recurs_c(s, 100) }, }) } fn recurs_c(s: EndpointC1, loops: i32) -> Result<(), Box> { let ((balance, overdraft), s) = recv_mpst_c_from_s(s)?; match loops { 0 => { let s = choose_mpst_multi_to_all!( s, Branching1fromCtoA::Quit, Branching1fromCtoS::Quit, => NameC, MeshedChannels, 2 ); let s = send_mpst_c_to_s((), s); close_mpst_multi(s) } _ => { let s = choose_mpst_multi_to_all!( s, Branching1fromCtoA::Pay, Branching1fromCtoS::Pay, => NameC, MeshedChannels, 2 ); let payee: String = rand::thread_rng() .sample_iter(&Alphanumeric) .take(3) .map(char::from) .collect(); let s = send_mpst_c_to_s((payee, balance + overdraft), s); recurs_c(s, loops - 1) } } } fn aux() { let (thread_a, thread_s, thread_c) = fork_mpst( black_box(endpoint_a), black_box(endpoint_c), black_box(endpoint_s), ); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); } ///////////////////////// pub fn online_wallet(c: &mut Criterion) { c.bench_function("Online wallet basic", |b| b.iter(aux)); } ///////////////////////// criterion_group! { name = bench; config = Criterion::default().significance_level(0.05).without_plots().sample_size(100000); targets = online_wallet, } criterion_main! { bench }