diff --git a/masq_lib/src/constants.rs b/masq_lib/src/constants.rs index 4b7720c70..1371c0b63 100644 --- a/masq_lib/src/constants.rs +++ b/masq_lib/src/constants.rs @@ -5,7 +5,7 @@ use crate::data_version::DataVersion; use const_format::concatcp; pub const DEFAULT_CHAIN: Chain = Chain::PolyMainnet; -pub const CURRENT_SCHEMA_VERSION: usize = 7; +pub const CURRENT_SCHEMA_VERSION: usize = 8; pub const HIGHEST_RANDOM_CLANDESTINE_PORT: u16 = 9999; pub const HTTP_PORT: u16 = 80; diff --git a/masq_lib/src/logger.rs b/masq_lib/src/logger.rs index 455d0f574..b5fe282c8 100644 --- a/masq_lib/src/logger.rs +++ b/masq_lib/src/logger.rs @@ -1,10 +1,9 @@ use std::fmt::{Debug, Formatter}; // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::constants::CURRENT_SCHEMA_VERSION; use crate::constants::{ CLIENT_REQUEST_PAYLOAD_CURRENT_VERSION, CLIENT_RESPONSE_PAYLOAD_CURRENT_VERSION, - DNS_RESOLVER_FAILURE_CURRENT_VERSION, GOSSIP_CURRENT_VERSION, GOSSIP_FAILURE_CURRENT_VERSION, - NODE_RECORD_INNER_CURRENT_VERSION, + CURRENT_SCHEMA_VERSION, DNS_RESOLVER_FAILURE_CURRENT_VERSION, GOSSIP_CURRENT_VERSION, + GOSSIP_FAILURE_CURRENT_VERSION, NODE_RECORD_INNER_CURRENT_VERSION, }; use crate::data_version::DataVersion; use crate::messages::SerializableLogLevel; diff --git a/masq_lib/src/shared_schema.rs b/masq_lib/src/shared_schema.rs index 97734cd91..01cbbed5e 100644 --- a/masq_lib/src/shared_schema.rs +++ b/masq_lib/src/shared_schema.rs @@ -431,7 +431,6 @@ pub fn shared_app(head: App<'static, 'static>) -> App<'static, 'static> { Arg::with_name("min-hops") .long("min-hops") .value_name("MIN_HOPS") - .default_value("3") .required(false) .min_values(0) .max_values(1) diff --git a/multinode_integration_tests/src/masq_real_node.rs b/multinode_integration_tests/src/masq_real_node.rs index dbc547e93..2963bf08d 100644 --- a/multinode_integration_tests/src/masq_real_node.rs +++ b/multinode_integration_tests/src/masq_real_node.rs @@ -15,7 +15,7 @@ use masq_lib::test_utils::utils::TEST_DEFAULT_MULTINODE_CHAIN; use masq_lib::utils::localhost; use masq_lib::utils::{DEFAULT_CONSUMING_DERIVATION_PATH, DEFAULT_EARNING_DERIVATION_PATH}; use node_lib::blockchain::bip32::Bip32ECKeyProvider; -use node_lib::neighborhood::DEFAULT_MIN_HOPS_COUNT; +use node_lib::neighborhood::DEFAULT_MIN_HOPS; use node_lib::sub_lib::accountant::{ PaymentThresholds, DEFAULT_EARNING_WALLET, DEFAULT_PAYMENT_THRESHOLDS, }; @@ -114,7 +114,7 @@ pub fn make_consuming_wallet_info(token: &str) -> ConsumingWalletInfo { #[derive(PartialEq, Eq, Clone, Debug)] pub struct NodeStartupConfig { pub neighborhood_mode: String, - pub min_hops_count: Hops, + pub min_hops: Hops, pub ip_info: LocalIpInfo, pub dns_servers_opt: Option>, pub neighbors: Vec, @@ -146,7 +146,7 @@ impl NodeStartupConfig { pub fn new() -> NodeStartupConfig { NodeStartupConfig { neighborhood_mode: "standard".to_string(), - min_hops_count: DEFAULT_MIN_HOPS_COUNT, + min_hops: DEFAULT_MIN_HOPS, ip_info: LocalIpInfo::ZeroHop, dns_servers_opt: None, neighbors: Vec::new(), @@ -179,7 +179,7 @@ impl NodeStartupConfig { args.push("--neighborhood-mode".to_string()); args.push(self.neighborhood_mode.clone()); args.push("--min-hops".to_string()); - args.push(format!("{}", self.min_hops_count as usize)); + args.push(format!("{}", self.min_hops as usize)); if let LocalIpInfo::DistributedKnown(ip_addr) = self.ip_info { args.push("--ip".to_string()); args.push(ip_addr.to_string()); @@ -409,7 +409,7 @@ impl NodeStartupConfig { pub struct NodeStartupConfigBuilder { neighborhood_mode: String, - min_hops_count: Hops, + min_hops: Hops, ip_info: LocalIpInfo, dns_servers_opt: Option>, neighbors: Vec, @@ -465,7 +465,7 @@ impl NodeStartupConfigBuilder { pub fn standard() -> Self { Self { neighborhood_mode: "standard".to_string(), - min_hops_count: DEFAULT_MIN_HOPS_COUNT, + min_hops: DEFAULT_MIN_HOPS, ip_info: LocalIpInfo::DistributedUnknown, dns_servers_opt: None, neighbors: vec![], @@ -491,7 +491,7 @@ impl NodeStartupConfigBuilder { pub fn copy(config: &NodeStartupConfig) -> Self { Self { neighborhood_mode: config.neighborhood_mode.clone(), - min_hops_count: config.min_hops_count, + min_hops: config.min_hops, ip_info: config.ip_info, dns_servers_opt: config.dns_servers_opt.clone(), neighbors: config.neighbors.clone(), @@ -530,8 +530,8 @@ impl NodeStartupConfigBuilder { } } - pub fn min_hops_count(mut self, value: Hops) -> Self { - self.min_hops_count = value; + pub fn min_hops(mut self, value: Hops) -> Self { + self.min_hops = value; self } @@ -648,7 +648,7 @@ impl NodeStartupConfigBuilder { pub fn build(self) -> NodeStartupConfig { NodeStartupConfig { neighborhood_mode: self.neighborhood_mode, - min_hops_count: self.min_hops_count, + min_hops: self.min_hops, ip_info: self.ip_info, dns_servers_opt: self.dns_servers_opt, neighbors: self.neighbors, @@ -1304,7 +1304,7 @@ mod tests { #[test] fn node_startup_config_builder_settings() { - let min_hops_count = Hops::SixHops; + let min_hops = Hops::SixHops; let ip_addr = IpAddr::from_str("1.2.3.4").unwrap(); let one_neighbor_key = PublicKey::new(&[1, 2, 3, 4]); let one_neighbor_ip_addr = IpAddr::from_str("4.5.6.7").unwrap(); @@ -1333,7 +1333,7 @@ mod tests { let dns_target = IpAddr::from_str("8.9.10.11").unwrap(); let result = NodeStartupConfigBuilder::standard() - .min_hops_count(min_hops_count) + .min_hops(min_hops) .ip(ip_addr) .dns_servers(dns_servers.clone()) .neighbor(neighbors[0].clone()) @@ -1342,7 +1342,7 @@ mod tests { .dns_port(35) .build(); - assert_eq!(result.min_hops_count, min_hops_count); + assert_eq!(result.min_hops, min_hops); assert_eq!(result.ip_info, LocalIpInfo::DistributedKnown(ip_addr)); assert_eq!(result.dns_servers_opt, Some(dns_servers)); assert_eq!(result.neighbors, neighbors); @@ -1355,7 +1355,7 @@ mod tests { fn node_startup_config_builder_copy() { let original = NodeStartupConfig { neighborhood_mode: "consume-only".to_string(), - min_hops_count: Hops::TwoHops, + min_hops: Hops::TwoHops, ip_info: LocalIpInfo::DistributedUnknown, dns_servers_opt: Some(vec![IpAddr::from_str("255.255.255.255").unwrap()]), neighbors: vec![NodeReference::new( @@ -1434,7 +1434,7 @@ mod tests { .build(); assert_eq!(result.neighborhood_mode, neighborhood_mode); - assert_eq!(result.min_hops_count, Hops::TwoHops); + assert_eq!(result.min_hops, Hops::TwoHops); assert_eq!(result.ip_info, LocalIpInfo::DistributedKnown(ip_addr)); assert_eq!(result.dns_servers_opt, Some(dns_servers)); assert_eq!(result.neighbors, neighbors); @@ -1501,7 +1501,7 @@ mod tests { let subject = NodeStartupConfigBuilder::standard() .neighborhood_mode("consume-only") - .min_hops_count(Hops::SixHops) + .min_hops(Hops::SixHops) .ip(IpAddr::from_str("1.3.5.7").unwrap()) .neighbor(one_neighbor.clone()) .neighbor(another_neighbor.clone()) diff --git a/multinode_integration_tests/tests/data_routing_test.rs b/multinode_integration_tests/tests/data_routing_test.rs index 9b0e5a979..61a6d6281 100644 --- a/multinode_integration_tests/tests/data_routing_test.rs +++ b/multinode_integration_tests/tests/data_routing_test.rs @@ -70,16 +70,16 @@ fn http_end_to_end_routing_test() { ); } -fn assert_http_end_to_end_routing_test(min_hops_count: Hops) { +fn assert_http_end_to_end_routing_test(min_hops: Hops) { let mut cluster = MASQNodeCluster::start().unwrap(); let config = NodeStartupConfigBuilder::standard() - .min_hops_count(min_hops_count) + .min_hops(min_hops) .chain(cluster.chain) .consuming_wallet_info(make_consuming_wallet_info("first_node")) .build(); let first_node = cluster.start_real_node(config); - let nodes_count = 2 * (min_hops_count as usize) + 1; + let nodes_count = 2 * (min_hops as usize) + 1; let nodes = (0..nodes_count) .map(|_| { cluster.start_real_node( @@ -106,7 +106,7 @@ fn assert_http_end_to_end_routing_test(min_hops_count: Hops) { } #[test] -fn http_end_to_end_routing_test_with_different_min_hops_count() { +fn http_end_to_end_routing_test_with_different_min_hops() { // This test fails sometimes due to a timeout: "Couldn't read chunk: Kind(TimedOut)" // You may fix it by increasing the timeout for the client. assert_http_end_to_end_routing_test(Hops::OneHop); diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index 5265286bf..8ea9c7646 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -642,7 +642,7 @@ mod tests { use crate::sub_lib::ui_gateway::UiGatewayConfig; use crate::test_utils::automap_mocks::{AutomapControlFactoryMock, AutomapControlMock}; use crate::test_utils::make_wallet; - use crate::test_utils::neighborhood_test_utils::MIN_HOPS_COUNT_FOR_TEST; + use crate::test_utils::neighborhood_test_utils::MIN_HOPS_FOR_TEST; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::{ make_accountant_subs_from_recorder, make_blockchain_bridge_subs_from, @@ -1084,13 +1084,14 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, payment_thresholds_opt: Some(PaymentThresholds::default()), when_pending_too_long_sec: DEFAULT_PENDING_TOO_LONG_SEC, }; - let persistent_config = - PersistentConfigurationMock::default().chain_name_result("eth-ropsten".to_string()); + let persistent_config = PersistentConfigurationMock::default() + .chain_name_result("eth-ropsten".to_string()) + .set_min_hops_result(Ok(())); Bootstrapper::pub_initialize_cryptdes_for_testing( &Some(main_cryptde()), &Some(alias_cryptde()), @@ -1158,7 +1159,7 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, payment_thresholds_opt: Default::default(), when_pending_too_long_sec: DEFAULT_PENDING_TOO_LONG_SEC @@ -1276,6 +1277,7 @@ mod tests { let mut config = BootstrapperConfig::default(); config.neighborhood_config = NeighborhoodConfig { mode: NeighborhoodMode::ConsumeOnly(vec![]), + min_hops: MIN_HOPS_FOR_TEST, }; let subject = ActorSystemFactoryToolsReal::new(); let state_before = INITIALIZATION_COUNTER.lock().unwrap().0; @@ -1302,7 +1304,7 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let make_params_arc = Arc::new(Mutex::new(vec![])); let mut subject = make_subject_with_null_setter(); @@ -1456,7 +1458,7 @@ mod tests { real_user: RealUser::null(), neighborhood_config: NeighborhoodConfig { mode: NeighborhoodMode::ConsumeOnly(vec![]), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, payment_thresholds_opt: Default::default(), when_pending_too_long_sec: DEFAULT_PENDING_TOO_LONG_SEC @@ -1468,7 +1470,7 @@ mod tests { let _ = subject.prepare_initial_messages( make_cryptde_pair(), config.clone(), - Box::new(PersistentConfigurationMock::new()), + Box::new(PersistentConfigurationMock::new().set_min_hops_result(Ok(()))), Box::new(actor_factory), ); @@ -1645,7 +1647,7 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, node_descriptor: Default::default(), payment_thresholds_opt: Default::default(), @@ -1657,7 +1659,7 @@ mod tests { let _ = subject.prepare_initial_messages( make_cryptde_pair(), config.clone(), - Box::new(PersistentConfigurationMock::new()), + Box::new(PersistentConfigurationMock::new().set_min_hops_result(Ok(()))), Box::new(actor_factory), ); diff --git a/node/src/bootstrapper.rs b/node/src/bootstrapper.rs index 533c9cb41..316d5a914 100644 --- a/node/src/bootstrapper.rs +++ b/node/src/bootstrapper.rs @@ -15,7 +15,7 @@ use crate::json_discriminator_factory::JsonDiscriminatorFactory; use crate::listener_handler::ListenerHandler; use crate::listener_handler::ListenerHandlerFactory; use crate::listener_handler::ListenerHandlerFactoryReal; -use crate::neighborhood::DEFAULT_MIN_HOPS_COUNT; +use crate::neighborhood::DEFAULT_MIN_HOPS; use crate::node_configurator::node_configurator_standard::{ NodeConfiguratorStandardPrivileged, NodeConfiguratorStandardUnprivileged, }; @@ -398,7 +398,7 @@ impl BootstrapperConfig { consuming_wallet_opt: None, neighborhood_config: NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: DEFAULT_MIN_HOPS_COUNT, + min_hops: DEFAULT_MIN_HOPS, }, when_pending_too_long_sec: DEFAULT_PENDING_TOO_LONG_SEC, } @@ -741,7 +741,7 @@ mod tests { use crate::sub_lib::node_addr::NodeAddr; use crate::sub_lib::socket_server::ConfiguredByPrivilege; use crate::sub_lib::stream_connector::ConnectionInfo; - use crate::test_utils::neighborhood_test_utils::MIN_HOPS_COUNT_FOR_TEST; + use crate::test_utils::neighborhood_test_utils::MIN_HOPS_FOR_TEST; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::make_recorder; use crate::test_utils::recorder::RecordAwaiter; @@ -1234,7 +1234,7 @@ mod tests { let clandestine_port_opt = Some(44444); let neighborhood_config = NeighborhoodConfig { mode: NeighborhoodMode::OriginateOnly(vec![], rate_pack(9)), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let earning_wallet = make_wallet("earning wallet"); let consuming_wallet_opt = Some(make_wallet("consuming wallet")); @@ -1853,7 +1853,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; config.data_directory = data_dir.clone(); config.clandestine_port_opt = Some(port); @@ -1923,7 +1923,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; config.data_directory = data_dir.clone(); config.clandestine_port_opt = None; @@ -1972,7 +1972,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let listener_handler = ListenerHandlerNull::new(vec![]); let mut subject = BootstrapperBuilder::new() @@ -2009,7 +2009,7 @@ mod tests { Chain::EthRopsten, cryptde, ))]), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let listener_handler = ListenerHandlerNull::new(vec![]); let mut subject = BootstrapperBuilder::new() @@ -2039,7 +2039,7 @@ mod tests { config.clandestine_port_opt = None; config.neighborhood_config = NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let listener_handler = ListenerHandlerNull::new(vec![]); let mut subject = BootstrapperBuilder::new() @@ -2070,7 +2070,7 @@ mod tests { config.data_directory = data_dir.to_path_buf(); config.neighborhood_config = NeighborhoodConfig { mode: NeighborhoodMode::Standard(NodeAddr::default(), vec![], DEFAULT_RATE_PACK), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let mut subject = BootstrapperBuilder::new().config(config).build(); subject.set_up_clandestine_port(); diff --git a/node/src/daemon/setup_reporter.rs b/node/src/daemon/setup_reporter.rs index d97f080b2..d492e4343 100644 --- a/node/src/daemon/setup_reporter.rs +++ b/node/src/daemon/setup_reporter.rs @@ -11,6 +11,7 @@ use crate::db_config::config_dao_null::ConfigDaoNull; use crate::db_config::persistent_configuration::{ PersistentConfiguration, PersistentConfigurationReal, }; +use crate::neighborhood::DEFAULT_MIN_HOPS; use crate::node_configurator::node_configurator_standard::privileged_parse_args; use crate::node_configurator::unprivileged_parse_args_configuration::{ UnprivilegedParseArgsConfiguration, UnprivilegedParseArgsConfigurationDaoNull, @@ -830,11 +831,44 @@ impl ValueRetriever for MappingProtocol { } } -struct MinHops {} +struct MinHops { + logger: Logger, +} + +impl MinHops { + pub fn new() -> Self { + Self { + logger: Logger::new("MinHops"), + } + } +} + impl ValueRetriever for MinHops { fn value_name(&self) -> &'static str { "min-hops" } + + fn computed_default( + &self, + _bootstrapper_config: &BootstrapperConfig, + persistent_config: &dyn PersistentConfiguration, + _db_password_opt: &Option, + ) -> Option<(String, UiSetupResponseValueStatus)> { + match persistent_config.min_hops() { + Ok(min_hops) => Some(if min_hops == DEFAULT_MIN_HOPS { + (DEFAULT_MIN_HOPS.to_string(), Default) + } else { + (min_hops.to_string(), Configured) + }), + Err(e) => { + error!( + self.logger, + "No value for min hops found in database; database is corrupt: {:?}", e + ); + None + } + } + } } struct NeighborhoodMode {} @@ -1063,7 +1097,7 @@ fn value_retrievers(dirs_wrapper: &dyn DirsWrapper) -> Vec( + &self, + mig_declaration_utilities: Box, + ) -> rusqlite::Result<()> { + let statement = format!( + "INSERT INTO config (name, value, encrypted) VALUES ('min_hops', '{DEFAULT_MIN_HOPS}', 0)", + ); + mig_declaration_utilities.execute_upon_transaction(&[&statement]) + } + + fn old_version(&self) -> usize { + 7 + } +} + +#[cfg(test)] +mod tests { + use crate::database::db_initializer::{ + DbInitializationConfig, DbInitializer, DbInitializerReal, DATABASE_FILE, + }; + use crate::database::db_migrations::db_migrator::DatabaseMigration; + use crate::database::db_migrations::migrations::migration_7_to_8::Migrate_7_to_8; + use crate::neighborhood::DEFAULT_MIN_HOPS; + use crate::test_utils::database_utils::{ + bring_db_0_back_to_life_and_return_connection, make_external_data, retrieve_config_row, + }; + use masq_lib::test_utils::utils::ensure_node_home_directory_exists; + + #[test] + fn old_version_says_7() { + let subject = Migrate_7_to_8 {}; + + let result = subject.old_version(); + + assert_eq!(result, 7); + } + + #[test] + fn migration_from_7_to_8_is_properly_set() { + let start_at = Migrate_7_to_8 {}.old_version(); + let dir_path = ensure_node_home_directory_exists( + "db_migrations", + "migration_from_7_to_8_is_properly_set", + ); + let db_path = dir_path.join(DATABASE_FILE); + let _ = bring_db_0_back_to_life_and_return_connection(&db_path); + let subject = DbInitializerReal::default(); + { + subject + .initialize_to_version(&dir_path, start_at, DbInitializationConfig::test_default()) + .unwrap(); + } + + let result = subject.initialize_to_version( + &dir_path, + start_at + 1, + DbInitializationConfig::create_or_migrate(make_external_data()), + ); + + let connection = result.unwrap(); + let (mhc_value, mhc_encrypted) = retrieve_config_row(connection.as_ref(), "min_hops"); + assert_eq!(mhc_value, Some(DEFAULT_MIN_HOPS.to_string())); + assert_eq!(mhc_encrypted, false); + let (schv_value, schv_encrypted) = + retrieve_config_row(connection.as_ref(), "schema_version"); + assert_eq!(schv_value, Some("8".to_string())); + assert_eq!(schv_encrypted, false); + } +} diff --git a/node/src/database/db_migrations/migrations/mod.rs b/node/src/database/db_migrations/migrations/mod.rs index 69df36eab..bc540b4ae 100644 --- a/node/src/database/db_migrations/migrations/mod.rs +++ b/node/src/database/db_migrations/migrations/mod.rs @@ -7,3 +7,4 @@ pub mod migration_3_to_4; pub mod migration_4_to_5; pub mod migration_5_to_6; pub mod migration_6_to_7; +pub mod migration_7_to_8; diff --git a/node/src/db_config/config_dao_null.rs b/node/src/db_config/config_dao_null.rs index 8e1b37818..e3550da14 100644 --- a/node/src/db_config/config_dao_null.rs +++ b/node/src/db_config/config_dao_null.rs @@ -2,6 +2,7 @@ use crate::database::db_initializer::DbInitializerReal; use crate::db_config::config_dao::{ConfigDao, ConfigDaoError, ConfigDaoRecord}; +use crate::neighborhood::DEFAULT_MIN_HOPS; use crate::sub_lib::accountant::{DEFAULT_PAYMENT_THRESHOLDS, DEFAULT_SCAN_INTERVALS}; use crate::sub_lib::neighborhood::DEFAULT_RATE_PACK; use itertools::Itertools; @@ -108,6 +109,10 @@ impl Default for ConfigDaoNull { data.insert("blockchain_service_url".to_string(), (None, false)); data.insert("past_neighbors".to_string(), (None, true)); data.insert("mapping_protocol".to_string(), (None, false)); + data.insert( + "min_hops".to_string(), + (Some(DEFAULT_MIN_HOPS.to_string()), false), + ); data.insert("earning_wallet_address".to_string(), (None, false)); data.insert( "schema_version".to_string(), @@ -135,6 +140,7 @@ mod tests { use crate::database::db_initializer::DbInitializationConfig; use crate::database::db_initializer::DbInitializer; use crate::db_config::config_dao::ConfigDaoReal; + use crate::neighborhood::DEFAULT_MIN_HOPS; use masq_lib::blockchains::chains::Chain; use masq_lib::constants::{DEFAULT_CHAIN, ETH_MAINNET_CONTRACT_CREATION_BLOCK}; use masq_lib::test_utils::utils::ensure_node_home_directory_exists; @@ -144,6 +150,7 @@ mod tests { fn get_works() { let subject = ConfigDaoNull::default(); + assert_eq!(subject.get("booga"), Err(ConfigDaoError::NotPresent)); assert_eq!( subject.get("chain_name").unwrap(), ConfigDaoRecord::new( @@ -161,21 +168,16 @@ mod tests { ) ); assert_eq!( - subject.get("gas_price").unwrap(), - ConfigDaoRecord::new("gas_price", Some("1"), false) + subject.get("consuming_wallet_private_key").unwrap(), + ConfigDaoRecord::new("consuming_wallet_private_key", None, true) ); assert_eq!( - subject.get("start_block").unwrap(), - ConfigDaoRecord::new( - "start_block", - Some(&DEFAULT_CHAIN.rec().contract_creation_block.to_string()), - false - ) + subject.get("gas_price").unwrap(), + ConfigDaoRecord::new("gas_price", Some("1"), false) ); - assert_eq!(subject.get("booga"), Err(ConfigDaoError::NotPresent)); assert_eq!( - subject.get("consuming_wallet_private_key").unwrap(), - ConfigDaoRecord::new("consuming_wallet_private_key", None, true) + subject.get("min_hops").unwrap(), + ConfigDaoRecord::new("min_hops", Some(&DEFAULT_MIN_HOPS.to_string()), false) ); assert_eq!( subject.get("payment_thresholds").unwrap(), @@ -197,6 +199,14 @@ mod tests { false ) ); + assert_eq!( + subject.get("start_block").unwrap(), + ConfigDaoRecord::new( + "start_block", + Some(&DEFAULT_CHAIN.rec().contract_creation_block.to_string()), + false + ) + ); } #[test] diff --git a/node/src/db_config/persistent_configuration.rs b/node/src/db_config/persistent_configuration.rs index d1b212582..3420ec688 100644 --- a/node/src/db_config/persistent_configuration.rs +++ b/node/src/db_config/persistent_configuration.rs @@ -13,7 +13,7 @@ use crate::db_config::typed_config_layer::{ }; use crate::sub_lib::accountant::{PaymentThresholds, ScanIntervals}; use crate::sub_lib::cryptde::PlainData; -use crate::sub_lib::neighborhood::{NodeDescriptor, RatePack}; +use crate::sub_lib::neighborhood::{Hops, NodeDescriptor, RatePack}; use crate::sub_lib::wallet::Wallet; #[cfg(test)] use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; @@ -118,6 +118,8 @@ pub trait PersistentConfiguration { &mut self, value: Option, ) -> Result<(), PersistentConfigError>; + fn min_hops(&self) -> Result; + fn set_min_hops(&mut self, value: Hops) -> Result<(), PersistentConfigError>; fn neighborhood_mode(&self) -> Result; fn set_neighborhood_mode( &mut self, @@ -335,6 +337,19 @@ impl PersistentConfiguration for PersistentConfigurationReal { .set("mapping_protocol", value.map(|v| v.to_string()))?) } + fn min_hops(&self) -> Result { + let result = self.get("min_hops")?.map(|val| Hops::from_str(&val)); + match result { + None => Self::missing_value_panic("min_hops"), + Some(Ok(hops)) => Ok(hops), + Some(Err(msg)) => Err(PersistentConfigError::DatabaseError(msg)), + } + } + + fn set_min_hops(&mut self, value: Hops) -> Result<(), PersistentConfigError> { + Ok(self.dao.set("min_hops", Some(value.to_string()))?) + } + fn neighborhood_mode(&self) -> Result { NeighborhoodModeLight::from_str( self.get("neighborhood_mode")? @@ -1685,6 +1700,49 @@ mod tests { assert_eq!(*set_params, vec![("mapping_protocol".to_string(), None)]); } + #[test] + fn min_hops_works() { + let config_dao = Box::new(ConfigDaoMock::new().get_result(Ok(ConfigDaoRecord::new( + "min_hops", + Some("3"), + false, + )))); + let subject = PersistentConfigurationReal::new(config_dao); + + let min_hops = subject.min_hops().unwrap(); + + assert_eq!(min_hops, Hops::ThreeHops); + } + + #[test] + fn set_min_hops_to_some() { + let set_params_arc = Arc::new(Mutex::new(vec![])); + let config_dao = ConfigDaoMock::new() + .set_params(&set_params_arc) + .set_result(Ok(())); + let mut subject = PersistentConfigurationReal::new(Box::new(config_dao)); + + let result = subject.set_min_hops(Hops::TwoHops); + + assert_eq!(result, Ok(())); + let set_params = set_params_arc.lock().unwrap(); + assert_eq!( + *set_params, + vec![("min_hops".to_string(), Some("2".to_string()))] + ); + } + + #[test] + #[should_panic(expected = "ever-supplied value missing: min_hops; database is corrupt!")] + fn panics_when_min_hops_value_is_missing() { + let config_dao = Box::new( + ConfigDaoMock::new().get_result(Ok(ConfigDaoRecord::new("min_hops", None, false))), + ); + let subject = PersistentConfigurationReal::new(config_dao); + + let _result = subject.min_hops(); + } + #[test] fn neighborhood_mode_works() { let get_params_arc = Arc::new(Mutex::new(vec![])); diff --git a/node/src/neighborhood/gossip_acceptor.rs b/node/src/neighborhood/gossip_acceptor.rs index 311d0d620..3700a448b 100644 --- a/node/src/neighborhood/gossip_acceptor.rs +++ b/node/src/neighborhood/gossip_acceptor.rs @@ -937,11 +937,8 @@ impl GossipHandler for StandardGossipHandler { let initial_neighborship_status = StandardGossipHandler::check_full_neighbor(database, gossip_source.ip()); - let patch = self.compute_patch( - &agrs, - database.root(), - neighborhood_metadata.min_hops_count as u8, - ); + let patch = + self.compute_patch(&agrs, database.root(), neighborhood_metadata.min_hops as u8); let filtered_agrs = self.filter_agrs_by_patch(agrs, patch); let mut db_changed = self.identify_and_add_non_introductory_new_nodes( @@ -989,7 +986,7 @@ impl StandardGossipHandler { &self, agrs: &[AccessibleGossipRecord], root_node: &NodeRecord, - min_hops_count: u8, + min_hops: u8, ) -> HashSet { let agrs_by_key = agrs .iter() @@ -1001,7 +998,7 @@ impl StandardGossipHandler { &mut patch, root_node.public_key(), &agrs_by_key, - min_hops_count, + min_hops, root_node, ); @@ -1339,7 +1336,7 @@ mod tests { use crate::test_utils::neighborhood_test_utils::{ db_from_node, gossip_about_nodes_from_database, linearly_connect_nodes, make_meaningless_db, make_node_record, make_node_record_f, make_node_records, - public_keys_from_node_records, MIN_HOPS_COUNT_FOR_TEST, + public_keys_from_node_records, MIN_HOPS_FOR_TEST, }; use crate::test_utils::unshared_test_utils::make_cpm_recipient; use crate::test_utils::{assert_contains, main_cryptde, vec_to_set}; @@ -1369,7 +1366,7 @@ mod tests { NeighborhoodMetadata { connection_progress_peers: vec![], cpm_recipient: make_cpm_recipient().0, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, } } @@ -2385,7 +2382,7 @@ mod tests { .build(); let agrs: Vec = gossip.try_into().unwrap(); - let result = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_COUNT_FOR_TEST as u8); + let result = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_FOR_TEST as u8); let expected_hashset = vec![ node_a.public_key().clone(), @@ -2437,7 +2434,7 @@ mod tests { .build(); let agrs: Vec = gossip.try_into().unwrap(); - let patch = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_COUNT_FOR_TEST as u8); + let patch = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_FOR_TEST as u8); let expected_hashset = vec![ node_a.public_key().clone(), @@ -2486,7 +2483,7 @@ mod tests { .build(); let agrs: Vec = gossip.try_into().unwrap(); - let patch = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_COUNT_FOR_TEST as u8); + let patch = subject.compute_patch(&agrs, node_a_db.root(), MIN_HOPS_FOR_TEST as u8); let expected_hashset = vec![ node_a.public_key().clone(), @@ -2568,17 +2565,17 @@ mod tests { assert_eq!(result, GossipAcceptanceResult::Ignored); } - fn assert_compute_patch(min_hops_count: Hops) { + fn assert_compute_patch(min_hops: Hops) { let subject = StandardGossipHandler::new(Logger::new("assert_compute_patch")); // one node to finish hops and another node that's outside the patch - let nodes_count = min_hops_count as usize + 2; + let nodes_count = min_hops as usize + 2; let nodes = make_node_records(nodes_count as u16); let db = linearly_connect_nodes(&nodes); // gossip is intended for the first node (also root), thereby it's excluded let gossip = gossip_about_nodes_from_database(&db, &nodes[1..]); let agrs: Vec = gossip.try_into().unwrap(); - let result = subject.compute_patch(&agrs, db.root(), min_hops_count as u8); + let result = subject.compute_patch(&agrs, db.root(), min_hops as u8); // last node is excluded because it is outside the patch let expected_nodes = &nodes[0..nodes_count - 1]; diff --git a/node/src/neighborhood/mod.rs b/node/src/neighborhood/mod.rs index 6fa64006c..5a68bd485 100644 --- a/node/src/neighborhood/mod.rs +++ b/node/src/neighborhood/mod.rs @@ -79,7 +79,7 @@ use neighborhood_database::NeighborhoodDatabase; use node_record::NodeRecord; pub const CRASH_KEY: &str = "NEIGHBORHOOD"; -pub const DEFAULT_MIN_HOPS_COUNT: Hops = Hops::ThreeHops; +pub const DEFAULT_MIN_HOPS: Hops = Hops::ThreeHops; pub const UNREACHABLE_HOST_PENALTY: i64 = 100_000_000; pub const RESPONSE_UNDESIRABILITY_FACTOR: usize = 1_000; // assumed response length is request * this @@ -94,7 +94,7 @@ pub struct Neighborhood { neighborhood_database: NeighborhoodDatabase, consuming_wallet_opt: Option, mode: NeighborhoodModeLight, - min_hops_count: Hops, + min_hops: Hops, next_return_route_id: u32, overall_connection_status: OverallConnectionStatus, chain: Chain, @@ -410,7 +410,7 @@ enum RouteDirection { impl Neighborhood { pub fn new(cryptde: &'static dyn CryptDE, config: &BootstrapperConfig) -> Self { let neighborhood_config = &config.neighborhood_config; - let min_hops_count = neighborhood_config.min_hops_count; + let min_hops = neighborhood_config.min_hops; let neighborhood_mode = &neighborhood_config.mode; let mode: NeighborhoodModeLight = neighborhood_mode.into(); let neighbor_configs = neighborhood_mode.neighbor_configs(); @@ -454,7 +454,7 @@ impl Neighborhood { neighborhood_database, consuming_wallet_opt: config.consuming_wallet_opt.clone(), mode, - min_hops_count, + min_hops, next_return_route_id: 0, overall_connection_status, chain: config.blockchain_bridge_config.chain, @@ -491,6 +491,7 @@ impl Neighborhood { fn handle_start_message(&mut self) { debug!(self.logger, "Connecting to persistent database"); self.connect_database(); + self.validate_or_replace_min_hops_value(); self.send_debut_gossip_to_all_initial_descriptors(); } @@ -546,6 +547,26 @@ impl Neighborhood { } } + fn validate_or_replace_min_hops_value(&mut self) { + if let Some(persistent_config) = self.persistent_config_opt.as_ref() { + let value_in_db = persistent_config + .min_hops() + .expect("Min Hops value is not initialized inside Database"); + let value_in_neighborhood = self.min_hops; + if value_in_neighborhood != value_in_db { + info!( + self.logger, + "Database with different min hops value detected; \ + currently set: {:?}, found in db: {:?}; changing to {:?}", + value_in_neighborhood, + value_in_db, + value_in_db + ); + self.min_hops = value_in_db; + } + } + } + fn send_debut_gossip_to_all_initial_descriptors(&mut self) { if self.overall_connection_status.is_empty() { info!(self.logger, "Empty. No Nodes to report to; continuing"); @@ -727,7 +748,7 @@ impl Neighborhood { let neighborhood_metadata = NeighborhoodMetadata { connection_progress_peers: self.overall_connection_status.get_peer_addrs(), cpm_recipient, - min_hops_count: self.min_hops_count, + min_hops: self.min_hops, }; let acceptance_result = self.gossip_acceptor.handle( &mut self.neighborhood_database, @@ -820,7 +841,7 @@ impl Neighborhood { if self.handle_route_query_message(msg).is_some() { debug!( &self.logger, - "The connectivity check has found a {}-hop route.", self.min_hops_count as usize + "The connectivity check has found a {}-hop route.", self.min_hops as usize ); self.overall_connection_status .update_ocs_stage_and_send_message_to_ui( @@ -946,7 +967,7 @@ impl Neighborhood { let over = self.make_route_segment( self.cryptde.public_key(), request_msg.target_key_opt.as_ref(), - self.min_hops_count as usize, + self.min_hops as usize, request_msg.target_component, request_msg.payload_size, RouteDirection::Over, @@ -961,7 +982,7 @@ impl Neighborhood { let back = self.make_route_segment( over.keys.last().expect("Empty segment"), Some(self.cryptde.public_key()), - self.min_hops_count as usize, + self.min_hops as usize, request_msg .return_component_opt .expect("No return component"), @@ -1611,7 +1632,7 @@ mod tests { cryptdes_from_node_records, db_from_node, linearly_connect_nodes, make_global_cryptde_node_record, make_ip, make_node, make_node_descriptor, make_node_record, make_node_record_f, make_node_records, neighborhood_from_nodes, - MIN_HOPS_COUNT_FOR_TEST, + MIN_HOPS_FOR_TEST, }; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::rate_pack; @@ -1653,21 +1674,18 @@ mod tests { #[test] fn constants_have_correct_values() { assert_eq!(CRASH_KEY, "NEIGHBORHOOD"); - assert_eq!(DEFAULT_MIN_HOPS_COUNT, Hops::ThreeHops); + assert_eq!(DEFAULT_MIN_HOPS, Hops::ThreeHops); } #[test] - fn min_hops_count_is_set_inside_neighborhood() { - let min_hops_count = Hops::SixHops; + fn min_hops_is_set_inside_neighborhood() { + let min_hops = Hops::SixHops; let mode = NeighborhoodMode::Standard( NodeAddr::new(&make_ip(1), &[1234, 2345]), vec![make_node_descriptor(make_ip(2))], rate_pack(100), ); - let neighborhood_config = NeighborhoodConfig { - mode, - min_hops_count, - }; + let neighborhood_config = NeighborhoodConfig { mode, min_hops }; let subject = Neighborhood::new( main_cryptde(), @@ -1675,11 +1693,11 @@ mod tests { neighborhood_config, make_wallet("earning"), None, - "min_hops_count_is_set_inside_neighborhood", + "min_hops_is_set_inside_neighborhood", ), ); - assert_eq!(subject.min_hops_count, Hops::SixHops); + assert_eq!(subject.min_hops, Hops::SixHops); } #[test] @@ -1696,7 +1714,7 @@ mod tests { "masq://eth-ropsten:AQIDBA@1.2.3.4:1234", )) .unwrap()]), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), None, @@ -1721,7 +1739,7 @@ mod tests { "masq://eth-mainnet:AQIDBA@1.2.3.4:1234", )) .unwrap()]), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), None, @@ -1742,7 +1760,7 @@ mod tests { &bc_from_nc_plus( NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), None, @@ -1771,7 +1789,7 @@ mod tests { vec![neighbor.node_descriptor(TEST_DEFAULT_CHAIN, cryptde)], DEFAULT_RATE_PACK.clone(), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), None, @@ -1810,13 +1828,16 @@ mod tests { &bc_from_nc_plus( NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), "node_with_zero_hop_config_ignores_start_message", ), ); + subject.persistent_config_opt = Some(Box::new( + PersistentConfigurationMock::new().min_hops_result(Ok(MIN_HOPS_FOR_TEST)), + )); subject.data_directory = data_dir; let addr = subject.start(); let sub = addr.clone().recipient::(); @@ -1859,7 +1880,7 @@ mod tests { ], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), @@ -1939,7 +1960,7 @@ mod tests { initial_node_descriptors, rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let bootstrap_config = bc_from_nc_plus(neighborhood_config, make_wallet("earning"), None, "test"); @@ -2408,7 +2429,7 @@ mod tests { initial_node_descriptors, rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let mut subject = Neighborhood::new( main_cryptde(), @@ -2485,7 +2506,7 @@ mod tests { ], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), None, @@ -2560,7 +2581,7 @@ mod tests { let system = System::new("route_query_works_when_node_is_set_for_one_hop_and_no_consuming_wallet"); let mut subject = make_standard_subject(); - subject.min_hops_count = Hops::OneHop; + subject.min_hops = Hops::OneHop; subject .neighborhood_database .root_mut() @@ -2642,7 +2663,7 @@ mod tests { ) { let system = System::new("route_query_responds_with_none_when_asked_for_one_hop_round_trip_route_without_consuming_wallet_when_back_route_needs_two_hops"); let mut subject = make_standard_subject(); - subject.min_hops_count = Hops::OneHop; + subject.min_hops = Hops::OneHop; let a = &make_node_record(1234, true); let b = &subject.neighborhood_database.root().clone(); let c = &make_node_record(3456, true); @@ -2674,7 +2695,7 @@ mod tests { ) { let system = System::new("route_query_responds_with_none_when_asked_for_two_hop_one_way_route_without_consuming_wallet"); let mut subject = make_standard_subject(); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; let addr: Addr = subject.start(); let sub: Recipient = addr.recipient::(); let msg = RouteQueryMessage::data_indefinite_route_request(None, 20000); @@ -2764,7 +2785,7 @@ mod tests { let earning_wallet = make_wallet("earning"); let system = System::new("route_query_messages"); let mut subject = make_standard_subject(); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; subject .neighborhood_database .root_mut() @@ -2884,7 +2905,7 @@ mod tests { let cryptde = main_cryptde(); let system = System::new("return_route_ids_increase"); let (_, _, _, mut subject) = make_o_r_e_subject(); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; let addr: Addr = subject.start(); let sub: Recipient = addr.recipient::(); @@ -2915,7 +2936,7 @@ mod tests { let cryptde = main_cryptde(); let system = System::new("can_update_consuming_wallet"); let (o, r, e, mut subject) = make_o_r_e_subject(); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; let addr: Addr = subject.start(); let set_wallet_sub = addr.clone().recipient::(); let route_sub = addr.recipient::(); @@ -3357,7 +3378,7 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), @@ -3756,7 +3777,7 @@ mod tests { initial_node_descriptors, rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let bootstrap_config = bc_from_nc_plus(neighborhood_config, make_wallet("earning"), None, "test"); @@ -3788,7 +3809,7 @@ mod tests { let (accountant, _, _) = make_recorder(); let node_to_ui_recipient = ui_gateway.start().recipient::(); let connected_signal = accountant.start().recipient(); - subject.min_hops_count = hops; + subject.min_hops = hops; subject.logger = Logger::new(test_name); subject.node_to_ui_recipient_opt = Some(node_to_ui_recipient); subject.connected_signal_opt = Some(connected_signal); @@ -4479,7 +4500,7 @@ mod tests { vec![], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, this_node_inside.earning_wallet(), None, @@ -4542,13 +4563,16 @@ mod tests { vec![debut_target.clone()], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, NodeRecord::earning_wallet_from_key(&cryptde.public_key()), NodeRecord::consuming_wallet_from_key(&cryptde.public_key()), "node_gossips_to_neighbors_on_startup", ), ); + subject.persistent_config_opt = Some(Box::new( + PersistentConfigurationMock::new().min_hops_result(Ok(MIN_HOPS_FOR_TEST)), + )); subject.data_directory = data_dir; subject.logger = Logger::new("node_gossips_to_neighbors_on_startup"); let this_node = subject.neighborhood_database.root().clone(); @@ -4581,6 +4605,96 @@ mod tests { )); } + #[test] + fn node_validates_min_hops_value_from_persistent_configuration() { + let test_name = "node_validates_min_hops_value_from_persistent_configuration"; + let min_hops_in_neighborhood = Hops::SixHops; + let min_hops_in_persistent_configuration = min_hops_in_neighborhood; + let mut subject = Neighborhood::new( + main_cryptde(), + &bc_from_nc_plus( + NeighborhoodConfig { + mode: NeighborhoodMode::Standard( + NodeAddr::new(&make_ip(0), &[1234]), + vec![make_node_descriptor(make_ip(1))], + rate_pack(100), + ), + min_hops: min_hops_in_neighborhood, + }, + make_wallet("earning"), + None, + test_name, + ), + ); + subject.persistent_config_opt = Some(Box::new( + PersistentConfigurationMock::new() + .min_hops_result(Ok(min_hops_in_persistent_configuration)), + )); + let system = System::new(test_name); + let addr: Addr = subject.start(); + let peer_actors = peer_actors_builder().build(); + addr.try_send(BindMessage { peer_actors }).unwrap(); + + addr.try_send(StartMessage {}).unwrap(); + + addr.try_send(AssertionsMessage { + assertions: Box::new(move |neighborhood: &mut Neighborhood| { + assert_eq!(neighborhood.min_hops, min_hops_in_persistent_configuration); + }), + }) + .unwrap(); + System::current().stop(); + system.run(); + } + + #[test] + fn neighborhood_picks_min_hops_value_from_db_if_it_is_different_from_that_in_neighborhood() { + init_test_logging(); + let test_name = "neighborhood_picks_min_hops_value_from_db_if_it_is_different_from_that_in_neighborhood"; + let min_hops_in_neighborhood = Hops::SixHops; + let min_hops_in_db = Hops::TwoHops; + let mut subject = Neighborhood::new( + main_cryptde(), + &bc_from_nc_plus( + NeighborhoodConfig { + mode: NeighborhoodMode::Standard( + NodeAddr::new(&make_ip(0), &[1234]), + vec![make_node_descriptor(make_ip(1))], + rate_pack(100), + ), + min_hops: min_hops_in_neighborhood, + }, + make_wallet("earning"), + None, + test_name, + ), + ); + subject.logger = Logger::new(test_name); + subject.persistent_config_opt = Some(Box::new( + PersistentConfigurationMock::new().min_hops_result(Ok(min_hops_in_db)), + )); + let system = System::new(test_name); + let addr: Addr = subject.start(); + let peer_actors = peer_actors_builder().build(); + addr.try_send(BindMessage { peer_actors }).unwrap(); + + addr.try_send(StartMessage {}).unwrap(); + + let assertions_msg = AssertionsMessage { + assertions: Box::new(move |neighborhood: &mut Neighborhood| { + assert_eq!(neighborhood.min_hops, min_hops_in_db) + }), + }; + addr.try_send(assertions_msg).unwrap(); + System::current().stop(); + system.run(); + TestLogHandler::new().exists_log_containing(&format!( + "INFO: {test_name}: Database with different min hops value detected; \ + currently set: {:?}, found in db: {:?}; changing to {:?}", + min_hops_in_neighborhood, min_hops_in_db, min_hops_in_db + )); + } + /* Database, where we'll fail to make a three-hop route to C after removing A: @@ -4738,7 +4852,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), @@ -4800,7 +4914,7 @@ mod tests { vec![node_record_to_neighbor_config(&one_neighbor)], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), @@ -4867,7 +4981,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, earning_wallet.clone(), consuming_wallet.clone(), @@ -4931,7 +5045,7 @@ mod tests { ))], rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, node_record.earning_wallet(), None, @@ -4973,12 +5087,12 @@ mod tests { #[test] fn make_round_trip_route_returns_error_when_no_non_next_door_neighbor_found() { // Make a triangle of Nodes - let min_hops_count = Hops::TwoHops; + let min_hops = Hops::TwoHops; let one_next_door_neighbor = make_node_record(3333, true); let another_next_door_neighbor = make_node_record(4444, true); let subject_node = make_global_cryptde_node_record(5555, true); // 9e7p7un06eHs6frl5A let mut subject = neighborhood_from_nodes(&subject_node, Some(&one_next_door_neighbor)); - subject.min_hops_count = min_hops_count; + subject.min_hops = min_hops; subject .neighborhood_database @@ -5013,7 +5127,7 @@ mod tests { assert_eq!( Err(format!( "Couldn't find any routes: at least {}-hop from {} to ProxyClient at Unknown", - min_hops_count as usize, + min_hops as usize, main_cryptde().public_key() )), result @@ -5027,7 +5141,7 @@ mod tests { let subject_node = make_global_cryptde_node_record(666, true); // 9e7p7un06eHs6frl5A let mut subject = neighborhood_from_nodes(&subject_node, Some(&next_door_neighbor)); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; subject .neighborhood_database @@ -5090,15 +5204,15 @@ mod tests { assert_eq!(expected_public_keys, actual_keys); } - fn assert_route_query_message(min_hops_count: Hops) { - let hops = min_hops_count as usize; + fn assert_route_query_message(min_hops: Hops) { + let hops = min_hops as usize; let nodes_count = hops + 1; let root_node = make_global_cryptde_node_record(4242, true); let mut nodes = make_node_records(nodes_count as u16); nodes[0] = root_node; let db = linearly_connect_nodes(&nodes); let mut subject = neighborhood_from_nodes(db.root(), nodes.get(1)); - subject.min_hops_count = min_hops_count; + subject.min_hops = min_hops; subject.neighborhood_database = db; let result = subject.make_round_trip_route(RouteQueryMessage { @@ -5176,7 +5290,7 @@ mod tests { fn check_fee_preference(payload_size: usize, a_not_b: bool) { let mut subject = make_standard_subject(); - subject.min_hops_count = Hops::TwoHops; + subject.min_hops = Hops::TwoHops; let db = &mut subject.neighborhood_database; let o = &db.root().public_key().clone(); let a = &db.add_node(make_node_record(2345, true)).unwrap(); @@ -5443,7 +5557,7 @@ mod tests { &bc_from_nc_plus( NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, make_wallet("earning"), None, @@ -5812,7 +5926,7 @@ mod tests { initial_node_descriptors, rate_pack(100), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }; let bootstrap_config = bc_from_nc_plus(neighborhood_config, make_wallet("earning"), None, test_name); @@ -5836,7 +5950,7 @@ mod tests { &bc_from_nc_plus( NeighborhoodConfig { mode: NeighborhoodMode::ConsumeOnly(vec![make_node_descriptor(make_ip(1))]), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, make_wallet("earning"), None, diff --git a/node/src/node_configurator/node_configurator_standard.rs b/node/src/node_configurator/node_configurator_standard.rs index 8da663d66..49bdf3fa3 100644 --- a/node/src/node_configurator/node_configurator_standard.rs +++ b/node/src/node_configurator/node_configurator_standard.rs @@ -247,6 +247,8 @@ fn configure_database( config: &BootstrapperConfig, persistent_config: &mut dyn PersistentConfiguration, ) -> Result<(), ConfiguratorError> { + // We don't want to panic in case clandestine_port or blockchain_service_url is not configured + // inside the bootstrap config if let Some(port) = config.clandestine_port_opt { if let Err(pce) = persistent_config.set_clandestine_port(port) { return Err(pce.into_configurator_error("clandestine-port")); @@ -256,6 +258,9 @@ fn configure_database( if let Err(pce) = persistent_config.set_neighborhood_mode(neighborhood_mode_light) { return Err(pce.into_configurator_error("neighborhood-mode")); } + if let Err(pce) = persistent_config.set_min_hops(config.neighborhood_config.min_hops) { + return Err(pce.into_configurator_error("min-hops")); + } if let Some(url) = config .blockchain_bridge_config .blockchain_service_url_opt @@ -379,6 +384,7 @@ mod tests { config.clandestine_port_opt = None; let mut persistent_config = PersistentConfigurationMock::new() .set_neighborhood_mode_result(Ok(())) + .set_min_hops_result(Ok(())) .set_gas_price_result(Err(PersistentConfigError::TransactionError)); let result = configure_database(&config, &mut persistent_config); @@ -396,6 +402,7 @@ mod tests { Some("https://infura.io/ID".to_string()); let mut persistent_config = PersistentConfigurationMock::new() .set_neighborhood_mode_result(Ok(())) + .set_min_hops_result(Ok(())) .set_blockchain_service_url_result(Err(PersistentConfigError::TransactionError)); let result = configure_database(&config, &mut persistent_config); @@ -423,6 +430,22 @@ mod tests { ) } + #[test] + fn configure_database_handles_error_during_setting_min_hops() { + let mut config = BootstrapperConfig::new(); + config.neighborhood_config.min_hops = Hops::FourHops; + let mut persistent_config = PersistentConfigurationMock::new() + .set_neighborhood_mode_result(Ok(())) + .set_min_hops_result(Err(PersistentConfigError::TransactionError)); + + let result = configure_database(&config, &mut persistent_config); + + assert_eq!( + result, + Err(PersistentConfigError::TransactionError.into_configurator_error("min-hops")) + ) + } + fn make_default_cli_params() -> ArgsBuilder { ArgsBuilder::new().param("--ip", "1.2.3.4") } @@ -577,7 +600,7 @@ mod tests { config.neighborhood_config, NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, // not populated on the privileged side - min_hops_count: Hops::ThreeHops, + min_hops: Hops::ThreeHops, } ); assert_eq!( @@ -881,12 +904,14 @@ mod tests { .as_str(), )) .unwrap()]); + config.neighborhood_config.min_hops = Hops::FourHops; config.blockchain_bridge_config.blockchain_service_url_opt = Some("https://infura.io/ID".to_string()); let set_blockchain_service_params_arc = Arc::new(Mutex::new(vec![])); let set_clandestine_port_params_arc = Arc::new(Mutex::new(vec![])); let set_gas_price_params_arc = Arc::new(Mutex::new(vec![])); let set_neighborhood_mode_params_arc = Arc::new(Mutex::new(vec![])); + let set_min_hops_params_arc = Arc::new(Mutex::new(vec![])); let mut persistent_config = PersistentConfigurationMock::new() .set_clandestine_port_params(&set_clandestine_port_params_arc) .set_clandestine_port_result(Ok(())) @@ -895,7 +920,9 @@ mod tests { .set_neighborhood_mode_params(&set_neighborhood_mode_params_arc) .set_neighborhood_mode_result(Ok(())) .set_gas_price_params(&set_gas_price_params_arc) - .set_gas_price_result(Ok(())); + .set_gas_price_result(Ok(())) + .set_min_hops_params(&set_min_hops_params_arc) + .set_min_hops_result(Ok(())); let result = configure_database(&config, &mut persistent_config); @@ -914,6 +941,8 @@ mod tests { assert_eq!(*set_gas_price_params, vec![gas_price]); let set_clandestine_port_params = set_clandestine_port_params_arc.lock().unwrap(); assert_eq!(*set_clandestine_port_params, vec![1234]); + let set_min_hops_params = set_min_hops_params_arc.lock().unwrap(); + assert_eq!(*set_min_hops_params, vec![Hops::FourHops]) } #[test] @@ -928,6 +957,7 @@ mod tests { .set_blockchain_service_url_params(&set_blockchain_service_params_arc) .set_neighborhood_mode_params(&set_neighborhood_mode_params_arc) .set_neighborhood_mode_result(Ok(())) + .set_min_hops_result(Ok(())) .set_gas_price_result(Ok(())); let result = configure_database(&config, &mut persistent_config); diff --git a/node/src/node_configurator/unprivileged_parse_args_configuration.rs b/node/src/node_configurator/unprivileged_parse_args_configuration.rs index 5d543a80a..2d86fb1ad 100644 --- a/node/src/node_configurator/unprivileged_parse_args_configuration.rs +++ b/node/src/node_configurator/unprivileged_parse_args_configuration.rs @@ -20,7 +20,6 @@ use masq_lib::constants::{DEFAULT_CHAIN, MASQ_URL_PREFIX}; use masq_lib::logger::Logger; use masq_lib::multi_config::MultiConfig; use masq_lib::shared_schema::{ConfiguratorError, ParamError}; -use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use masq_lib::utils::{AutomapProtocol, ExpectValue}; use rustc_hex::FromHex; use std::net::{IpAddr, Ipv4Addr}; @@ -214,14 +213,16 @@ pub fn make_neighborhood_config( } }; - let min_hops_count = value_m!(multi_config, "min-hops", Hops) - .expect("Clap schema didn't specify the default value."); + let min_hops: Hops = match value_m!(multi_config, "min-hops", Hops) { + Some(hops) => hops, + None => match persistent_config.min_hops() { + Ok(hops) => hops, + Err(e) => panic!("Unable to find min_hops value in database: {:?}", e), + }, + }; match make_neighborhood_mode(multi_config, neighbor_configs, persistent_config) { - Ok(mode) => Ok(NeighborhoodConfig { - mode, - min_hops_count, - }), + Ok(mode) => Ok(NeighborhoodConfig { mode, min_hops }), Err(e) => Err(e), } } @@ -349,20 +350,23 @@ fn convert_ci_configs( if separate_configs.is_empty() { Ok(None) } else { - let dummy_cryptde: Box = { - if value_m!(multi_config, "fake-public-key", String).is_none() { - Box::new(CryptDEReal::new(TEST_DEFAULT_CHAIN)) - } else { - Box::new(CryptDENull::new(TEST_DEFAULT_CHAIN)) - } - }; let desired_chain = Chain::from( value_m!(multi_config, "chain", String) .unwrap_or_else(|| DEFAULT_CHAIN.rec().literal_identifier.to_string()) .as_str(), ); - let results = - validate_descriptors_from_user(separate_configs, dummy_cryptde, desired_chain); + let cryptde_for_key_len: Box = { + if value_m!(multi_config, "fake-public-key", String).is_none() { + Box::new(CryptDEReal::new(desired_chain)) + } else { + Box::new(CryptDENull::new(desired_chain)) + } + }; + let results = validate_descriptors_from_user( + separate_configs, + cryptde_for_key_len, + desired_chain, + ); let (ok, err): (Vec, Vec) = results.into_iter().partition(|result| result.is_ok()); let ok = ok @@ -385,12 +389,12 @@ fn convert_ci_configs( fn validate_descriptors_from_user( descriptors: Vec, - dummy_cryptde: Box, + cryptde_for_key_len: Box, desired_native_chain: Chain, ) -> Vec> { descriptors.into_iter().map(|node_desc_from_ci| { let node_desc_trimmed = node_desc_from_ci.trim(); - match NodeDescriptor::try_from((dummy_cryptde.as_ref(), node_desc_trimmed)) { + match NodeDescriptor::try_from((cryptde_for_key_len.as_ref(), node_desc_trimmed)) { Ok(descriptor) => { let competence_from_descriptor = descriptor.blockchain; if desired_native_chain == competence_from_descriptor { @@ -632,6 +636,7 @@ mod tests { use crate::sub_lib::neighborhood::{Hops, DEFAULT_RATE_PACK}; use crate::sub_lib::utils::make_new_multi_config; use crate::sub_lib::wallet::Wallet; + use crate::test_utils::neighborhood_test_utils::MIN_HOPS_FOR_TEST; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::unshared_test_utils::{ configure_default_persistent_config, default_persistent_config_just_accountant_config, @@ -642,7 +647,7 @@ mod tests { use masq_lib::constants::DEFAULT_GAS_PRICE; use masq_lib::multi_config::{CommandLineVcl, NameValueVclArg, VclArg, VirtualCommandLine}; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; - use masq_lib::test_utils::utils::ensure_node_home_directory_exists; + use masq_lib::test_utils::utils::{ensure_node_home_directory_exists, TEST_DEFAULT_CHAIN}; use masq_lib::utils::running_test; use std::path::PathBuf; use std::str::FromStr; @@ -714,13 +719,38 @@ mod tests { ], DEFAULT_RATE_PACK ), - min_hops_count: Hops::OneHop, + min_hops: Hops::OneHop, }) ); } #[test] - fn make_neighborhood_config_standard_missing_min_hops_count() { + #[should_panic(expected = "Unable to find min_hops value in database: NotPresent")] + fn node_panics_if_min_hops_value_does_not_exist_inside_multi_config_or_db() { + running_test(); + let multi_config = make_new_multi_config( + &app_node(), + vec![Box::new(CommandLineVcl::new( + ArgsBuilder::new() + .param("--neighborhood-mode", "standard") + .opt("--min-hops") + .into(), + ))], + ) + .unwrap(); + let mut persistent_config = PersistentConfigurationMock::new() + .min_hops_result(Err(PersistentConfigError::NotPresent)); + + let _result = make_neighborhood_config( + &UnprivilegedParseArgsConfigurationDaoReal {}, + &multi_config, + &mut persistent_config, + &mut BootstrapperConfig::new(), + ); + } + + #[test] + fn make_neighborhood_config_standard_missing_min_hops() { running_test(); let multi_config = make_new_multi_config( &app_node(), @@ -744,13 +774,12 @@ mod tests { &mut BootstrapperConfig::new(), ); - let min_hops_count = result.unwrap().min_hops_count; - assert_eq!(min_hops_count, Hops::ThreeHops); + let min_hops = result.unwrap().min_hops; + assert_eq!(min_hops, Hops::ThreeHops); } #[test] - fn make_neighborhood_config_standard_uses_default_value_when_no_min_hops_count_value_is_provided( - ) { + fn make_neighborhood_config_standard_uses_default_value_when_no_min_hops_value_is_provided() { running_test(); let args = ArgsBuilder::new() .param("--neighborhood-mode", "standard") @@ -770,13 +799,12 @@ mod tests { &mut BootstrapperConfig::new(), ); - let min_hops_count = result.unwrap().min_hops_count; - assert_eq!(min_hops_count, Hops::ThreeHops); + let min_hops = result.unwrap().min_hops; + assert_eq!(min_hops, Hops::ThreeHops); } #[test] - fn make_neighborhood_config_standard_throws_err_when_undesirable_min_hops_count_value_is_provided( - ) { + fn make_neighborhood_config_standard_throws_err_when_undesirable_min_hops_value_is_provided() { running_test(); let args = ArgsBuilder::new() .param("--neighborhood-mode", "standard") @@ -826,7 +854,7 @@ mod tests { let node_addr = match result { Ok(NeighborhoodConfig { mode: NeighborhoodMode::Standard(node_addr, _, _), - min_hops_count: Hops::ThreeHops, + min_hops: Hops::ThreeHops, }) => node_addr, x => panic!("Wasn't expecting {:?}", x), }; @@ -1632,6 +1660,7 @@ mod tests { "masq://eth-ropsten:AQIDBA@1.2.3.4:1234,masq://eth-ropsten:AgMEBQ@2.3.4.5:2345", ), None, + None, ) .check_password_result(Ok(false)) .set_mapping_protocol_params(&set_mapping_protocol_params_arc) @@ -1681,7 +1710,7 @@ mod tests { vec![Box::new(CommandLineVcl::new(args.into()))]; let multi_config = make_new_multi_config(&app_node(), vcls).unwrap(); let mut persistent_configuration = { - let config = make_persistent_config(None, None, None, None, None, None) + let config = make_persistent_config(None, None, None, None, None, None, None) .blockchain_service_url_result(Ok(Some("https://infura.io/ID".to_string()))); default_persistent_config_just_accountant_config(config) }; @@ -2251,7 +2280,8 @@ mod tests { ) { running_test(); let multi_config = make_simplified_multi_config([]); - let mut persistent_config = make_persistent_config(None, None, None, None, None, None); + let mut persistent_config = + make_persistent_config(None, None, None, None, None, None, None); let mut config = BootstrapperConfig::new(); get_wallets(&multi_config, &mut persistent_config, &mut config).unwrap(); @@ -2292,6 +2322,7 @@ mod tests { None, None, None, + None, ); let mut config = BootstrapperConfig::new(); @@ -2317,6 +2348,7 @@ mod tests { None, None, None, + None, ); let mut config = BootstrapperConfig::new(); @@ -2342,6 +2374,7 @@ mod tests { None, None, None, + None, ); let mut config = BootstrapperConfig::new(); config.db_password_opt = Some("password".to_string()); @@ -2368,6 +2401,7 @@ mod tests { None, None, None, + None, ) .check_password_result(Ok(false)); let mut config = BootstrapperConfig::new(); @@ -2597,6 +2631,7 @@ mod tests { gas_price_opt: Option, past_neighbors_opt: Option<&str>, rate_pack_opt: Option, + min_hops_opt: Option, ) -> PersistentConfigurationMock { let consuming_wallet_private_key_opt = consuming_wallet_private_key_opt.map(|x| x.to_string()); @@ -2615,6 +2650,7 @@ mod tests { _ => Ok(None), }; let rate_pack = rate_pack_opt.unwrap_or(DEFAULT_RATE_PACK); + let min_hops = min_hops_opt.unwrap_or(MIN_HOPS_FOR_TEST); PersistentConfigurationMock::new() .consuming_wallet_private_key_result(Ok(consuming_wallet_private_key_opt)) .earning_wallet_address_result( @@ -2625,5 +2661,6 @@ mod tests { .past_neighbors_result(past_neighbors_result) .mapping_protocol_result(Ok(Some(AutomapProtocol::Pcp))) .rate_pack_result(Ok(rate_pack)) + .min_hops_result(Ok(min_hops)) } } diff --git a/node/src/sub_lib/neighborhood.rs b/node/src/sub_lib/neighborhood.rs index 2ac4f350e..f70ca1857 100644 --- a/node/src/sub_lib/neighborhood.rs +++ b/node/src/sub_lib/neighborhood.rs @@ -391,15 +391,21 @@ impl FromStr for Hops { "4" => Ok(Hops::FourHops), "5" => Ok(Hops::FiveHops), "6" => Ok(Hops::SixHops), - _ => Err("Invalid value for min hops count provided".to_string()), + _ => Err("Invalid value for min hops provided".to_string()), } } } +impl Display for Hops { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", *self as usize) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct NeighborhoodConfig { pub mode: NeighborhoodMode, - pub min_hops_count: Hops, + pub min_hops: Hops, } lazy_static! { @@ -576,7 +582,7 @@ impl fmt::Display for GossipFailure_0v1 { pub struct NeighborhoodMetadata { pub connection_progress_peers: Vec, pub cpm_recipient: Recipient, - pub min_hops_count: Hops, + pub min_hops: Hops, } pub struct NeighborhoodTools { @@ -1248,7 +1254,7 @@ mod tests { } #[test] - fn min_hops_count_can_be_converted_from_str() { + fn valid_hops_can_be_converted_from_str() { assert_eq!(Hops::from_str("1").unwrap(), Hops::OneHop); assert_eq!(Hops::from_str("2").unwrap(), Hops::TwoHops); assert_eq!(Hops::from_str("3").unwrap(), Hops::ThreeHops); @@ -1258,12 +1264,22 @@ mod tests { } #[test] - fn min_hops_count_conversion_from_str_returns_error() { + fn invalid_hops_conversion_from_str_returns_error() { let result = Hops::from_str("100"); assert_eq!( result, - Err("Invalid value for min hops count provided".to_string()) + Err("Invalid value for min hops provided".to_string()) ) } + + #[test] + fn display_is_implemented_for_hops() { + assert_eq!(Hops::OneHop.to_string(), "1"); + assert_eq!(Hops::TwoHops.to_string(), "2"); + assert_eq!(Hops::ThreeHops.to_string(), "3"); + assert_eq!(Hops::FourHops.to_string(), "4"); + assert_eq!(Hops::FiveHops.to_string(), "5"); + assert_eq!(Hops::SixHops.to_string(), "6"); + } } diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index 9cf5f2ae8..3dfd8839e 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -555,6 +555,7 @@ pub mod unshared_test_utils { NLSpawnHandleHolder, NLSpawnHandleHolderReal, NotifyHandle, NotifyLaterHandle, }; use crate::test_utils::database_utils::bring_db_0_back_to_life_and_return_connection; + use crate::test_utils::neighborhood_test_utils::MIN_HOPS_FOR_TEST; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::{make_recorder, Recorder, Recording}; use crate::test_utils::recorder_stop_conditions::{StopCondition, StopConditions}; @@ -681,6 +682,7 @@ pub mod unshared_test_utils { .past_neighbors_result(Ok(None)) .gas_price_result(Ok(1)) .blockchain_service_url_result(Ok(None)) + .min_hops_result(Ok(MIN_HOPS_FOR_TEST)) } pub fn default_persistent_config_just_accountant_config( diff --git a/node/src/test_utils/neighborhood_test_utils.rs b/node/src/test_utils/neighborhood_test_utils.rs index e85ccc4cf..d9899c3f1 100644 --- a/node/src/test_utils/neighborhood_test_utils.rs +++ b/node/src/test_utils/neighborhood_test_utils.rs @@ -3,7 +3,7 @@ use crate::bootstrapper::BootstrapperConfig; use crate::neighborhood::gossip::{GossipBuilder, GossipNodeRecord, Gossip_0v1}; use crate::neighborhood::neighborhood_database::NeighborhoodDatabase; use crate::neighborhood::node_record::{NodeRecord, NodeRecordInner_0v1}; -use crate::neighborhood::{AccessibleGossipRecord, Neighborhood, DEFAULT_MIN_HOPS_COUNT}; +use crate::neighborhood::{AccessibleGossipRecord, Neighborhood, DEFAULT_MIN_HOPS}; use crate::sub_lib::cryptde::PublicKey; use crate::sub_lib::cryptde::{CryptDE, PlainData}; use crate::sub_lib::cryptde_null::CryptDENull; @@ -18,7 +18,7 @@ use std::convert::TryFrom; use std::net::IpAddr; use std::net::Ipv4Addr; -pub const MIN_HOPS_COUNT_FOR_TEST: Hops = DEFAULT_MIN_HOPS_COUNT; +pub const MIN_HOPS_FOR_TEST: Hops = DEFAULT_MIN_HOPS; impl From<(&NeighborhoodDatabase, &PublicKey, bool)> for AccessibleGossipRecord { fn from( @@ -97,11 +97,11 @@ pub fn neighborhood_from_nodes( vec![NodeDescriptor::from((neighbor, Chain::EthRopsten, cryptde))], *root.rate_pack(), ), - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, None => NeighborhoodConfig { mode: NeighborhoodMode::ZeroHop, - min_hops_count: MIN_HOPS_COUNT_FOR_TEST, + min_hops: MIN_HOPS_FOR_TEST, }, }; config.earning_wallet = root.earning_wallet(); diff --git a/node/src/test_utils/persistent_configuration_mock.rs b/node/src/test_utils/persistent_configuration_mock.rs index b831d1094..1f8fceadc 100644 --- a/node/src/test_utils/persistent_configuration_mock.rs +++ b/node/src/test_utils/persistent_configuration_mock.rs @@ -4,7 +4,7 @@ use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; use crate::sub_lib::accountant::{PaymentThresholds, ScanIntervals}; -use crate::sub_lib::neighborhood::{NodeDescriptor, RatePack}; +use crate::sub_lib::neighborhood::{Hops, NodeDescriptor, RatePack}; use crate::sub_lib::wallet::Wallet; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use crate::{arbitrary_id_stamp_in_trait_impl, set_arbitrary_id_stamp_in_mock_impl}; @@ -44,6 +44,9 @@ pub struct PersistentConfigurationMock { mapping_protocol_results: RefCell, PersistentConfigError>>>, set_mapping_protocol_params: Arc>>>, set_mapping_protocol_results: RefCell>>, + min_hops_results: RefCell>>, + set_min_hops_params: Arc>>, + set_min_hops_results: RefCell>>, neighborhood_mode_results: RefCell>>, set_neighborhood_mode_params: Arc>>, set_neighborhood_mode_results: RefCell>>, @@ -172,6 +175,15 @@ impl PersistentConfiguration for PersistentConfigurationMock { self.set_mapping_protocol_results.borrow_mut().remove(0) } + fn min_hops(&self) -> Result { + self.min_hops_results.borrow_mut().remove(0) + } + + fn set_min_hops(&mut self, value: Hops) -> Result<(), PersistentConfigError> { + self.set_min_hops_params.lock().unwrap().push(value); + self.set_min_hops_results.borrow_mut().remove(0) + } + fn neighborhood_mode(&self) -> Result { self.neighborhood_mode_results.borrow_mut().remove(0) } @@ -374,6 +386,27 @@ impl PersistentConfigurationMock { self } + pub fn min_hops_result(self, result: Result) -> Self { + self.min_hops_results.borrow_mut().push(result); + self + } + + pub fn set_min_hops_params( + mut self, + params: &Arc>>, + ) -> PersistentConfigurationMock { + self.set_min_hops_params = params.clone(); + self + } + + pub fn set_min_hops_result( + self, + result: Result<(), PersistentConfigError>, + ) -> PersistentConfigurationMock { + self.set_min_hops_results.borrow_mut().push(result); + self + } + pub fn neighborhood_mode_result( self, result: Result,