diff --git a/.circleci/config.yml b/.circleci/config.yml index d06abe5e..2b06455a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -115,7 +115,7 @@ commands: environment: RUST_BACKTRACE: 1 command: | - cargo test -- --test-threads=1 + cargo test --release -- --test-threads=1 workflows: version: 2 diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 95e3cf68..c1f21ee4 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -24,4 +24,5 @@ cfg-if = "1.0.0" assert_fs = "1.0" [features] -non-functional = [] +load-tests = [] +soak-tests = [] \ No newline at end of file diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index b56f75c5..66946d5e 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -2,7 +2,7 @@ cfg_if::cfg_if! { if #[cfg(test)] { pub mod setup; pub mod public; - #[cfg(feature = "non-functional")] + pub mod private; pub mod non_functional; } } @@ -24,3 +24,10 @@ pub enum Error { #[error("iapyx error")] IapyxError(#[from] iapyx::ControllerError), } + +#[allow(dead_code)] +pub enum Vote { + BLANK = 0, + YES = 1, + NO = 2, +} diff --git a/integration-tests/src/non_functional/load.rs b/integration-tests/src/non_functional/load.rs new file mode 100644 index 00000000..71dd2b61 --- /dev/null +++ b/integration-tests/src/non_functional/load.rs @@ -0,0 +1,132 @@ +use crate::non_functional::build_load_config; +use crate::non_functional::private_vote_test_scenario; +use crate::setup::vitup_setup; +use assert_fs::TempDir; +use iapyx::{IapyxLoad, Protocol}; +use jormungandr_testing_utils::testing::node::time; +use jortestkit::measurement::Status; +use vit_servicing_station_tests::common::data::ArbitraryValidVotingTemplateGenerator; +use vitup::scenario::network::setup_network; +use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; + +#[tokio::test] +pub async fn load_test_public_100_000_votes() { + let testing_directory = TempDir::new().unwrap().into_persistent(); + let endpoint = "127.0.0.1:8080"; + + let no_of_votes = 100_000; + let no_of_threads = 10; + let no_of_wallets = 4_000; + + let mut quick_setup = QuickVitBackendSettingsBuilder::new(); + quick_setup + .initials_count(no_of_wallets, "1234") + .vote_start_epoch(0) + .tally_start_epoch(3) + .tally_end_epoch(4) + .slot_duration_in_seconds(2) + .slots_in_epoch_count(60) + .proposals_count(250) + .voting_power(31_000) + .private(false); + + let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); + let (mut vit_controller, mut controller, vit_parameters, fund_name) = + vitup_setup(quick_setup, testing_directory.path().to_path_buf()); + + let (nodes, vit_station, wallet_proxy) = setup_network( + &mut controller, + &mut vit_controller, + vit_parameters, + &mut template_generator, + endpoint.to_string(), + &Protocol::Http, + ) + .unwrap(); + + let mut qr_codes_folder = testing_directory.path().to_path_buf(); + qr_codes_folder.push("vit_backend/qr-codes"); + + let config = build_load_config(endpoint, qr_codes_folder, no_of_threads, no_of_votes); + let iapyx_load = IapyxLoad::new(config); + if let Some(benchmark) = iapyx_load.start().unwrap() { + assert!(benchmark.status() == Status::Green, "too low efficiency"); + } + + println!( + "{:?}", + nodes + .get(0) + .unwrap() + .explorer() + .status() + .unwrap() + .data + .unwrap() + .status + ); + + time::wait_for_epoch(10, nodes.get(0).unwrap().explorer()); + + let mut committee = controller.wallet("committee").unwrap(); + let vote_plan = controller.vote_plan(&fund_name).unwrap(); + + controller + .fragment_sender() + .send_public_vote_tally(&mut committee, &vote_plan.into(), nodes.get(0).unwrap()) + .unwrap(); + + vit_station.shutdown(); + wallet_proxy.shutdown(); + for node in nodes { + node.logger() + .assert_no_errors(&format!("Errors in logs for node: {}", node.alias())); + node.shutdown().unwrap(); + } + + controller.finalize(); +} + +#[tokio::test] +pub async fn load_test_private_pesimistic() { + let no_of_votes = 30_000; + let no_of_threads = 10; + let no_of_wallets = 4_000; + let endpoint = "127.0.0.1:8080"; + + let mut quick_setup = QuickVitBackendSettingsBuilder::new(); + quick_setup + .initials_count(no_of_wallets, "1234") + .vote_start_epoch(0) + .tally_start_epoch(3) + .tally_end_epoch(4) + .slot_duration_in_seconds(2) + .slots_in_epoch_count(60) + .proposals_count(250) + .voting_power(31_000) + .private(true); + + private_vote_test_scenario(quick_setup, endpoint, no_of_votes, no_of_threads); +} + +#[tokio::test] +pub async fn load_test_private_optimistic() { + let no_of_votes = 100_000; + let no_of_threads = 10; + let no_of_wallets = 20_000; + let endpoint = "127.0.0.1:8080"; + + let mut quick_setup = QuickVitBackendSettingsBuilder::new(); + quick_setup + .initials_count(no_of_wallets, "1234") + .vote_start_epoch(0) + .tally_start_epoch(6) + .tally_end_epoch(7) + .slot_duration_in_seconds(2) + .slots_in_epoch_count(60) + .proposals_count(250) + .voting_power(31_000) + .private(true); + + private_vote_test_scenario(quick_setup, endpoint, no_of_votes, no_of_threads); +} diff --git a/integration-tests/src/non_functional/load_test.rs b/integration-tests/src/non_functional/load_test.rs deleted file mode 100644 index c2c07562..00000000 --- a/integration-tests/src/non_functional/load_test.rs +++ /dev/null @@ -1,223 +0,0 @@ -use assert_fs::TempDir; -use iapyx::{IapyxLoad, IapyxLoadConfig, Protocol}; -use jormungandr_scenario_tests::prepare_command; -use jormungandr_scenario_tests::scenario::Controller; -use jormungandr_scenario_tests::Context; -use jormungandr_testing_utils::testing::{network_builder::Seed, node::time}; -use jortestkit::prelude::*; -use jortestkit::{ - load::{Configuration, Monitor}, - measurement::Status, -}; -use std::path::Path; -use std::path::PathBuf; -use std::str::FromStr; -use vit_servicing_station_tests::common::data::ArbitraryValidVotingTemplateGenerator; -use vit_servicing_station_tests::common::data::ValidVotePlanParameters; -use vitup::scenario::controller::VitController; -use vitup::scenario::network::setup_network; -use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; - -#[test] -pub fn load_test_public_100_000_votes() { - let endpoint = "127.0.0.1:8080"; - let testing_directory = TempDir::new().unwrap().into_persistent(); - let no_of_votes = 100_000; - let no_of_threads = 5; - let no_of_wallets = 3_000; - - let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); - let (mut vit_controller, mut controller, vit_parameters, _fund_name) = - vitup_setup(false, no_of_wallets, testing_directory.path().to_path_buf()); - - let (nodes, vit_station, wallet_proxy) = setup_network( - &mut controller, - &mut vit_controller, - vit_parameters, - &mut template_generator, - endpoint.to_string(), - &Protocol::Http, - ) - .unwrap(); - - let mut qr_codes_folder = testing_directory.path().to_path_buf(); - qr_codes_folder.push("vit_backend/qr-codes"); - - let config = build_load_config(endpoint, qr_codes_folder, no_of_threads, no_of_votes); - let iapyx_load = IapyxLoad::new(config); - if let Some(benchmark) = iapyx_load.start().unwrap() { - assert!(benchmark.status() == Status::Green, "too low efficiency"); - } - - println!( - "{:?}", - nodes - .get(0) - .unwrap() - .explorer() - .status() - .unwrap() - .data - .unwrap() - .status - ); - - time::wait_for_epoch(10, nodes.get(0).unwrap().explorer()); - - let mut committee = controller.wallet("committee").unwrap(); - let vote_plan = controller.vote_plan(&fund_name).unwrap(); - - controller - .fragment_sender() - .send_public_vote_tally(&mut committee, &vote_plan.into(), nodes.get(0).unwrap()) - .unwrap(); - - vit_station.shutdown(); - wallet_proxy.shutdown(); - for node in nodes { - node.logger() - .assert_no_errors(&format!("Errors in logs for node: {}", node.alias())); - node.shutdown().unwrap(); - } - - controller.finalize(); -} - -#[test] -pub fn load_test_private_30_000_votes() { - let endpoint = "127.0.0.1:8080"; - let testing_directory = TempDir::new().unwrap().into_persistent(); - let no_of_votes = 30_000; - let no_of_threads = 5; - let no_of_wallets = 1_000; - - let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); - let (mut vit_controller, mut controller, vit_parameters, fund_name) = - vitup_setup(true, no_of_wallets, testing_directory.path().to_path_buf()); - let (nodes, vit_station, wallet_proxy) = setup_network( - &mut controller, - &mut vit_controller, - vit_parameters, - &mut template_generator, - endpoint.to_string(), - &Protocol::Http, - ) - .unwrap(); - - let mut qr_codes_folder = testing_directory.path().to_path_buf(); - qr_codes_folder.push("vit_backend/qr-codes"); - - wait_until_folder_contains_all_qrs(no_of_wallets, &qr_codes_folder); - - let config = build_load_config(endpoint, qr_codes_folder, no_of_threads, no_of_votes); - let iapyx_load = IapyxLoad::new(config); - if let Some(benchmark) = iapyx_load.start().unwrap() { - assert!( - benchmark.status() == Status::Green, - "too low efficiency {:?} [{:?}]", - benchmark.efficiency(), - benchmark.definition().thresholds() - ); - } - - time::wait_for_epoch(2, nodes.get(0).unwrap().explorer()); - - let mut committee = controller.wallet("committee").unwrap(); - let vote_plan = controller.vote_plan(&fund_name).unwrap(); - - controller - .fragment_sender() - .send_public_vote_tally(&mut committee, &vote_plan.into(), nodes.get(5).unwrap()) - .unwrap(); - - vit_station.shutdown(); - wallet_proxy.shutdown(); - for node in nodes { - node.logger() - .assert_no_errors(&format!("Errors in logs for node: {}", node.alias())); - node.shutdown().unwrap(); - } - - controller.finalize(); -} - -pub fn wait_until_folder_contains_all_qrs>(qrs_count: usize, folder: P) { - loop { - let qrs = std::fs::read_dir(folder.as_ref()).unwrap(); - if qrs.into_iter().count() < qrs_count { - std::thread::sleep(std::time::Duration::from_secs(5)); - } - } -} - -pub fn vitup_setup( - private: bool, - no_of_wallets: usize, - mut testing_directory: PathBuf, -) -> (VitController, Controller, ValidVotePlanParameters, String) { - let jormungandr = prepare_command(PathBuf::from_str("jormungandr").unwrap()); - let jcli = prepare_command(PathBuf::from_str("jcli").unwrap()); - let seed = Seed::generate(rand::rngs::OsRng); - let generate_documentation = true; - let log_level = "info".to_string(); - - let context = Context::new( - seed, - jormungandr, - jcli, - Some(testing_directory.clone()), - generate_documentation, - ProgressBarMode::Standard, - log_level, - ); - - let mut quick_setup = QuickVitBackendSettingsBuilder::new(); - - quick_setup - .initials_count(no_of_wallets, "1234") - .vote_start_epoch(0) - .tally_start_epoch(20) - .tally_end_epoch(21) - .slot_duration_in_seconds(5) - .slots_in_epoch_count(10) - .proposals_count(1) - .voting_power(8_000) - .private(private); - - testing_directory.push(quick_setup.title()); - if testing_directory.exists() { - std::fs::remove_dir_all(&testing_directory).unwrap(); - } - - let fund_name = quick_setup.fund_name(); - let (vit_controller, controller, vit_parameters) = quick_setup.build(context).unwrap(); - (vit_controller, controller, vit_parameters, fund_name) -} - -fn build_load_config( - address: &str, - qr_codes_folder: PathBuf, - threads_no: usize, - no_of_votes: u32, -) -> IapyxLoadConfig { - let config = Configuration::requests_per_thread( - threads_no, - no_of_votes, - 100, - Monitor::Progress(100), - 60, - ); - - IapyxLoadConfig { - config, - criterion: Some(100), - address: address.to_string(), - wallet_mnemonics_file: None, - qr_codes_folder: Some(qr_codes_folder), - secrets_folder: None, - global_pin: "".to_string(), - read_pin_from_filename: true, - use_https_for_post: false, - debug: true, - } -} diff --git a/integration-tests/src/non_functional/mod.rs b/integration-tests/src/non_functional/mod.rs index c455ec1a..e0c27e9b 100644 --- a/integration-tests/src/non_functional/mod.rs +++ b/integration-tests/src/non_functional/mod.rs @@ -1 +1,110 @@ -pub mod load_test; +#[cfg(feature = "load-tests")] +pub mod load; +#[cfg(feature = "soak-tests")] +pub mod soak; + +use crate::setup::vitup_setup; +use crate::setup::wait_until_folder_contains_all_qrs; +use assert_fs::TempDir; +use iapyx::{IapyxLoad, IapyxLoadConfig, Protocol}; +use jormungandr_testing_utils::testing::node::time; +use jortestkit::{ + load::{Configuration, Monitor}, + measurement::Status, +}; +use std::path::PathBuf; +use vit_servicing_station_tests::common::data::ArbitraryValidVotingTemplateGenerator; +use vitup::scenario::network::setup_network; +use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; + +#[allow(dead_code)] +fn private_vote_test_scenario( + quick_setup: QuickVitBackendSettingsBuilder, + endpoint: &str, + no_of_votes: u32, + no_of_threads: usize, +) { + let testing_directory = TempDir::new().unwrap().into_persistent(); + let wallet_count = quick_setup.parameters().initials.as_ref().unwrap().count(); + + let (mut vit_controller, mut controller, vit_parameters, fund_name) = + vitup_setup(quick_setup, testing_directory.path().to_path_buf()); + + let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); + let (nodes, vit_station, wallet_proxy) = setup_network( + &mut controller, + &mut vit_controller, + vit_parameters, + &mut template_generator, + endpoint.to_string(), + &Protocol::Http, + ) + .unwrap(); + + println!("before qr_codes_folder"); + + let mut qr_codes_folder = testing_directory.path().to_path_buf(); + qr_codes_folder.push("vit_backend/qr-codes"); + + wait_until_folder_contains_all_qrs(wallet_count, &qr_codes_folder); + + let config = build_load_config(endpoint, qr_codes_folder, no_of_threads, no_of_votes); + let iapyx_load = IapyxLoad::new(config); + if let Some(benchmark) = iapyx_load.start().unwrap() { + assert!( + benchmark.status() == Status::Green, + "too low efficiency {:?} [{:?}]", + benchmark.efficiency(), + benchmark.definition().thresholds() + ); + } + + time::wait_for_epoch(2, nodes.get(0).unwrap().explorer()); + + let mut committee = controller.wallet("committee").unwrap(); + let vote_plan = controller.vote_plan(&fund_name).unwrap(); + + controller + .fragment_sender() + .send_public_vote_tally(&mut committee, &vote_plan.into(), nodes.get(5).unwrap()) + .unwrap(); + + vit_station.shutdown(); + wallet_proxy.shutdown(); + for node in nodes { + node.logger() + .assert_no_errors(&format!("Errors in logs for node: {}", node.alias())); + node.shutdown().unwrap(); + } + + controller.finalize(); +} + +#[allow(dead_code)] +fn build_load_config( + address: &str, + qr_codes_folder: PathBuf, + threads_no: usize, + no_of_votes: u32, +) -> IapyxLoadConfig { + let config = Configuration::requests_per_thread( + threads_no, + no_of_votes, + 100, + Monitor::Progress(100), + 60, + ); + + IapyxLoadConfig { + config, + criterion: Some(100), + address: address.to_string(), + wallet_mnemonics_file: None, + qr_codes_folder: Some(qr_codes_folder), + secrets_folder: None, + global_pin: "".to_string(), + read_pin_from_filename: true, + use_https_for_post: false, + debug: true, + } +} diff --git a/integration-tests/src/non_functional/soak.rs b/integration-tests/src/non_functional/soak.rs new file mode 100644 index 00000000..53875b9a --- /dev/null +++ b/integration-tests/src/non_functional/soak.rs @@ -0,0 +1,24 @@ +use crate::non_functional::private_vote_test_scenario; +use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; + +#[test] +pub fn soak_test_private_super_optimistic() { + let no_of_votes = 300_000; + let no_of_threads = 10; + let no_of_wallets = 40_000; + let endpoint = "127.0.0.1:8080"; + + let mut quick_setup = QuickVitBackendSettingsBuilder::new(); + quick_setup + .initials_count(no_of_wallets, "1234") + .vote_start_epoch(0) + .tally_start_epoch(8) + .tally_end_epoch(10) + .slot_duration_in_seconds(2) + .slots_in_epoch_count(60) + .proposals_count(500) + .voting_power(1_500_000) + .private(true); + + private_vote_test_scenario(quick_setup, endpoint, no_of_votes, no_of_threads); +} diff --git a/integration-tests/src/private.rs b/integration-tests/src/private.rs new file mode 100644 index 00000000..132fca26 --- /dev/null +++ b/integration-tests/src/private.rs @@ -0,0 +1,183 @@ +use super::Vote; +use crate::setup::*; +use assert_fs::TempDir; +use chain_impl_mockchain::block::BlockDate; +use chain_impl_mockchain::key::Hash; +use iapyx::Protocol; +use jormungandr_testing_utils::testing::node::time; +use std::path::Path; +use std::str::FromStr; +use tokio; +use vit_servicing_station_tests::common::data::ArbitraryValidVotingTemplateGenerator; +use vitup::config::{InitialEntry, Initials}; +use vitup::scenario::network::setup_network; +use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; + +#[tokio::test] +pub async fn private_vote_e2e_flow() -> std::result::Result<(), crate::Error> { + let endpoint = "127.0.0.1:8080"; + let testing_directory = TempDir::new().unwrap().into_persistent(); + let mut quick_setup = QuickVitBackendSettingsBuilder::new(); + quick_setup + .initials(Initials(vec![ + InitialEntry::Wallet { + name: "david".to_string(), + funds: 10_000, + pin: "1234".to_string(), + }, + InitialEntry::Wallet { + name: "edgar".to_string(), + funds: 10_000, + pin: "1234".to_string(), + }, + InitialEntry::Wallet { + name: "filip".to_string(), + funds: 10_000, + pin: "1234".to_string(), + }, + ])) + .vote_start_epoch(0) + .tally_start_epoch(1) + .tally_end_epoch(2) + .slot_duration_in_seconds(2) + .slots_in_epoch_count(60) + .proposals_count(1) + .voting_power(8_000) + .private(true); + + let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); + let (mut vit_controller, mut controller, vit_parameters, fund_name) = + vitup_setup(quick_setup, testing_directory.path().to_path_buf()); + let (nodes, vit_station, wallet_proxy) = setup_network( + &mut controller, + &mut vit_controller, + vit_parameters, + &mut template_generator, + endpoint.to_string(), + &Protocol::Http, + ) + .unwrap(); + + let mut committee = controller.wallet("committee_1").unwrap(); + + let leader_1 = &nodes[0]; + let wallet_node = &nodes[4]; + + let mut qr_codes_folder = testing_directory.path().to_path_buf(); + qr_codes_folder.push("vit_backend/qr-codes"); + wait_until_folder_contains_all_qrs(3, &qr_codes_folder); + let david_qr_code = Path::new(&qr_codes_folder).join("wallet_david_1234.png"); + let edgar_qr_code = Path::new(&qr_codes_folder).join("wallet_edgar_1234.png"); + let filip_qr_code = Path::new(&qr_codes_folder).join("wallet_filip_1234.png"); + + // start mainnet wallets + let mut david = vit_controller + .iapyx_wallet_from_qr(&david_qr_code, "1234", &wallet_proxy) + .unwrap(); + david.retrieve_funds().unwrap(); + david.convert_and_send().unwrap(); + + let fund1_vote_plan = controller.vote_plan(&fund_name).unwrap(); + + println!( + "Controller: {}: {:?}", + fund1_vote_plan.id(), + fund1_vote_plan + ); + + let vote_plan = &leader_1.vote_plans().unwrap()[0]; + println!("Blockchain: {:?}", vote_plan); + + // start voting + david + .vote_for(fund1_vote_plan.id(), 0, Vote::YES as u8) + .unwrap(); + + let mut edgar = vit_controller + .iapyx_wallet_from_qr(&edgar_qr_code, "1234", &wallet_proxy) + .unwrap(); + edgar.retrieve_funds().unwrap(); + edgar.convert_and_send().unwrap(); + + edgar + .vote_for(fund1_vote_plan.id(), 0, Vote::YES as u8) + .unwrap(); + + let mut filip = vit_controller + .iapyx_wallet_from_qr(&filip_qr_code, "1234", &wallet_proxy) + .unwrap(); + filip.retrieve_funds().unwrap(); + filip.convert_and_send().unwrap(); + + filip + .vote_for(fund1_vote_plan.id(), 0, Vote::NO as u8) + .unwrap(); + + let target_date = BlockDate { + epoch: 1, + slot_id: 5, + }; + time::wait_for_date(target_date.into(), leader_1.explorer()); + + controller + .fragment_sender() + .send_encrypted_tally(&mut committee, &fund1_vote_plan.clone().into(), wallet_node) + .unwrap(); + + let target_date = BlockDate { + epoch: 1, + slot_id: 30, + }; + time::wait_for_date(target_date.into(), leader_1.explorer()); + + let active_vote_plans = leader_1.vote_plans().unwrap(); + let vote_plan_status = active_vote_plans + .iter() + .find(|c_vote_plan| c_vote_plan.id == Hash::from_str(&fund1_vote_plan.id()).unwrap().into()) + .unwrap(); + + println!("{:?}", active_vote_plans); + + println!("{:?}", leader_1.fragment_logs().unwrap()); + + let shares = controller + .settings() + .private_vote_plans + .get(&fund_name) + .unwrap() + .decrypt_tally(&vote_plan_status.clone().into()); + + controller + .fragment_sender() + .send_private_vote_tally( + &mut committee, + &fund1_vote_plan.clone().into(), + shares, + wallet_node, + ) + .unwrap(); + + time::wait_for_epoch(2, leader_1.explorer()); + + let active_vote_plans = leader_1.vote_plans().unwrap(); + let vote_plan_status = active_vote_plans + .iter() + .find(|c_vote_plan| c_vote_plan.id == Hash::from_str(&fund1_vote_plan.id()).unwrap().into()) + .unwrap(); + + for proposal in vote_plan_status.proposals.iter() { + assert!( + proposal.tally.is_some(), + "Proposal is not tallied {:?}", + proposal + ); + } + + vit_station.shutdown(); + wallet_proxy.shutdown(); + for node in nodes { + node.shutdown()?; + } + controller.finalize(); + Ok(()) +} diff --git a/integration-tests/src/public.rs b/integration-tests/src/public.rs index 0196679d..650d436c 100644 --- a/integration-tests/src/public.rs +++ b/integration-tests/src/public.rs @@ -1,3 +1,4 @@ +use super::Vote; use crate::setup::*; use assert_fs::TempDir; use chain_impl_mockchain::block::BlockDate; @@ -12,13 +13,6 @@ use vitup::config::{InitialEntry, Initials}; use vitup::scenario::network::setup_network; use vitup::setup::start::quick::QuickVitBackendSettingsBuilder; -#[allow(dead_code)] -pub enum Vote { - BLANK = 0, - YES = 1, - NO = 2, -} - #[tokio::test] pub async fn public_vote_e2e_flow() -> std::result::Result<(), crate::Error> { let endpoint = "127.0.0.1:8080"; @@ -146,172 +140,3 @@ pub async fn public_vote_e2e_flow() -> std::result::Result<(), crate::Error> { controller.finalize(); Ok(()) } - -#[tokio::test] -pub async fn private_vote_e2e_flow() -> std::result::Result<(), crate::Error> { - let endpoint = "127.0.0.1:8080"; - let testing_directory = TempDir::new().unwrap().into_persistent(); - let mut quick_setup = QuickVitBackendSettingsBuilder::new(); - quick_setup - .initials(Initials(vec![ - InitialEntry::Wallet { - name: "david".to_string(), - funds: 10_000, - pin: "1234".to_string(), - }, - InitialEntry::Wallet { - name: "edgar".to_string(), - funds: 10_000, - pin: "1234".to_string(), - }, - InitialEntry::Wallet { - name: "filip".to_string(), - funds: 10_000, - pin: "1234".to_string(), - }, - ])) - .vote_start_epoch(0) - .tally_start_epoch(1) - .tally_end_epoch(2) - .slot_duration_in_seconds(2) - .slots_in_epoch_count(60) - .proposals_count(1) - .voting_power(8_000) - .private(true); - - let mut template_generator = ArbitraryValidVotingTemplateGenerator::new(); - let (mut vit_controller, mut controller, vit_parameters, fund_name) = - vitup_setup(quick_setup, testing_directory.path().to_path_buf()); - let (nodes, vit_station, wallet_proxy) = setup_network( - &mut controller, - &mut vit_controller, - vit_parameters, - &mut template_generator, - endpoint.to_string(), - &Protocol::Http, - ) - .unwrap(); - - let mut committee = controller.wallet("committee_1").unwrap(); - - let leader_1 = &nodes[0]; - let wallet_node = &nodes[4]; - - let mut qr_codes_folder = testing_directory.path().to_path_buf(); - qr_codes_folder.push("vit_backend/qr-codes"); - wait_until_folder_contains_all_qrs(3, &qr_codes_folder); - let david_qr_code = Path::new(&qr_codes_folder).join("wallet_david_1234.png"); - let edgar_qr_code = Path::new(&qr_codes_folder).join("wallet_edgar_1234.png"); - let filip_qr_code = Path::new(&qr_codes_folder).join("wallet_filip_1234.png"); - - // start mainnet wallets - let mut david = vit_controller - .iapyx_wallet_from_qr(&david_qr_code, "1234", &wallet_proxy) - .unwrap(); - david.retrieve_funds().unwrap(); - david.convert_and_send().unwrap(); - - let fund1_vote_plan = controller.vote_plan(&fund_name).unwrap(); - - println!( - "Controller: {}: {:?}", - fund1_vote_plan.id(), - fund1_vote_plan - ); - - let vote_plan = &leader_1.vote_plans().unwrap()[0]; - println!("Blockchain: {:?}", vote_plan); - - // start voting - david - .vote_for(fund1_vote_plan.id(), 0, Vote::YES as u8) - .unwrap(); - - let mut edgar = vit_controller - .iapyx_wallet_from_qr(&edgar_qr_code, "1234", &wallet_proxy) - .unwrap(); - edgar.retrieve_funds().unwrap(); - edgar.convert_and_send().unwrap(); - - edgar - .vote_for(fund1_vote_plan.id(), 0, Vote::YES as u8) - .unwrap(); - - let mut filip = vit_controller - .iapyx_wallet_from_qr(&filip_qr_code, "1234", &wallet_proxy) - .unwrap(); - filip.retrieve_funds().unwrap(); - filip.convert_and_send().unwrap(); - - filip - .vote_for(fund1_vote_plan.id(), 0, Vote::NO as u8) - .unwrap(); - - let target_date = BlockDate { - epoch: 1, - slot_id: 5, - }; - time::wait_for_date(target_date.into(), leader_1.explorer()); - - controller - .fragment_sender() - .send_encrypted_tally(&mut committee, &fund1_vote_plan.clone().into(), wallet_node) - .unwrap(); - - let target_date = BlockDate { - epoch: 1, - slot_id: 30, - }; - time::wait_for_date(target_date.into(), leader_1.explorer()); - - let active_vote_plans = leader_1.vote_plans().unwrap(); - let vote_plan_status = active_vote_plans - .iter() - .find(|c_vote_plan| c_vote_plan.id == Hash::from_str(&fund1_vote_plan.id()).unwrap().into()) - .unwrap(); - - println!("{:?}", active_vote_plans); - - println!("{:?}", leader_1.fragment_logs().unwrap()); - - let shares = controller - .settings() - .private_vote_plans - .get(&fund_name) - .unwrap() - .decrypt_tally(&vote_plan_status.clone().into()); - - controller - .fragment_sender() - .send_private_vote_tally( - &mut committee, - &fund1_vote_plan.clone().into(), - shares, - wallet_node, - ) - .unwrap(); - - time::wait_for_epoch(2, leader_1.explorer()); - - let active_vote_plans = leader_1.vote_plans().unwrap(); - let vote_plan_status = active_vote_plans - .iter() - .find(|c_vote_plan| c_vote_plan.id == Hash::from_str(&fund1_vote_plan.id()).unwrap().into()) - .unwrap(); - - for proposal in vote_plan_status.proposals.iter() { - assert!( - proposal.tally.is_some(), - "Proposal is not tallied {:?}", - proposal - ); - } - - vit_station.shutdown(); - wallet_proxy.shutdown(); - for node in nodes { - node.shutdown()?; - } - controller.finalize(); - Ok(()) -} diff --git a/integration-tests/src/setup.rs b/integration-tests/src/setup.rs index 272ab07b..03fa4cdd 100644 --- a/integration-tests/src/setup.rs +++ b/integration-tests/src/setup.rs @@ -37,7 +37,7 @@ pub fn context(testing_directory: &PathBuf) -> Context { jcli, Some(testing_directory.clone()), generate_documentation, - ProgressBarMode::Standard, + ProgressBarMode::None, log_level, ) } @@ -56,7 +56,7 @@ pub fn vitup_setup_default( .tally_end_epoch(21) .slot_duration_in_seconds(5) .slots_in_epoch_count(10) - .proposals_count(1) + .proposals_count(100) .voting_power(8_000) .private(private); diff --git a/vitup/src/config/initials.rs b/vitup/src/config/initials.rs index f4172981..13c530e6 100644 --- a/vitup/src/config/initials.rs +++ b/vitup/src/config/initials.rs @@ -59,6 +59,26 @@ impl Initials { 0 } + pub fn count(&self) -> usize { + let mut sum = 0; + for initial in self.0.iter() { + match initial { + Initial::ZeroFunds { zero_funds, pin: _ } => sum += *zero_funds, + Initial::BelowThreshold { + below_threshold, + pin: _, + } => sum += below_threshold, + Initial::AboveThreshold { + above_threshold, + pin: _, + } => sum += above_threshold, + Initial::Wallet { .. } => sum += 1, + _ => {} + } + } + sum + } + pub fn zero_funds_pin(&self) -> Option { for initial in self.0.iter() { if let Initial::ZeroFunds { zero_funds: _, pin } = initial {