From 9240b9c2494593ae3d10603ac6f61929ae629999 Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 10 Aug 2023 23:23:35 +0200 Subject: [PATCH 01/10] GH-672: first batch of fixed items from the review 3 --- node/src/accountant/mod.rs | 65 ++++++++++--------- node/src/accountant/payment_adjuster.rs | 6 +- node/src/accountant/scanners/mod.rs | 22 +++---- .../payable_payments_agent_abstract_layer.rs | 11 ++-- .../scanners/payable_payments_agent_web3.rs | 45 ++++++------- .../scanners/payable_payments_setup_msg.rs | 29 ++++----- node/src/accountant/test_utils.rs | 56 +++++++++------- node/src/blockchain/blockchain_bridge.rs | 63 +++++++++--------- node/src/blockchain/blockchain_interface.rs | 4 +- node/src/sub_lib/blockchain_bridge.rs | 6 +- node/src/test_utils/mod.rs | 23 ++++--- node/src/test_utils/recorder.rs | 38 +++++------ 12 files changed, 182 insertions(+), 186 deletions(-) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index d8490e167..6f9a0257e 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -30,7 +30,7 @@ use crate::accountant::database_access_objects::utils::{ use crate::accountant::financials::visibility_restricted_module::{ check_query_is_within_tech_limits, financials_entry_check, }; -use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsgPayload; +use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; use crate::accountant::scanners::{ScanSchedulers, Scanners}; use crate::blockchain::blockchain_bridge::{ PendingPayableFingerprint, PendingPayableFingerprintSeeds, RetrieveTransactions, @@ -93,7 +93,7 @@ pub struct Accountant { scan_schedulers: ScanSchedulers, financial_statistics: Rc>, outbound_payments_instructions_sub_opt: Option>, - payable_payments_setup_msg_payload_sub_opt: Option>, + payable_payments_setup_msg_payload_sub_opt: Option>, retrieve_transactions_sub_opt: Option>, request_transaction_receipts_subs_opt: Option>, report_inbound_payments_sub_opt: Option>, @@ -547,11 +547,8 @@ impl Accountant { Some(msg.peer_actors.blockchain_bridge.retrieve_transactions); self.report_inbound_payments_sub_opt = Some(msg.peer_actors.accountant.report_inbound_payments); - self.payable_payments_setup_msg_payload_sub_opt = Some( - msg.peer_actors - .blockchain_bridge - .initial_payable_payment_setup_msg, - ); + self.payable_payments_setup_msg_payload_sub_opt = + Some(msg.peer_actors.blockchain_bridge.qualified_paybles_message); self.report_sent_payables_sub_opt = Some(msg.peer_actors.accountant.report_sent_payments); self.ui_message_sub_opt = Some(msg.peer_actors.ui_gateway.node_to_ui_message_sub); self.request_transaction_receipts_subs_opt = Some( @@ -1347,8 +1344,8 @@ mod tests { system.run(); let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); assert_eq!( - blockchain_bridge_recording.get_record::(0), - &PayablePaymentsSetupMsgPayload { + blockchain_bridge_recording.get_record::(0), + &QualifiedPayablesMessage { qualified_payables: vec![payable_account], response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1433,7 +1430,7 @@ mod tests { let agent = PayablePaymentsAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp); let accounts = vec![account_1, account_2]; let payable_payments_setup_msg = PayablePaymentsSetupMsg { - payload: PayablePaymentsSetupMsgPayload { + payables: QualifiedPayablesMessage { qualified_payables: accounts.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1452,7 +1449,7 @@ mod tests { let (actual_payload, actual_agent_id_stamp) = actual_payable_payments_setup_msg_guts; assert_eq!( actual_payload, - PayablePaymentsSetupMsgPayload { + QualifiedPayablesMessage { qualified_payables: accounts.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1464,8 +1461,8 @@ mod tests { assert!(is_adjustment_required_params.is_empty()); let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); let payments_instructions = blockchain_bridge_recording - .get_record_partial_eq_less::(0); - assert_eq!(payments_instructions.checked_accounts, accounts); + .get_record::(0); + assert_eq!(payments_instructions.affordable_accounts, accounts); assert_eq!( payments_instructions.response_skeleton_opt, Some(ResponseSkeleton { @@ -1522,7 +1519,7 @@ mod tests { client_id: 12, context_id: 55, }; - let payload = PayablePaymentsSetupMsgPayload { + let payload = QualifiedPayablesMessage { qualified_payables: vec![unadjusted_account_1.clone(), unadjusted_account_2.clone()], response_skeleton_opt: Some(response_skeleton), }; @@ -1530,7 +1527,7 @@ mod tests { let agent = PayablePaymentsAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_first_phase); let payable_payments_setup_msg = PayablePaymentsSetupMsg { - payload: payload.clone(), + payables: payload.clone(), agent: Box::new(agent), }; // In the real world the agents are identical, here they bear different ids @@ -1539,7 +1536,7 @@ mod tests { let agent = PayablePaymentsAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_second_phase); let payments_instructions = OutboundPaymentsInstructions { - checked_accounts: vec![adjusted_account_1.clone(), adjusted_account_2.clone()], + affordable_accounts: vec![adjusted_account_1.clone(), adjusted_account_2.clone()], agent: Box::new(agent), response_skeleton_opt: Some(response_skeleton), }; @@ -1562,20 +1559,26 @@ mod tests { assert_eq!(system.run(), 0); let after = SystemTime::now(); let mut adjust_payments_params = adjust_payments_params_arc.lock().unwrap(); - let (actual_guts_of_awaited_adjustment, captured_now, logger_clone) = + let (actual_fields_of_awaited_adjustment, captured_now, logger_clone) = adjust_payments_params.remove(0); let (actual_adjustment, actual_payload, actual_agent_id_stamp) = - actual_guts_of_awaited_adjustment; + actual_fields_of_awaited_adjustment; assert_eq!(actual_adjustment, Adjustment::MasqToken); assert_eq!(actual_payload, payload); assert_eq!(actual_agent_id_stamp, agent_id_stamp_first_phase); - assert!(before <= captured_now && captured_now <= after); + assert!( + before <= captured_now && captured_now <= after, + "captured timestamp should have been between {:?} and {:?} but was {:?}", + before, + after, + captured_now + ); assert!(adjust_payments_params.is_empty()); let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); let payments_instructions = blockchain_bridge_recording - .get_record_partial_eq_less::(0); + .get_record::(0); assert_eq!( - payments_instructions.checked_accounts, + payments_instructions.affordable_accounts, vec![adjusted_account_1, adjusted_account_2] ); assert_eq!( @@ -1811,10 +1814,10 @@ mod tests { system.run(); let blockchain_bridge_recorder = blockchain_bridge_recording_arc.lock().unwrap(); assert_eq!(blockchain_bridge_recorder.len(), 1); - let message = blockchain_bridge_recorder.get_record::(0); + let message = blockchain_bridge_recorder.get_record::(0); assert_eq!( message, - &PayablePaymentsSetupMsgPayload { + &QualifiedPayablesMessage { qualified_payables, response_skeleton_opt: None, } @@ -2122,7 +2125,7 @@ mod tests { let payable_scanner = ScannerMock::new() .begin_scan_params(&begin_scan_params_arc) .begin_scan_result(Err(BeginScanError::NothingToProcess)) - .begin_scan_result(Ok(PayablePaymentsSetupMsgPayload { + .begin_scan_result(Ok(QualifiedPayablesMessage { qualified_payables: vec![make_payable_account(123)], response_skeleton_opt: None, })) @@ -2331,7 +2334,7 @@ mod tests { PayableDaoMock::default().non_pending_payables_result(qualified_payables.clone()); let (blockchain_bridge, _, blockchain_bridge_recordings_arc) = make_recorder(); let blockchain_bridge = blockchain_bridge - .system_stop_conditions(match_every_type_id!(PayablePaymentsSetupMsgPayload)); + .system_stop_conditions(match_every_type_id!(QualifiedPayablesMessage)); let system = System::new("scan_for_payable_message_triggers_payment_for_balances_over_the_curve"); let peer_actors = peer_actors_builder() @@ -2351,10 +2354,10 @@ mod tests { system.run(); let blockchain_bridge_recordings = blockchain_bridge_recordings_arc.lock().unwrap(); - let message = blockchain_bridge_recordings.get_record::(0); + let message = blockchain_bridge_recordings.get_record::(0); assert_eq!( message, - &PayablePaymentsSetupMsgPayload { + &QualifiedPayablesMessage { qualified_payables, response_skeleton_opt: None, } @@ -2369,8 +2372,8 @@ mod tests { let (blockchain_bridge, _, blockchain_bridge_recording) = make_recorder(); let blockchain_bridge_addr = blockchain_bridge .system_stop_conditions(match_every_type_id!( - PayablePaymentsSetupMsgPayload, - PayablePaymentsSetupMsgPayload + QualifiedPayablesMessage, + QualifiedPayablesMessage )) .start(); let pps_for_blockchain_bridge_sub = blockchain_bridge_addr.clone().recipient(); @@ -2431,12 +2434,12 @@ mod tests { let recording = blockchain_bridge_recording.lock().unwrap(); let messages_received = recording.len(); assert_eq!(messages_received, 2); - let first_message: &PayablePaymentsSetupMsgPayload = recording.get_record(0); + let first_message: &QualifiedPayablesMessage = recording.get_record(0); assert_eq!( first_message.response_skeleton_opt, message_before.response_skeleton_opt ); - let second_message: &PayablePaymentsSetupMsgPayload = recording.get_record(1); + let second_message: &QualifiedPayablesMessage = recording.get_record(1); assert_eq!( second_message.response_skeleton_opt, message_after.response_skeleton_opt diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index 0f53b0d71..fbd3b391a 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -74,7 +74,7 @@ pub enum AnalysisError {} mod tests { use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; use crate::accountant::scanners::payable_payments_setup_msg::{ - PayablePaymentsSetupMsg, PayablePaymentsSetupMsgPayload, + PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::test_utils::{make_payable_account, PayablePaymentsAgentMock}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; @@ -98,7 +98,7 @@ mod tests { .consuming_wallet_balances_result(Some(consuming_wallet_balances)) .estimated_transaction_fee_total_result(1_000_000_000_000_000); let non_required = PayablePaymentsSetupMsg { - payload: PayablePaymentsSetupMsgPayload { + payables: QualifiedPayablesMessage { qualified_payables: vec![payable_1.clone(), payable_2.clone()], response_skeleton_opt: None, }, @@ -118,7 +118,7 @@ mod tests { .consuming_wallet_balances_result(Some(consuming_wallet_balances)) .estimated_transaction_fee_total_result(1_000_000_000_000_000); let should_require = PayablePaymentsSetupMsg { - payload: PayablePaymentsSetupMsgPayload { + payables: QualifiedPayablesMessage { qualified_payables: vec![payable_1, payable_2], response_skeleton_opt: None, }, diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 9b06eea9f..527a05f08 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -9,7 +9,7 @@ pub mod scanners_utils; use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PayableDao, PendingPayable}; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDao; use crate::accountant::database_access_objects::receivable_dao::ReceivableDao; -use crate::accountant::scanners::payable_payments_setup_msg::{PayablePaymentsSetupMsgPayload, PayablePaymentsSetupMsg}; +use crate::accountant::scanners::payable_payments_setup_msg::{QualifiedPayablesMessage, PayablePaymentsSetupMsg}; use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; use crate::accountant::scanners::scan_mid_procedures::{ AwaitedAdjustment, PayableScannerMiddleProcedures, MultistagePayableScanner, @@ -64,7 +64,7 @@ use time::OffsetDateTime; use web3::types::{TransactionReceipt, H256}; pub struct Scanners { - pub payable: Box>, + pub payable: Box>, pub pending_payable: Box>, pub receivable: Box>, } @@ -185,13 +185,13 @@ pub struct PayableScanner { pub payment_adjuster: Box, } -impl Scanner for PayableScanner { +impl Scanner for PayableScanner { fn begin_scan( &mut self, timestamp: SystemTime, response_skeleton_opt: Option, logger: &Logger, - ) -> Result { + ) -> Result { if let Some(timestamp) = self.scan_started_at() { return Err(BeginScanError::ScanAlreadyRunning(timestamp)); } @@ -220,7 +220,7 @@ impl Scanner for PayableScanner { qualified_payables.len() ); let future_payload = - PayablePaymentsSetupMsgPayload::new(qualified_payables, response_skeleton_opt); + QualifiedPayablesMessage::new(qualified_payables, response_skeleton_opt); Ok(future_payload) } } @@ -267,9 +267,9 @@ impl PayableScannerMiddleProcedures for PayableScanner { Ok(None) => { //TODO will be decoupled with Web3 by GH-696 Ok(Either::Left(OutboundPaymentsInstructions { - checked_accounts: msg.payload.qualified_payables, + affordable_accounts: msg.payables.qualified_payables, agent: msg.agent, - response_skeleton_opt: msg.payload.response_skeleton_opt, + response_skeleton_opt: msg.payables.response_skeleton_opt, })) } Ok(Some(adjustment)) => Ok(Either::Right(AwaitedAdjustment::new(msg, adjustment))), @@ -287,7 +287,7 @@ impl PayableScannerMiddleProcedures for PayableScanner { } } -impl MultistagePayableScanner for PayableScanner {} +impl MultistagePayableScanner for PayableScanner {} impl PayableScanner { pub fn new( @@ -1037,7 +1037,7 @@ mod tests { }; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoError; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t}; - use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsgPayload; + use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::PendingPayableScanReport; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::{Correct, Failed}; use crate::blockchain::blockchain_interface::{ @@ -1169,7 +1169,7 @@ mod tests { assert_eq!(timestamp, Some(now)); assert_eq!( result, - Ok(PayablePaymentsSetupMsgPayload { + Ok(QualifiedPayablesMessage { qualified_payables: qualified_payable_accounts.clone(), response_skeleton_opt: None, }) @@ -2854,7 +2854,7 @@ mod tests { let logger = Logger::new(test_name); let log_handler = TestLogHandler::new(); - assert_elapsed_time_in_mark_as_ended::( + assert_elapsed_time_in_mark_as_ended::( &mut PayableScannerBuilder::new().build(), "Payables", test_name, diff --git a/node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs b/node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs index 192c35a4d..b2d3b75b9 100644 --- a/node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs +++ b/node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs @@ -25,15 +25,12 @@ use web3::types::U256; //* defaulted limit pub trait PayablePaymentsAgent: Send { - // The nature of a method of this kind lies in the possibility of the need to - // refuse the consultant's and leave the parameter out for uselessness - // e.g. Cardano does not require user's own choice of fee size - fn conclude_required_fee_per_computed_unit( + fn set_required_fee_per_computed_unit( &mut self, - consultant: &dyn PersistentConfiguration, + persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError>; - fn set_up_pending_transaction_id(&mut self, id: U256); - fn set_up_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances); + fn set_pending_transaction_id(&mut self, id: U256); + fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances); fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128; fn consuming_wallet_balances(&self) -> Option; fn required_fee_per_computed_unit(&self) -> Option; diff --git a/node/src/accountant/scanners/payable_payments_agent_web3.rs b/node/src/accountant/scanners/payable_payments_agent_web3.rs index d51ec5b11..3010e257d 100644 --- a/node/src/accountant/scanners/payable_payments_agent_web3.rs +++ b/node/src/accountant/scanners/payable_payments_agent_web3.rs @@ -8,28 +8,28 @@ use web3::types::U256; #[derive(Debug, Clone)] pub struct PayablePaymentsAgentWeb3 { gas_limit_const_part: u64, - upmost_added_gas_margin: u64, - consuming_wallet_balance_opt: Option, + maximum_added_gas_margin: u64, + consuming_wallet_balances_opt: Option, pending_transaction_id_opt: Option, gwei_per_computed_unit_opt: Option, } impl PayablePaymentsAgent for PayablePaymentsAgentWeb3 { - fn conclude_required_fee_per_computed_unit( + fn set_required_fee_per_computed_unit( &mut self, - consultant: &dyn PersistentConfiguration, + persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError> { - let gas_price_gwei = consultant.gas_price()?; + let gas_price_gwei = persistent_config.gas_price()?; self.gwei_per_computed_unit_opt = Some(gas_price_gwei); Ok(()) } - fn set_up_pending_transaction_id(&mut self, id: U256) { + fn set_pending_transaction_id(&mut self, id: U256) { self.pending_transaction_id_opt.replace(id); } - fn set_up_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { - self.consuming_wallet_balance_opt.replace(balances); + fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { + self.consuming_wallet_balances_opt.replace(balances); } fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128 { @@ -38,11 +38,11 @@ impl PayablePaymentsAgent for PayablePaymentsAgentWeb3 { .expect("gas price was not set") as u128; number_of_transactions as u128 * gas_price - * (self.upmost_added_gas_margin + self.gas_limit_const_part) as u128 + * (self.maximum_added_gas_margin + self.gas_limit_const_part) as u128 } fn consuming_wallet_balances(&self) -> Option { - self.consuming_wallet_balance_opt + self.consuming_wallet_balances_opt } fn required_fee_per_computed_unit(&self) -> Option { @@ -62,8 +62,8 @@ impl PayablePaymentsAgentWeb3 { pub fn new(gas_limit_const_part: u64) -> Self { Self { gas_limit_const_part, - upmost_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, - consuming_wallet_balance_opt: None, + maximum_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + consuming_wallet_balances_opt: None, pending_transaction_id_opt: None, gwei_per_computed_unit_opt: None, } @@ -92,12 +92,12 @@ mod tests { assert_eq!(subject.gas_limit_const_part, 455); assert_eq!( - subject.upmost_added_gas_margin, + subject.maximum_added_gas_margin, WEB3_MAXIMAL_GAS_LIMIT_MARGIN ); assert_eq!(subject.pending_transaction_id_opt, None); assert_eq!(subject.gwei_per_computed_unit_opt, None); - assert_eq!(subject.consuming_wallet_balance_opt, None) + assert_eq!(subject.consuming_wallet_balances_opt, None) } #[test] @@ -105,7 +105,7 @@ mod tests { let persistent_config = PersistentConfigurationMock::default().gas_price_result(Ok(130)); let mut subject = PayablePaymentsAgentWeb3::new(12345); - let result = subject.conclude_required_fee_per_computed_unit(&persistent_config); + let result = subject.set_required_fee_per_computed_unit(&persistent_config); assert_eq!(result, Ok(())); assert_eq!(subject.required_fee_per_computed_unit(), Some(130)) @@ -117,7 +117,7 @@ mod tests { .gas_price_result(Err(PersistentConfigError::TransactionError)); let mut subject = PayablePaymentsAgentWeb3::new(12345); - let result = subject.conclude_required_fee_per_computed_unit(&persistent_config); + let result = subject.set_required_fee_per_computed_unit(&persistent_config); assert_eq!(result, Err(PersistentConfigError::TransactionError)); } @@ -126,7 +126,7 @@ mod tests { fn set_and_get_methods_for_pending_transaction_id_work() { let mut subject = PayablePaymentsAgentWeb3::new(12345); - subject.set_up_pending_transaction_id(U256::from(654)); + subject.set_pending_transaction_id(U256::from(654)); assert_eq!(subject.pending_transaction_id(), Some(U256::from(654))) } @@ -139,7 +139,7 @@ mod tests { masq_token_balance_in_minor_units: U256::from(30_000), }; - subject.set_up_consuming_wallet_balances(consuming_wallet_balances.clone()); + subject.set_consuming_wallet_balances(consuming_wallet_balances.clone()); assert_eq!( subject.consuming_wallet_balances(), @@ -149,16 +149,17 @@ mod tests { #[test] fn estimated_transaction_fee_works() { - let mut one_agent = PayablePaymentsAgentWeb3::new(11_111); let persistent_config = PersistentConfigurationMock::default() .gas_price_result(Ok(122)) .gas_price_result(Ok(550)); + let mut one_agent = PayablePaymentsAgentWeb3::new(11_111); + let mut second_agent = PayablePaymentsAgentWeb3::new(444); + one_agent - .conclude_required_fee_per_computed_unit(&persistent_config) + .set_required_fee_per_computed_unit(&persistent_config) .unwrap(); - let mut second_agent = PayablePaymentsAgentWeb3::new(444); second_agent - .conclude_required_fee_per_computed_unit(&persistent_config) + .set_required_fee_per_computed_unit(&persistent_config) .unwrap(); assert_eq!( diff --git a/node/src/accountant/scanners/payable_payments_setup_msg.rs b/node/src/accountant/scanners/payable_payments_setup_msg.rs index b8c3ea7bf..46be8c120 100644 --- a/node/src/accountant/scanners/payable_payments_setup_msg.rs +++ b/node/src/accountant/scanners/payable_payments_setup_msg.rs @@ -7,13 +7,13 @@ use actix::Message; use std::fmt::Debug; #[derive(Debug, Message, PartialEq, Eq, Clone)] -pub struct PayablePaymentsSetupMsgPayload { +pub struct QualifiedPayablesMessage { // On purpose restricted visibility pub(in crate::accountant) qualified_payables: Vec, pub response_skeleton_opt: Option, } -impl PayablePaymentsSetupMsgPayload { +impl QualifiedPayablesMessage { // On purpose restricted visibility pub(in crate::accountant) fn new( qualified_payables: Vec, @@ -26,7 +26,7 @@ impl PayablePaymentsSetupMsgPayload { } } -impl SkeletonOptHolder for PayablePaymentsSetupMsgPayload { +impl SkeletonOptHolder for QualifiedPayablesMessage { fn skeleton_opt(&self) -> Option { self.response_skeleton_opt } @@ -34,23 +34,18 @@ impl SkeletonOptHolder for PayablePaymentsSetupMsgPayload { #[derive(Message)] pub struct PayablePaymentsSetupMsg { - pub payload: PayablePaymentsSetupMsgPayload, + pub payables: QualifiedPayablesMessage, pub agent: Box, } -// To be able to construct that msg outside Accountant -impl - From<( - PayablePaymentsSetupMsgPayload, - Box, - )> for PayablePaymentsSetupMsg -{ - fn from( - (payload, agent): ( - PayablePaymentsSetupMsgPayload, - Box, - ), +impl PayablePaymentsSetupMsg { + pub fn new( + qualified_payables_msg: QualifiedPayablesMessage, + payable_payments_agent: Box, ) -> Self { - PayablePaymentsSetupMsg { payload, agent } + Self { + payables: qualified_payables_msg, + agent: payable_payments_agent, + } } } diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 1f68418c5..c457f4541 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -16,7 +16,7 @@ use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t, use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; use crate::accountant::scanners::payable_payments_setup_msg::{ - PayablePaymentsSetupMsg, PayablePaymentsSetupMsgPayload, + PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::scanners::scan_mid_procedures::{ AwaitedAdjustment, MultistagePayableScanner, PayableScannerMiddleProcedures, @@ -1401,14 +1401,15 @@ impl PayableThresholdsGaugeMock { #[derive(Default)] pub struct PaymentAdjusterMock { //the tuple represents guts of unclonable PayablePaymentsSetupMsg - is_adjustment_required_params: - Arc>>, - is_adjustment_required_results: RefCell, AnalysisError>>>, + search_for_indispensable_adjustment_params: + Arc>>, + search_for_indispensable_adjustment_results: + RefCell, AnalysisError>>>, //the tuple represents guts of unclonable AwaitedAdjustment adjust_payments_params: Arc< Mutex< Vec<( - (Adjustment, PayablePaymentsSetupMsgPayload, ArbitraryIdStamp), + (Adjustment, QualifiedPayablesMessage, ArbitraryIdStamp), SystemTime, Logger, )>, @@ -1423,11 +1424,16 @@ impl PaymentAdjuster for PaymentAdjusterMock { msg: &PayablePaymentsSetupMsg, logger: &Logger, ) -> Result, AnalysisError> { - self.is_adjustment_required_params.lock().unwrap().push(( - (msg.payload.clone(), msg.agent.arbitrary_id_stamp()), - logger.clone(), - )); - self.is_adjustment_required_results.borrow_mut().remove(0) + self.search_for_indispensable_adjustment_params + .lock() + .unwrap() + .push(( + (msg.payables.clone(), msg.agent.arbitrary_id_stamp()), + logger.clone(), + )); + self.search_for_indispensable_adjustment_results + .borrow_mut() + .remove(0) } fn adjust_payments( @@ -1439,7 +1445,7 @@ impl PaymentAdjuster for PaymentAdjusterMock { self.adjust_payments_params.lock().unwrap().push(( ( setup.adjustment, - setup.original_setup_msg.payload.clone(), + setup.original_setup_msg.payables.clone(), setup.original_setup_msg.agent.arbitrary_id_stamp(), ), now, @@ -1452,9 +1458,9 @@ impl PaymentAdjuster for PaymentAdjusterMock { impl PaymentAdjusterMock { pub fn is_adjustment_required_params( mut self, - params: &Arc>>, + params: &Arc>>, ) -> Self { - self.is_adjustment_required_params = params.clone(); + self.search_for_indispensable_adjustment_params = params.clone(); self } @@ -1462,7 +1468,7 @@ impl PaymentAdjusterMock { self, result: Result, AnalysisError>, ) -> Self { - self.is_adjustment_required_results + self.search_for_indispensable_adjustment_results .borrow_mut() .push(result); self @@ -1473,7 +1479,7 @@ impl PaymentAdjusterMock { params: &Arc< Mutex< Vec<( - (Adjustment, PayablePaymentsSetupMsgPayload, ArbitraryIdStamp), + (Adjustment, QualifiedPayablesMessage, ArbitraryIdStamp), SystemTime, Logger, )>, @@ -1491,11 +1497,11 @@ impl PaymentAdjusterMock { } //in order to bypass restricted visibility -pub fn make_payable_payment_setup_msg_payload( +pub fn make_qualified_payables_message( qualified_payables: Vec, response_skeleton_opt: Option, -) -> PayablePaymentsSetupMsgPayload { - PayablePaymentsSetupMsgPayload { +) -> QualifiedPayablesMessage { + QualifiedPayablesMessage { qualified_payables, response_skeleton_opt, } @@ -1536,7 +1542,7 @@ where implement_as_any!(); } -impl MultistagePayableScanner for NullScanner {} +impl MultistagePayableScanner for NullScanner {} impl PayableScannerMiddleProcedures for NullScanner {} @@ -1649,12 +1655,12 @@ impl ScannerMock { } } -impl MultistagePayableScanner - for ScannerMock +impl MultistagePayableScanner + for ScannerMock { } -impl PayableScannerMiddleProcedures for ScannerMock {} +impl PayableScannerMiddleProcedures for ScannerMock {} impl ScanSchedulers { pub fn update_scheduler( @@ -1694,7 +1700,7 @@ pub struct PayablePaymentsAgentMock { } impl PayablePaymentsAgent for PayablePaymentsAgentMock { - fn conclude_required_fee_per_computed_unit( + fn set_required_fee_per_computed_unit( &mut self, persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError> { @@ -1707,14 +1713,14 @@ impl PayablePaymentsAgent for PayablePaymentsAgentMock { .remove(0) } - fn set_up_pending_transaction_id(&mut self, id: U256) { + fn set_pending_transaction_id(&mut self, id: U256) { self.set_up_pending_transaction_id_params .lock() .unwrap() .push(id); } - fn set_up_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { + fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { self.set_up_consuming_wallet_balances_params .lock() .unwrap() diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 41dc05071..e2c308e78 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -3,7 +3,7 @@ use crate::accountant::database_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; use crate::accountant::scanners::payable_payments_setup_msg::{ - PayablePaymentsSetupMsg, PayablePaymentsSetupMsgPayload, + PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::{ ReceivedPayments, ResponseSkeleton, ScanError, SentPayables, SkeletonOptHolder, @@ -138,10 +138,10 @@ impl Handler for BlockchainBridge { } } -impl Handler for BlockchainBridge { +impl Handler for BlockchainBridge { type Result = (); - fn handle(&mut self, msg: PayablePaymentsSetupMsgPayload, _ctx: &mut Self::Context) { + fn handle(&mut self, msg: QualifiedPayablesMessage, _ctx: &mut Self::Context) { self.handle_scan( Self::handle_payable_payments_setup_msg_payload, ScanType::Payables, @@ -266,7 +266,7 @@ impl BlockchainBridge { BlockchainBridgeSubs { bind: recipient!(addr, BindMessage), outbound_payments_instructions: recipient!(addr, OutboundPaymentsInstructions), - initial_payable_payment_setup_msg: recipient!(addr, PayablePaymentsSetupMsgPayload), + qualified_paybles_message: recipient!(addr, QualifiedPayablesMessage), retrieve_transactions: recipient!(addr, RetrieveTransactions), ui_sub: recipient!(addr, NodeFromUiMessage), request_transaction_receipts: recipient!(addr, RequestTransactionReceipts), @@ -275,7 +275,7 @@ impl BlockchainBridge { fn handle_payable_payments_setup_msg_payload( &mut self, - msg: PayablePaymentsSetupMsgPayload, + incoming_message: QualifiedPayablesMessage, ) -> Result<(), String> { let consuming_wallet = match self.consuming_wallet_opt.as_ref() { Some(wallet) => wallet, @@ -289,11 +289,11 @@ impl BlockchainBridge { }; // TODO GH-707 should see about rewriting these individual calls into a batch query - let gas_balance = match self + let transaction_fee_balance = match self .blockchain_interface .get_transaction_fee_balance(consuming_wallet) { - Ok(gas_balance) => gas_balance, + Ok(balance) => balance, Err(e) => { return Err(format!( "Did not find out gas balance of the consuming wallet: {:?}", @@ -316,15 +316,15 @@ impl BlockchainBridge { let consuming_wallet_balances = { ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: gas_balance, + transaction_fee_balance_in_minor_units: transaction_fee_balance, masq_token_balance_in_minor_units: token_balance, } }; let mut agent = self.blockchain_interface.mobilize_payable_payments_agent(); - agent.set_up_consuming_wallet_balances(consuming_wallet_balances); + agent.set_consuming_wallet_balances(consuming_wallet_balances); - match agent.conclude_required_fee_per_computed_unit(self.persistent_config.as_ref()) { + match agent.set_required_fee_per_computed_unit(self.persistent_config.as_ref()) { Ok(()) => (), Err(e) => { return Err(format!( @@ -334,12 +334,12 @@ impl BlockchainBridge { } } - let msg = PayablePaymentsSetupMsg::from((msg, agent)); + let outgoing_message = PayablePaymentsSetupMsg::new(incoming_message, agent); self.payable_payments_setup_subs_opt .as_ref() .expect("Accountant is unbound") - .try_send(msg) + .try_send(outgoing_message) .expect("Accountant is dead"); Ok(()) @@ -351,7 +351,7 @@ impl BlockchainBridge { ) -> Result<(), String> { let skeleton_opt = msg.response_skeleton_opt; let mut agent = msg.agent; - let checked_accounts = msg.checked_accounts; + let checked_accounts = msg.affordable_accounts; let result = self.process_payments(agent.as_mut(), checked_accounts); let locally_produced_result = match &result { @@ -482,7 +482,7 @@ impl BlockchainBridge { fn process_payments( &self, agent: &mut dyn PayablePaymentsAgent, - checked_accounts: Vec, + affordable_accounts: Vec, ) -> Result, PayableTransactionError> { let consuming_wallet = self .consuming_wallet_opt @@ -494,7 +494,7 @@ impl BlockchainBridge { .get_transaction_count(consuming_wallet) .map_err(PayableTransactionError::TransactionCount)?; - agent.set_up_pending_transaction_id(pending_tx_id); + agent.set_pending_transaction_id(pending_tx_id); let new_fingerprints_recipient = self.new_fingerprints_recipient(); @@ -502,7 +502,7 @@ impl BlockchainBridge { consuming_wallet, agent, new_fingerprints_recipient, - &checked_accounts, + &affordable_accounts, ) } @@ -526,8 +526,7 @@ mod tests { use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::test_utils::{ - make_payable_payment_setup_msg_payload, make_pending_payable_fingerprint, - PayablePaymentsAgentMock, + make_pending_payable_fingerprint, make_qualified_payables_message, PayablePaymentsAgentMock, }; use crate::blockchain::bip32::Bip32ECKeyProvider; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::Correct; @@ -699,7 +698,7 @@ mod tests { let addr = subject.start(); let subject_subs = BlockchainBridge::make_subs_from(&addr); let peer_actors = peer_actors_builder().accountant(accountant).build(); - let payload_msg = make_payable_payment_setup_msg_payload( + let payload_msg = make_qualified_payables_message( qualified_payables.clone(), Some(ResponseSkeleton { client_id: 11122, @@ -739,8 +738,8 @@ mod tests { ); let accountant_received_payment = accountant_recording_arc.lock().unwrap(); let actual_pps_msg: &PayablePaymentsSetupMsg = - accountant_received_payment.get_record_partial_eq_less(0); - assert_eq!(actual_pps_msg.payload, payload_msg); + accountant_received_payment.get_record(0); + assert_eq!(actual_pps_msg.payables, payload_msg); assert_eq!(actual_pps_msg.agent.arbitrary_id_stamp(), agent_id_stamp); assert_eq!(accountant_received_payment.len(), 1); } @@ -766,7 +765,7 @@ mod tests { ); subject.logger = Logger::new(test_name); subject.scan_error_subs_opt = Some(scan_error_recipient); - let request = make_payable_payment_setup_msg_payload( + let request = make_qualified_payables_message( vec![PayableAccount { wallet: make_wallet("blah"), balance_wei: 42, @@ -804,8 +803,8 @@ mod tests { } #[test] - fn initial_payable_payment_setup_msg_fails_on_inspection_of_gas_balance() { - let test_name = "initial_payable_payment_setup_msg_fails_on_inspection_of_gas_balance"; + fn qualified_payables_message_fails_on_inspection_of_gas_balance() { + let test_name = "qualified_payables_message_fails_on_inspection_of_gas_balance"; let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_result(Err(BlockchainError::QueryFailed( "So lazy and yet you're asking for your account balances?".to_string(), @@ -817,8 +816,8 @@ mod tests { } #[test] - fn initial_payable_payment_setup_msg_fails_on_inspection_of_token_balance() { - let test_name = "initial_payable_payment_setup_msg_fails_on_inspection_of_token_balance"; + fn qualified_payables_message_fails_on_inspection_of_token_balance() { + let test_name = "qualified_payables_message_fails_on_inspection_of_token_balance"; let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_result(Ok(U256::from(45678))) .get_token_balance_result(Err(BlockchainError::QueryFailed( @@ -840,7 +839,7 @@ mod tests { false, None, ); - let request = make_payable_payment_setup_msg_payload( + let request = make_qualified_payables_message( vec![PayableAccount { wallet: make_wallet("blah"), balance_wei: 4254, @@ -879,7 +878,7 @@ mod tests { false, Some(consuming_wallet), ); - let request = make_payable_payment_setup_msg_payload( + let request = make_qualified_payables_message( vec![PayableAccount { wallet: make_wallet("blah"), balance_wei: 123456, @@ -959,7 +958,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - checked_accounts: accounts.clone(), + affordable_accounts: accounts.clone(), agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1025,7 +1024,7 @@ mod tests { ); subject.sent_payable_subs_opt = Some(recipient); let request = OutboundPaymentsInstructions { - checked_accounts: vec![PayableAccount { + affordable_accounts: vec![PayableAccount { wallet: make_wallet("blah"), balance_wei: 42, last_paid_timestamp: SystemTime::now(), @@ -1095,7 +1094,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - checked_accounts: accounts, + affordable_accounts: accounts, agent: Box::new(PayablePaymentsAgentMock::default()), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1138,7 +1137,7 @@ mod tests { } #[test] - fn process_payments_returns_error_fetching_pending_nonce() { + fn process_payments_returns_error_fetching_pending_transaction_id() { let blockchain_interface_mock = BlockchainInterfaceMock::default() .get_transaction_count_result(Err(BlockchainError::QueryFailed( "What the hack...??".to_string(), diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index e846d99bf..c30d85b73 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -640,7 +640,7 @@ where gas_price: u64, ) -> Result { let data = Self::transaction_data(recipient, amount); - let gas_limit = self.required_gas_limit(data.as_slice()); + let gas_limit = self.compute_gas_limit(data.as_slice()); let gas_price = gwei_to_wei::(gas_price); let transaction_parameters = TransactionParameters { nonce: Some(nonce), @@ -702,7 +702,7 @@ where data } - fn required_gas_limit(&self, data: &[u8]) -> U256 { + fn compute_gas_limit(&self, data: &[u8]) -> U256 { ethereum_types::U256::try_from(data.iter().fold(self.gas_limit_const_part, |acc, v| { acc + if v == &0u8 { 4 } else { 68 } })) diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index bf434b9ed..817492b5a 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -2,7 +2,7 @@ use crate::accountant::database_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsgPayload; +use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; @@ -25,7 +25,7 @@ pub struct BlockchainBridgeConfig { pub struct BlockchainBridgeSubs { pub bind: Recipient, pub outbound_payments_instructions: Recipient, - pub initial_payable_payment_setup_msg: Recipient, + pub qualified_paybles_message: Recipient, pub retrieve_transactions: Recipient, pub ui_sub: Recipient, pub request_transaction_receipts: Recipient, @@ -39,7 +39,7 @@ impl Debug for BlockchainBridgeSubs { #[derive(Message)] pub struct OutboundPaymentsInstructions { - pub checked_accounts: Vec, + pub affordable_accounts: Vec, pub agent: Box, pub response_skeleton_opt: Option, } diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index 69df4f8a3..bd6dbb2d7 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -903,9 +903,6 @@ pub mod unshared_test_utils { interval: Duration, ctx: &'a mut Context, ) -> Box { - if !cfg!(test) { - panic!("NotifyLaterHandleMock outside test tree") - } self.notify_later_params .lock() .unwrap() @@ -1047,15 +1044,17 @@ pub mod unshared_test_utils { fn arbitrary_id_stamp(&self) -> ArbitraryIdStamp { match self.arbitrary_id_stamp_opt { Some(id) => id, - // At some mockable methods with present params, the best they can do is to - // ask for an ArbitraryId of the argument. If that needs to happen once it will - // happen always actually, even in cases where we won't be interested in checking - // the id up again. If we do nothing the call of this method will probably blow up, - // because the filed it points to is optional and is likely set to None. - // To avoid confusion from setting up a useless id stamp we provide a null id - // stamp, which allows for both calling this method without a direct punishment - // (if the id isn't set manually) but also setting the assertion on fire if it cannot - // match the expected id stamp when we suddenly do care + // For some mock implementations of methods with args, the best they can do to + // preserve these args for assertions is to take the ArbitraryId of the argument. + // If such code is set once it will happen in all tests using this mock and calling + // the method. However also in cases where we aren't really interested in checking + // that id. If we did nothing the call of this method would blow up because + // the carrying field is likely to be implemented as optional with the value defaulted + // to None. + // As a prevention of confusion from a set, yet useless id stamp, we'll put a null + // type of the id stamp in that place, allowing for both to call this method not risking a direct + // punishment (if the id isn't set manually) but also set the assertion on fire + // if it doesn't match the expected id when we write a test where we do care None => ArbitraryIdStamp::null(), } } diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index 347e844c5..965f8ab76 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. #![cfg(test)] use crate::accountant::scanners::payable_payments_setup_msg::{ - PayablePaymentsSetupMsg, PayablePaymentsSetupMsgPayload, + PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::ReportTransactionReceipts; use crate::accountant::{ @@ -131,7 +131,7 @@ recorder_message_handler_t_m_p!(ExpiredCoresPackage); recorder_message_handler_t_m_p!(ExpiredCoresPackage); recorder_message_handler_t_m_p!(InboundClientData); recorder_message_handler_t_m_p!(InboundServerData); -recorder_message_handler_t_m_p!(PayablePaymentsSetupMsgPayload); +recorder_message_handler_t_m_p!(QualifiedPayablesMessage); recorder_message_handler_t_m_p!(IncipientCoresPackage); recorder_message_handler_t_m_p!(NewPasswordMessage); recorder_message_handler_t_m_p!(NewPublicIp); @@ -302,16 +302,6 @@ impl Recording { .unwrap_or_else(|e| panic!("{}", e)) } - pub fn get_record_partial_eq_less(&self, index: usize) -> &T - where - T: Any + Send, - { - let wrapped_msg: &PretendedMatchable = self - .get_record_inner_body(index) - .unwrap_or_else(|e| panic!("{}", e)); - &wrapped_msg.0 - } - pub fn get_record_opt(&self, index: usize) -> Option<&T> where T: Any + Send, @@ -319,7 +309,7 @@ impl Recording { self.get_record_inner_body(index).ok() } - fn get_record_inner_body(&self, index: usize) -> Result<&T, String> { + fn get_record_inner_body(&self, index: usize) -> Result<&T, String> { let item_box = match self.messages.get(index) { Some(item_box) => item_box, None => { @@ -330,14 +320,20 @@ impl Recording { )) } }; - let item_opt = item_box.downcast_ref::(); - - match item_opt { + match item_box.downcast_ref::() { Some(item) => Ok(item), - None => Err(format!( - "Message {:?} could not be downcast to the expected type", - item_box - )), + None => { + // checking for less common but possible other type of an actor message, without PartialEq implemented + let item_opt = item_box.downcast_ref::>(); + + match item_opt { + Some(item) => Ok(&item.0), + None => Err(format!( + "Message {:?} could not be downcast to the expected type", + item_box + )), + } + } } } } @@ -479,7 +475,7 @@ pub fn make_blockchain_bridge_subs_from(addr: &Addr) -> BlockchainBrid BlockchainBridgeSubs { bind: recipient!(addr, BindMessage), outbound_payments_instructions: recipient!(addr, OutboundPaymentsInstructions), - initial_payable_payment_setup_msg: recipient!(addr, PayablePaymentsSetupMsgPayload), + qualified_paybles_message: recipient!(addr, QualifiedPayablesMessage), retrieve_transactions: recipient!(addr, RetrieveTransactions), ui_sub: recipient!(addr, NodeFromUiMessage), request_transaction_receipts: recipient!(addr, RequestTransactionReceipts), From d0b42ff096ce7afd71bdd9412a85547446bdde4d Mon Sep 17 00:00:00 2001 From: Bert Date: Sat, 12 Aug 2023 13:35:16 +0200 Subject: [PATCH 02/10] GH-672: another batch of fixes --- node/src/accountant/mod.rs | 23 +++--- node/src/accountant/payment_adjuster.rs | 60 ++++---------- .../scanners/mid_scan_procedures/mod.rs | 3 + .../payable_scanner/agent_abstract_layer.rs} | 0 .../payable_scanner/agent_web3.rs} | 6 +- .../payable_scanner/mod.rs} | 18 +++-- .../payable_scanner/setup_msg.rs} | 2 +- node/src/accountant/scanners/mod.rs | 21 ++--- node/src/accountant/test_utils.rs | 65 ++++++---------- node/src/actor_system_factory.rs | 10 +-- node/src/blockchain/blockchain_bridge.rs | 78 ++++++++----------- node/src/blockchain/blockchain_interface.rs | 4 +- node/src/blockchain/test_utils.rs | 2 +- node/src/sub_lib/accountant.rs | 2 +- node/src/sub_lib/blockchain_bridge.rs | 4 +- node/src/test_utils/recorder.rs | 6 +- .../test_utils/recorder_stop_conditions.rs | 2 +- 17 files changed, 125 insertions(+), 181 deletions(-) create mode 100644 node/src/accountant/scanners/mid_scan_procedures/mod.rs rename node/src/accountant/scanners/{payable_payments_agent_abstract_layer.rs => mid_scan_procedures/payable_scanner/agent_abstract_layer.rs} (100%) rename node/src/accountant/scanners/{payable_payments_agent_web3.rs => mid_scan_procedures/payable_scanner/agent_web3.rs} (94%) rename node/src/accountant/scanners/{scan_mid_procedures.rs => mid_scan_procedures/payable_scanner/mod.rs} (68%) rename node/src/accountant/scanners/{payable_payments_setup_msg.rs => mid_scan_procedures/payable_scanner/setup_msg.rs} (92%) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 6f9a0257e..877dff4fc 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -30,7 +30,9 @@ use crate::accountant::database_access_objects::utils::{ use crate::accountant::financials::visibility_restricted_module::{ check_query_is_within_tech_limits, financials_entry_check, }; -use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ + PayablePaymentsSetupMsg, QualifiedPayablesMessage, +}; use crate::accountant::scanners::{ScanSchedulers, Scanners}; use crate::blockchain::blockchain_bridge::{ PendingPayableFingerprint, PendingPayableFingerprintSeeds, RetrieveTransactions, @@ -67,7 +69,6 @@ use masq_lib::messages::{FromMessageBody, ToMessageBody, UiFinancialsRequest}; use masq_lib::ui_gateway::MessageTarget::ClientId; use masq_lib::ui_gateway::{NodeFromUiMessage, NodeToUiMessage}; use masq_lib::utils::ExpectValue; -use scanners::payable_payments_setup_msg::PayablePaymentsSetupMsg; use std::any::type_name; #[cfg(test)] use std::default::Default; @@ -1052,7 +1053,7 @@ mod tests { prove_that_crash_request_handler_is_hooked_up, AssertionsMessage, }; use crate::test_utils::{make_paying_wallet, make_wallet}; - use crate::{match_every_type_id, match_every_type_id_partial_eq_less}; + use crate::{match_every_type_id, match_every_type_id_without_partial_eq}; use actix::{Arbiter, System}; use ethereum_types::U64; use ethsign_crypto::Keccak256; @@ -1407,7 +1408,7 @@ mod tests { let is_adjustment_required_params_arc = Arc::new(Mutex::new(vec![])); let (blockchain_bridge, _, blockchain_bridge_recording_arc) = make_recorder(); let instructions_recipient = blockchain_bridge - .system_stop_conditions(match_every_type_id_partial_eq_less!( + .system_stop_conditions(match_every_type_id_without_partial_eq!( OutboundPaymentsInstructions )) .start() @@ -1460,8 +1461,8 @@ mod tests { assert_eq!(actual_agent_id_stamp, agent_id_stamp); assert!(is_adjustment_required_params.is_empty()); let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); - let payments_instructions = blockchain_bridge_recording - .get_record::(0); + let payments_instructions = + blockchain_bridge_recording.get_record::(0); assert_eq!(payments_instructions.affordable_accounts, accounts); assert_eq!( payments_instructions.response_skeleton_opt, @@ -1499,7 +1500,7 @@ mod tests { let adjust_payments_params_arc = Arc::new(Mutex::new(vec![])); let (blockchain_bridge, _, blockchain_bridge_recording_arc) = make_recorder(); let report_recipient = blockchain_bridge - .system_stop_conditions(match_every_type_id_partial_eq_less!( + .system_stop_conditions(match_every_type_id_without_partial_eq!( OutboundPaymentsInstructions )) .start() @@ -1575,8 +1576,8 @@ mod tests { ); assert!(adjust_payments_params.is_empty()); let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); - let payments_instructions = blockchain_bridge_recording - .get_record::(0); + let payments_instructions = + blockchain_bridge_recording.get_record::(0); assert_eq!( payments_instructions.affordable_accounts, vec![adjusted_account_1, adjusted_account_2] @@ -3180,8 +3181,8 @@ mod tests { let mut transaction_receipt_tx_2_fourth_round = TransactionReceipt::default(); transaction_receipt_tx_2_fourth_round.status = Some(U64::from(1)); // confirmed let agent = PayablePaymentsAgentMock::default() - .set_up_consuming_wallet_balances_params(&set_up_consuming_balances_params_arc) - .conclude_required_fee_per_computed_unit_result(Ok(())); + .set_consuming_wallet_balances_params(&set_up_consuming_balances_params_arc) + .set_required_fee_per_computed_unit_result(Ok(())); let transaction_fee_balance = U256::from(444_555_666_777_u64); let token_balance = U256::from(111_111_111_111_111_111_u64); let blockchain_interface = BlockchainInterfaceMock::default() diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index fbd3b391a..d9ca32b84 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsg; -use crate::accountant::scanners::scan_mid_procedures::AwaitedAdjustment; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::PreparedAdjustment; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use masq_lib::logger::Logger; #[cfg(test)] @@ -17,7 +17,7 @@ pub trait PaymentAdjuster { fn adjust_payments( &self, - setup: AwaitedAdjustment, + setup: PreparedAdjustment, now: SystemTime, logger: &Logger, ) -> OutboundPaymentsInstructions; @@ -38,7 +38,7 @@ impl PaymentAdjuster for PaymentAdjusterReal { fn adjust_payments( &self, - _setup: AwaitedAdjustment, + _setup: PreparedAdjustment, _now: SystemTime, _logger: &Logger, ) -> OutboundPaymentsInstructions { @@ -73,63 +73,37 @@ pub enum AnalysisError {} #[cfg(test)] mod tests { use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; - use crate::accountant::scanners::payable_payments_setup_msg::{ + use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::test_utils::{make_payable_account, PayablePaymentsAgentMock}; - use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; - use web3::types::U256; #[test] fn search_for_indispensable_adjustment_always_returns_none() { init_test_logging(); let test_name = "is_adjustment_required_always_returns_none"; - let mut payable_1 = make_payable_account(111); - payable_1.balance_wei = 100_000_000; - let mut payable_2 = make_payable_account(222); - payable_2.balance_wei = 200_000_000; - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::from(1_001_000_000_000_u64), - masq_token_balance_in_minor_units: U256::from(301_000_000), - }; - let agent_for_enough = PayablePaymentsAgentMock::default() - .consuming_wallet_balances_result(Some(consuming_wallet_balances)) - .estimated_transaction_fee_total_result(1_000_000_000_000_000); - let non_required = PayablePaymentsSetupMsg { + let mut payable = make_payable_account(111); + payable.balance_wei = 100_000_000; + let agent = PayablePaymentsAgentMock::default(); + let setup_msg = PayablePaymentsSetupMsg { payables: QualifiedPayablesMessage { - qualified_payables: vec![payable_1.clone(), payable_2.clone()], + qualified_payables: vec![payable], response_skeleton_opt: None, }, - agent: Box::new(agent_for_enough), + agent: Box::new(agent), }; let logger = Logger::new(test_name); let subject = PaymentAdjusterReal::new(); - let non_required_result = - subject.search_for_indispensable_adjustment(&non_required, &logger); - - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::from(999_000_000_000_u64), - masq_token_balance_in_minor_units: U256::from(299_000_000), - }; - let agent_for_insufficient = PayablePaymentsAgentMock::default() - .consuming_wallet_balances_result(Some(consuming_wallet_balances)) - .estimated_transaction_fee_total_result(1_000_000_000_000_000); - let should_require = PayablePaymentsSetupMsg { - payables: QualifiedPayablesMessage { - qualified_payables: vec![payable_1, payable_2], - response_skeleton_opt: None, - }, - agent: Box::new(agent_for_insufficient), - }; - - let should_require_result = - subject.search_for_indispensable_adjustment(&should_require, &logger); + let result = subject.search_for_indispensable_adjustment(&setup_msg, &logger); - assert_eq!(non_required_result, Ok(None)); - assert_eq!(should_require_result, Ok(None)); + assert_eq!(result, Ok(None)); TestLogHandler::default().exists_no_log_containing(test_name); + // Nobody in this test asked about the wallet balances and the transaction fee + // requirement, yet we got through with the final None. + // How do we know? The mock agent didn't blow up while missing these + // results } } diff --git a/node/src/accountant/scanners/mid_scan_procedures/mod.rs b/node/src/accountant/scanners/mid_scan_procedures/mod.rs new file mode 100644 index 000000000..16331e4bf --- /dev/null +++ b/node/src/accountant/scanners/mid_scan_procedures/mod.rs @@ -0,0 +1,3 @@ +// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. + +pub mod payable_scanner; diff --git a/node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_abstract_layer.rs similarity index 100% rename from node/src/accountant/scanners/payable_payments_agent_abstract_layer.rs rename to node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_abstract_layer.rs diff --git a/node/src/accountant/scanners/payable_payments_agent_web3.rs b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs similarity index 94% rename from node/src/accountant/scanners/payable_payments_agent_web3.rs rename to node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs index 3010e257d..dcdb125ed 100644 --- a/node/src/accountant/scanners/payable_payments_agent_web3.rs +++ b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use web3::types::U256; @@ -72,8 +72,8 @@ impl PayablePaymentsAgentWeb3 { #[cfg(test)] mod tests { - use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; - use crate::accountant::scanners::payable_payments_agent_web3::{ + use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; + use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_web3::{ PayablePaymentsAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::db_config::persistent_configuration::PersistentConfigError; diff --git a/node/src/accountant/scanners/scan_mid_procedures.rs b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs similarity index 68% rename from node/src/accountant/scanners/scan_mid_procedures.rs rename to node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs index 52433ebc8..b2ece800c 100644 --- a/node/src/accountant/scanners/scan_mid_procedures.rs +++ b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs @@ -1,7 +1,11 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +pub mod agent_abstract_layer; +pub mod agent_web3; +pub mod setup_msg; + use crate::accountant::payment_adjuster::Adjustment; -use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::scanners::Scanner; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use actix::Message; @@ -9,37 +13,37 @@ use itertools::Either; use masq_lib::logger::Logger; pub trait MultistagePayableScanner: - Scanner + PayableScannerMiddleProcedures + Scanner + PayableScannerMidScanProcedures where BeginMessage: Message, EndMessage: Message, { } -pub trait PayableScannerMiddleProcedures { +pub trait PayableScannerMidScanProcedures { fn try_skipping_payment_adjustment( &self, _msg: PayablePaymentsSetupMsg, _logger: &Logger, - ) -> Result, String> { + ) -> Result, String> { intentionally_blank!() } fn perform_payment_adjustment( &self, - _setup: AwaitedAdjustment, + _setup: PreparedAdjustment, _logger: &Logger, ) -> OutboundPaymentsInstructions { intentionally_blank!() } } -pub struct AwaitedAdjustment { +pub struct PreparedAdjustment { pub original_setup_msg: PayablePaymentsSetupMsg, pub adjustment: Adjustment, } -impl AwaitedAdjustment { +impl PreparedAdjustment { pub fn new(original_setup_msg: PayablePaymentsSetupMsg, adjustment: Adjustment) -> Self { Self { original_setup_msg, diff --git a/node/src/accountant/scanners/payable_payments_setup_msg.rs b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs similarity index 92% rename from node/src/accountant/scanners/payable_payments_setup_msg.rs rename to node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs index 46be8c120..ab4521f74 100644 --- a/node/src/accountant/scanners/payable_payments_setup_msg.rs +++ b/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; use actix::Message; use std::fmt::Debug; diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 527a05f08..8374d370a 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1,19 +1,12 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod payable_payments_agent_abstract_layer; -pub mod payable_payments_agent_web3; -pub mod payable_payments_setup_msg; -pub mod scan_mid_procedures; +pub mod mid_scan_procedures; pub mod scanners_utils; use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PayableDao, PendingPayable}; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDao; use crate::accountant::database_access_objects::receivable_dao::ReceivableDao; -use crate::accountant::scanners::payable_payments_setup_msg::{QualifiedPayablesMessage, PayablePaymentsSetupMsg}; use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; -use crate::accountant::scanners::scan_mid_procedures::{ - AwaitedAdjustment, PayableScannerMiddleProcedures, MultistagePayableScanner, -}; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableTransactingErrorEnum::{ LocallyCausedError, RemotelyCausedErrors, }; @@ -62,6 +55,8 @@ use std::time::{Duration, SystemTime}; use time::format_description::parse; use time::OffsetDateTime; use web3::types::{TransactionReceipt, H256}; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, PayableScannerMidScanProcedures}; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{PayablePaymentsSetupMsg, QualifiedPayablesMessage}; pub struct Scanners { pub payable: Box>, @@ -254,12 +249,12 @@ impl Scanner for PayableScanner { implement_as_any!(); } -impl PayableScannerMiddleProcedures for PayableScanner { +impl PayableScannerMidScanProcedures for PayableScanner { fn try_skipping_payment_adjustment( &self, msg: PayablePaymentsSetupMsg, logger: &Logger, - ) -> Result, String> { + ) -> Result, String> { match self .payment_adjuster .search_for_indispensable_adjustment(&msg, logger) @@ -272,14 +267,14 @@ impl PayableScannerMiddleProcedures for PayableScanner { response_skeleton_opt: msg.payables.response_skeleton_opt, })) } - Ok(Some(adjustment)) => Ok(Either::Right(AwaitedAdjustment::new(msg, adjustment))), + Ok(Some(adjustment)) => Ok(Either::Right(PreparedAdjustment::new(msg, adjustment))), Err(_e) => todo!("be implemented with GH-711"), } } fn perform_payment_adjustment( &self, - setup: AwaitedAdjustment, + setup: PreparedAdjustment, logger: &Logger, ) -> OutboundPaymentsInstructions { let now = SystemTime::now(); @@ -1037,7 +1032,7 @@ mod tests { }; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoError; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t}; - use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; + use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::PendingPayableScanReport; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::{Correct, Failed}; use crate::blockchain::blockchain_interface::{ diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index c457f4541..4cc8f74d3 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -14,12 +14,12 @@ use crate::accountant::database_access_objects::receivable_dao::{ }; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t, CustomQuery}; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::payable_payments_setup_msg::{ +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; -use crate::accountant::scanners::scan_mid_procedures::{ - AwaitedAdjustment, MultistagePayableScanner, PayableScannerMiddleProcedures, +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::{ + MultistagePayableScanner, PayableScannerMidScanProcedures, PreparedAdjustment, }; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableThresholdsGauge; use crate::accountant::scanners::{ @@ -1438,7 +1438,7 @@ impl PaymentAdjuster for PaymentAdjusterMock { fn adjust_payments( &self, - setup: AwaitedAdjustment, + setup: PreparedAdjustment, now: SystemTime, logger: &Logger, ) -> OutboundPaymentsInstructions { @@ -1544,7 +1544,7 @@ where impl MultistagePayableScanner for NullScanner {} -impl PayableScannerMiddleProcedures for NullScanner {} +impl PayableScannerMidScanProcedures for NullScanner {} impl Default for NullScanner { fn default() -> Self { @@ -1660,7 +1660,7 @@ impl MultistagePayableScanner { } -impl PayableScannerMiddleProcedures for ScannerMock {} +impl PayableScannerMidScanProcedures for ScannerMock {} impl ScanSchedulers { pub fn update_scheduler( @@ -1687,15 +1687,12 @@ impl ScanSchedulers { #[derive(Default)] pub struct PayablePaymentsAgentMock { - conclude_required_fee_per_computed_unit_params: Arc>>, - conclude_required_fee_per_computed_unit_results: - RefCell>>, - set_up_pending_transaction_id_params: Arc>>, - set_up_consuming_wallet_balances_params: Arc>>, - consuming_wallet_balances_results: RefCell>>, + set_required_fee_per_computed_unit_params: Arc>>, + set_required_fee_per_computed_unit_results: RefCell>>, + set_pending_transaction_id_params: Arc>>, + set_consuming_wallet_balances_params: Arc>>, required_fee_per_computed_unit_results: RefCell>>, pending_transaction_id_results: RefCell>>, - estimated_transaction_fee_total_results: Option, arbitrary_id_stamp_opt: Option, } @@ -1704,24 +1701,24 @@ impl PayablePaymentsAgent for PayablePaymentsAgentMock { &mut self, persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError> { - self.conclude_required_fee_per_computed_unit_params + self.set_required_fee_per_computed_unit_params .lock() .unwrap() .push(persistent_config.arbitrary_id_stamp()); - self.conclude_required_fee_per_computed_unit_results + self.set_required_fee_per_computed_unit_results .borrow_mut() .remove(0) } fn set_pending_transaction_id(&mut self, id: U256) { - self.set_up_pending_transaction_id_params + self.set_pending_transaction_id_params .lock() .unwrap() .push(id); } fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { - self.set_up_consuming_wallet_balances_params + self.set_consuming_wallet_balances_params .lock() .unwrap() .push(balances) @@ -1749,50 +1746,34 @@ impl PayablePaymentsAgent for PayablePaymentsAgentMock { } impl PayablePaymentsAgentMock { - pub fn conclude_required_fee_per_computed_unit_params( + pub fn set_required_fee_per_computed_unit_params( mut self, params: &Arc>>, ) -> Self { - self.conclude_required_fee_per_computed_unit_params = params.clone(); + self.set_required_fee_per_computed_unit_params = params.clone(); self } - pub fn conclude_required_fee_per_computed_unit_result( + pub fn set_required_fee_per_computed_unit_result( self, result: Result<(), PersistentConfigError>, ) -> Self { - self.conclude_required_fee_per_computed_unit_results + self.set_required_fee_per_computed_unit_results .borrow_mut() .push(result); self } - pub fn set_up_pending_transaction_id_params(mut self, params: &Arc>>) -> Self { - self.set_up_pending_transaction_id_params = params.clone(); + pub fn set_pending_transaction_id_params(mut self, params: &Arc>>) -> Self { + self.set_pending_transaction_id_params = params.clone(); self } - pub fn set_up_consuming_wallet_balances_params( + pub fn set_consuming_wallet_balances_params( mut self, params: &Arc>>, ) -> Self { - self.set_up_consuming_wallet_balances_params = params.clone(); - self - } - - pub fn estimated_transaction_fee_params(self, _params: &Arc>>) -> Self { - todo!("to be implemented by GH-711") - } - - pub fn estimated_transaction_fee_total_result(mut self, result: u128) -> Self { - self.estimated_transaction_fee_total_results = Some(result); - self - } - - pub fn consuming_wallet_balances_result(self, result: Option) -> Self { - self.consuming_wallet_balances_results - .borrow_mut() - .push(result); + self.set_consuming_wallet_balances_params = params.clone(); self } diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index 5265286bf..a9b312285 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -510,14 +510,14 @@ impl ActorFactory for ActorFactoryReal { let crashable = is_crashable(config); let wallet_opt = config.consuming_wallet_opt.clone(); let data_directory = config.data_directory.clone(); - let chain_id = config.blockchain_bridge_config.chain; + let chain = config.blockchain_bridge_config.chain; let arbiter = Arbiter::builder().stop_system_on_panic(true); let addr: Addr = arbiter.start(move |_| { - let (blockchain_interface, persistent_config) = BlockchainBridge::make_connections( - blockchain_service_url_opt, - data_directory, - chain_id, + let blockchain_interface= BlockchainBridge::initialize_blockchain_interface( + blockchain_service_url_opt.as_ref().map(|url|url.as_str()), + chain, ); + let persistent_config = BlockchainBridge::initialize_persistent_configuration(&data_directory); BlockchainBridge::new( blockchain_interface, persistent_config, diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index e2c308e78..ecb02185c 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::payable_payments_setup_msg::{ +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::{ @@ -36,7 +36,7 @@ use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use masq_lib::messages::ScanType; use masq_lib::ui_gateway::NodeFromUiMessage; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::SystemTime; use web3::transports::{EventLoopHandle, Http}; use web3::types::{TransactionReceipt, H256}; @@ -213,42 +213,33 @@ impl BlockchainBridge { } } - pub fn make_connections( - blockchain_service_url: Option, - data_directory: PathBuf, - chain: Chain, - ) -> ( - Box, - Box, - ) { - let blockchain_interface: Box = { - match blockchain_service_url { - Some(url) => match Http::new(&url) { - Ok((event_loop_handle, transport)) => { - Self::construct_blockchain_interface(event_loop_handle, transport, chain) - } - Err(e) => panic!("Invalid blockchain node URL: {:?}", e), - }, - None => Box::new(BlockchainInterfaceClandestine::new(chain)), - } - }; + pub fn initialize_persistent_configuration(data_directory: &Path)->Box{ let config_dao = Box::new(ConfigDaoReal::new( DbInitializerReal::default() .initialize( - &data_directory, + data_directory, DbInitializationConfig::panic_on_migration(), ) - .unwrap_or_else(|err| db_connection_launch_panic(err, &data_directory)), + .unwrap_or_else(|err| db_connection_launch_panic(err, data_directory)), )); - ( - blockchain_interface, - Box::new(PersistentConfigurationReal::new(config_dao)), - ) + Box::new(PersistentConfigurationReal::new(config_dao)) + } + + pub fn initialize_blockchain_interface(blockchain_service_url_opt: Option<&str>, chain: Chain)->Box{ + match blockchain_service_url_opt { + Some(url) => match Http::new(&url) { + Ok((event_loop_handle, transport)) => { + Self::initialize_appropriate_definite_interface(event_loop_handle, transport, chain) + } + Err(e) => panic!("Invalid blockchain node URL: {:?}", e), + }, + None => Box::new(BlockchainInterfaceClandestine::new(chain)), //TODO make sure this is tested (after the merge??) + } } // TODO when we have multiple chains of fundamentally different architectures and also ability to switch them, // this should probably be replaced by a HashMap of a distinct blockchain interface for each chain - fn construct_blockchain_interface( + fn initialize_appropriate_definite_interface( http_event_loop_handle: EventLoopHandle, transport: Http, chain: Chain, @@ -629,10 +620,9 @@ mod tests { #[should_panic(expected = "Invalid blockchain node URL")] fn invalid_blockchain_url_produces_panic() { let data_directory = PathBuf::new(); //never reached - let blockchain_service_url = Some("http://λ:8545".to_string()); - let _ = BlockchainBridge::make_connections( + let blockchain_service_url = Some("http://λ:8545"); + let _ = BlockchainBridge::initialize_blockchain_interface( blockchain_service_url, - data_directory, DEFAULT_CHAIN, ); } @@ -653,11 +643,11 @@ mod tests { let agent_id_stamp = ArbitraryIdStamp::new(); let agent = PayablePaymentsAgentMock::default() .set_arbitrary_id_stamp(agent_id_stamp) - .set_up_consuming_wallet_balances_params(&set_up_consuming_wallet_balances_params_arc) - .conclude_required_fee_per_computed_unit_params( + .set_consuming_wallet_balances_params(&set_up_consuming_wallet_balances_params_arc) + .set_required_fee_per_computed_unit_params( &conclude_required_fee_per_computed_unit_params_arc, ) - .conclude_required_fee_per_computed_unit_result(Ok(())); + .set_required_fee_per_computed_unit_result(Ok(())); let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_params(&get_transaction_fee_balance_params_arc) .get_transaction_fee_balance_result(Ok(transaction_fee_balance)) @@ -737,8 +727,7 @@ mod tests { vec![persistent_config_id_stamp] ); let accountant_received_payment = accountant_recording_arc.lock().unwrap(); - let actual_pps_msg: &PayablePaymentsSetupMsg = - accountant_received_payment.get_record(0); + let actual_pps_msg: &PayablePaymentsSetupMsg = accountant_received_payment.get_record(0); assert_eq!(actual_pps_msg.payables, payload_msg); assert_eq!(actual_pps_msg.agent.arbitrary_id_stamp(), agent_id_stamp); assert_eq!(accountant_received_payment.len(), 1); @@ -862,10 +851,9 @@ mod tests { #[test] fn handle_payable_payments_setup_msg_payload_fails_on_gas_price_query_on_behalf_of_the_agent() { - let agent = PayablePaymentsAgentMock::default() - .conclude_required_fee_per_computed_unit_result(Err( - PersistentConfigError::DatabaseError("siesta".to_string()), - )); + let agent = PayablePaymentsAgentMock::default().set_required_fee_per_computed_unit_result( + Err(PersistentConfigError::DatabaseError("siesta".to_string())), + ); let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_result(Ok(U256::from(456789))) .get_token_balance_result(Ok(U256::from(7890123456_u64))) @@ -953,7 +941,7 @@ mod tests { let arbitrary_id_stamp = ArbitraryIdStamp::new(); let agent = PayablePaymentsAgentMock::default() .set_arbitrary_id_stamp(arbitrary_id_stamp) - .set_up_pending_transaction_id_params(&set_up_pending_transaction_id_params_arc); + .set_pending_transaction_id_params(&set_up_pending_transaction_id_params_arc); send_bind_message!(subject_subs, peer_actors); let _ = addr @@ -1892,10 +1880,8 @@ mod tests { ); let act = |data_dir: &Path| { - BlockchainBridge::make_connections( - Some("http://127.0.0.1".to_string()), - data_dir.to_path_buf(), - Chain::PolyMumbai, + BlockchainBridge::initialize_persistent_configuration( + data_dir ); }; diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index c30d85b73..2c2dd5055 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::accountant::{comma_joined_stringifiable, gwei_to_wei}; use crate::blockchain::batch_payable_tools::{BatchPayableTools, BatchPayableToolsReal}; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; @@ -720,7 +720,7 @@ mod tests { use super::*; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::gwei_to_wei; - use crate::accountant::scanners::payable_payments_agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; + use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::accountant::test_utils::{ make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, PayablePaymentsAgentMock, diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index a2ef577e4..70d511d4d 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::blockchain::batch_payable_tools::BatchPayableTools; use web3::transports::{Batch, EventLoopHandle, Http}; use web3::types::{Address, Bytes, SignedTransaction, TransactionParameters, U256}; diff --git a/node/src/sub_lib/accountant.rs b/node/src/sub_lib/accountant.rs index aa5e8a26c..2987fa598 100644 --- a/node/src/sub_lib/accountant.rs +++ b/node/src/sub_lib/accountant.rs @@ -3,7 +3,7 @@ use crate::accountant::database_access_objects::banned_dao::BannedDaoFactory; use crate::accountant::database_access_objects::payable_dao::PayableDaoFactory; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoFactory; use crate::accountant::database_access_objects::receivable_dao::ReceivableDaoFactory; -use crate::accountant::scanners::payable_payments_setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::{ checked_conversion, Accountant, ReceivedPayments, ReportTransactionReceipts, ScanError, SentPayables, diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 817492b5a..004954101 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_payments_agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::payable_payments_setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index 965f8ab76..19e687291 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. #![cfg(test)] -use crate::accountant::scanners::payable_payments_setup_msg::{ - PayablePaymentsSetupMsg, QualifiedPayablesMessage, -}; + +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::ReportTransactionReceipts; use crate::accountant::{ ReceivedPayments, RequestTransactionReceipts, ScanError, ScanForPayables, diff --git a/node/src/test_utils/recorder_stop_conditions.rs b/node/src/test_utils/recorder_stop_conditions.rs index f1d46efc2..c75b6fa77 100644 --- a/node/src/test_utils/recorder_stop_conditions.rs +++ b/node/src/test_utils/recorder_stop_conditions.rs @@ -125,7 +125,7 @@ macro_rules! match_every_type_id{ } #[macro_export] -macro_rules! match_every_type_id_partial_eq_less { +macro_rules! match_every_type_id_without_partial_eq { ($($single_message: ident),+) => { StopConditions::All(vec![$(StopCondition::StopOnType(TypeId::of::>())),+]) } From 727d38079102e7e083c0a755913ee8f8a4ca50a4 Mon Sep 17 00:00:00 2001 From: Bert Date: Sat, 12 Aug 2023 23:12:18 +0200 Subject: [PATCH 03/10] GH-672: refactoring some complicated test concepts for actor_system_factory and adding one test for blockchain_bridge of that kind --- node/src/accountant/mod.rs | 48 ++- node/src/actor_system_factory.rs | 435 +++++++++++++------- node/src/blockchain/blockchain_bridge.rs | 78 +++- node/src/blockchain/blockchain_interface.rs | 70 +--- node/src/bootstrapper.rs | 9 +- node/src/dispatcher.rs | 7 +- node/src/node_test_utils.rs | 11 - node/src/stream_messages.rs | 16 +- node/src/stream_reader.rs | 7 +- node/src/sub_lib/accountant.rs | 18 +- node/src/sub_lib/blockchain_bridge.rs | 24 ++ node/src/test_utils/http_test_server.rs | 71 ++++ node/src/test_utils/mod.rs | 2 + 13 files changed, 493 insertions(+), 303 deletions(-) create mode 100644 node/src/test_utils/http_test_server.rs diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 877dff4fc..936ce1ced 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -979,31 +979,6 @@ pub fn wei_to_gwei, S: Display + Copy + Div + From(wei.div(S::from(WEIS_IN_GWEI as u32))) } -#[cfg(test)] -pub mod check_sqlite_fns { - use super::*; - use crate::sub_lib::accountant::DEFAULT_PAYMENT_THRESHOLDS; - use actix::System; - - #[derive(Message)] - pub struct TestUserDefinedSqliteFnsForNewDelinquencies {} - - impl Handler for Accountant { - type Result = (); - - fn handle( - &mut self, - _msg: TestUserDefinedSqliteFnsForNewDelinquencies, - _ctx: &mut Self::Context, - ) -> Self::Result { - //will crash a test if our user-defined SQLite fns have been unregistered - self.receivable_dao - .new_delinquencies(SystemTime::now(), &DEFAULT_PAYMENT_THRESHOLDS); - System::current().stop(); - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -4481,3 +4456,26 @@ mod tests { assert_on_initialization_with_panic_on_migration(&data_dir, &act); } } + +#[cfg(test)] +pub mod assertion_messages_with_exposed_private_actor_body { + use super::*; + use crate::sub_lib::accountant::DEFAULT_PAYMENT_THRESHOLDS; + use crate::test_utils::unshared_test_utils::AssertionsMessage; + use actix::System; + + pub fn assertion_msg_to_test_registration_of_our_sqlite_fns() -> AssertionsMessage { + AssertionsMessage { + assertions: Box::new(|accountant: &mut Accountant| { + // Will crash a test if our user-defined SQLite fns have been unreachable; + // We cannot rely on failures in the DAO tests, because Account's database connection + // has to be set up specially so as to register the extra sqlite functions + + accountant + .receivable_dao + .new_delinquencies(SystemTime::now(), &DEFAULT_PAYMENT_THRESHOLDS); + System::current().stop(); + }), + } + } +} diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index a9b312285..0040ba20c 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -13,15 +13,13 @@ use super::ui_gateway::UiGateway; use crate::accountant::database_access_objects::banned_dao::{ BannedCacheLoader, BannedCacheLoaderReal, }; -use crate::blockchain::blockchain_bridge::BlockchainBridge; +use crate::blockchain::blockchain_bridge::{BlockchainBridge, BlockchainBridgeSubsFactory}; use crate::bootstrapper::CryptDEPair; use crate::database::db_initializer::DbInitializationConfig; use crate::database::db_initializer::{connection_or_panic, DbInitializer, DbInitializerReal}; use crate::db_config::persistent_configuration::PersistentConfiguration; use crate::node_configurator::configurator::Configurator; -use crate::sub_lib::accountant::{ - AccountantSubs, AccountantSubsFactory, AccountantSubsFactoryReal, DaoFactories, -}; +use crate::sub_lib::accountant::{AccountantSubs, AccountantSubsFactory, DaoFactories}; use crate::sub_lib::blockchain_bridge::BlockchainBridgeSubs; use crate::sub_lib::configurator::ConfiguratorSubs; use crate::sub_lib::cryptde::CryptDE; @@ -35,7 +33,7 @@ use crate::sub_lib::proxy_client::ProxyClientConfig; use crate::sub_lib::proxy_client::ProxyClientSubs; use crate::sub_lib::proxy_server::ProxyServerSubs; use crate::sub_lib::ui_gateway::UiGatewaySubs; -use actix::Recipient; +use actix::{Actor, Recipient}; use actix::{Addr, Arbiter}; use automap_lib::comm_layer::AutomapError; use automap_lib::control_layer::automap_control::{ @@ -71,18 +69,13 @@ impl ActorSystemFactory for ActorSystemFactoryReal { &self, config: BootstrapperConfig, actor_factory: Box, - persist_config: Box, + persistent_config: Box, ) -> StreamHandlerPoolSubs { - self.tools.validate_database_chain( - persist_config.as_ref(), - config.blockchain_bridge_config.chain, - ); - self.tools.prepare_initial_messages( - self.tools.cryptdes(), - config, - persist_config, - actor_factory, - ) + self.tools + .validate_database_chain(&*persistent_config, config.blockchain_bridge_config.chain); + let cryptdes = self.tools.cryptdes(); + self.tools + .prepare_initial_messages(cryptdes, config, persistent_config, actor_factory) } } @@ -157,13 +150,14 @@ impl ActorSystemFactoryTools for ActorSystemFactoryToolsReal { is_decentralized: config.neighborhood_config.mode.is_decentralized(), crashable: is_crashable(&config), }); - let blockchain_bridge_subs = actor_factory.make_and_start_blockchain_bridge(&config); + let blockchain_bridge_subs = actor_factory + .make_and_start_blockchain_bridge(&config, &BlockchainBridgeSubsFactory {}); let neighborhood_subs = actor_factory.make_and_start_neighborhood(cryptdes.main, &config); let accountant_subs = actor_factory.make_and_start_accountant( config.clone(), &db_initializer, &BannedCacheLoaderReal {}, - &AccountantSubsFactoryReal {}, + &AccountantSubsFactory {}, ); let ui_gateway_subs = actor_factory.make_and_start_ui_gateway(&config); let stream_handler_pool_subs = actor_factory.make_and_start_stream_handler_pool(&config); @@ -370,7 +364,7 @@ pub trait ActorFactory { config: BootstrapperConfig, db_initializer: &dyn DbInitializer, banned_cache_loader: &dyn BannedCacheLoader, - accountant_subs_factory: &dyn AccountantSubsFactory, + subs_factory: &dyn SubsFactory, ) -> AccountantSubs; fn make_and_start_ui_gateway(&self, config: &BootstrapperConfig) -> UiGatewaySubs; fn make_and_start_stream_handler_pool( @@ -378,8 +372,11 @@ pub trait ActorFactory { config: &BootstrapperConfig, ) -> StreamHandlerPoolSubs; fn make_and_start_proxy_client(&self, config: ProxyClientConfig) -> ProxyClientSubs; - fn make_and_start_blockchain_bridge(&self, config: &BootstrapperConfig) - -> BlockchainBridgeSubs; + fn make_and_start_blockchain_bridge( + &self, + config: &BootstrapperConfig, + subs_factory: &dyn SubsFactory, + ) -> BlockchainBridgeSubs; fn make_and_start_configurator(&self, config: &BootstrapperConfig) -> ConfiguratorSubs; } @@ -449,7 +446,7 @@ impl ActorFactory for ActorFactoryReal { config: BootstrapperConfig, db_initializer: &dyn DbInitializer, banned_cache_loader: &dyn BannedCacheLoader, - accountant_subs_factory: &dyn AccountantSubsFactory, + subs_factory: &dyn SubsFactory, ) -> AccountantSubs { let data_directory = config.data_directory.as_path(); let payable_dao_factory = Box::new(Accountant::dao_factory(data_directory)); @@ -469,7 +466,7 @@ impl ActorFactory for ActorFactoryReal { }, ) }); - accountant_subs_factory.make(&addr) + subs_factory.make(&addr) } fn make_and_start_ui_gateway(&self, config: &BootstrapperConfig) -> UiGatewaySubs { @@ -502,6 +499,7 @@ impl ActorFactory for ActorFactoryReal { fn make_and_start_blockchain_bridge( &self, config: &BootstrapperConfig, + subs_factory: &dyn SubsFactory, ) -> BlockchainBridgeSubs { let blockchain_service_url_opt = config .blockchain_bridge_config @@ -513,11 +511,12 @@ impl ActorFactory for ActorFactoryReal { let chain = config.blockchain_bridge_config.chain; let arbiter = Arbiter::builder().stop_system_on_panic(true); let addr: Addr = arbiter.start(move |_| { - let blockchain_interface= BlockchainBridge::initialize_blockchain_interface( - blockchain_service_url_opt.as_ref().map(|url|url.as_str()), + let blockchain_interface = BlockchainBridge::initialize_blockchain_interface( + blockchain_service_url_opt, chain, ); - let persistent_config = BlockchainBridge::initialize_persistent_configuration(&data_directory); + let persistent_config = + BlockchainBridge::initialize_persistent_configuration(&data_directory); BlockchainBridge::new( blockchain_interface, persistent_config, @@ -525,7 +524,7 @@ impl ActorFactory for ActorFactoryReal { wallet_opt, ) }); - BlockchainBridge::make_subs_from(&addr) + subs_factory.make(&addr) } fn make_and_start_configurator(&self, config: &BootstrapperConfig) -> ConfiguratorSubs { @@ -615,18 +614,30 @@ impl LogRecipientSetter for LogRecipientSetterReal { } } +// Test writing easing stuff. If further examination of the actor +// starting methods in ActorFactory is desirable. +// This allows to get the started actor's address and then messages +// can be sent to it, possibly the AssertionMessage. +pub trait SubsFactory +where + Actor: actix::Actor, +{ + fn make(&self, addr: &Addr) -> ActorSubs; +} + #[cfg(test)] mod tests { use super::*; - use crate::accountant::check_sqlite_fns::TestUserDefinedSqliteFnsForNewDelinquencies; + use crate::accountant::assertion_messages_with_exposed_private_actor_body::assertion_msg_to_test_registration_of_our_sqlite_fns; use crate::accountant::test_utils::bc_from_earning_wallet; use crate::accountant::DEFAULT_PENDING_TOO_LONG_SEC; use crate::actor_system_factory::tests::ShouldWeRunTheTest::{GoAhead, Skip}; + use crate::blockchain::blockchain_bridge::assertion_messages_with_exposed_private_actor_body::assertion_msg_to_test_blockchain_bridge_connectivity; use crate::bootstrapper::{Bootstrapper, RealUser}; use crate::database::connection_wrapper::ConnectionWrapper; + use crate::db_config::persistent_configuration::PersistentConfigurationReal; use crate::node_test_utils::{ - make_stream_handler_pool_subs_from, make_stream_handler_pool_subs_from_recorder, - start_recorder_refcell_opt, + make_stream_handler_pool_subs_from_recorder, start_recorder_refcell_opt, }; use crate::sub_lib::accountant::{PaymentThresholds, ScanIntervals}; use crate::sub_lib::blockchain_bridge::BlockchainBridgeConfig; @@ -641,6 +652,7 @@ mod tests { use crate::sub_lib::stream_handler_pool::TransmitDataMsg; use crate::sub_lib::ui_gateway::UiGatewayConfig; use crate::test_utils::automap_mocks::{AutomapControlFactoryMock, AutomapControlMock}; + use crate::test_utils::http_test_server::TestServer; use crate::test_utils::make_wallet; use crate::test_utils::neighborhood_test_utils::MIN_HOPS_COUNT_FOR_TEST; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; @@ -652,8 +664,10 @@ mod tests { }; use crate::test_utils::recorder::{make_recorder, Recorder}; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; - use crate::test_utils::unshared_test_utils::assert_on_initialization_with_panic_on_migration; use crate::test_utils::unshared_test_utils::system_killer_actor::SystemKillerActor; + use crate::test_utils::unshared_test_utils::{ + assert_on_initialization_with_panic_on_migration, AssertionsMessage, + }; use crate::test_utils::{alias_cryptde, rate_pack}; use crate::test_utils::{main_cryptde, make_cryptde_pair}; use crate::{hopper, proxy_client, proxy_server, stream_handler_pool, ui_gateway}; @@ -675,9 +689,10 @@ mod tests { TEST_DEFAULT_CHAIN, }; use masq_lib::ui_gateway::NodeFromUiMessage; - use masq_lib::utils::running_test; use masq_lib::utils::AutomapProtocol::Igdp; + use masq_lib::utils::{find_free_port, running_test}; use regex::Regex; + use serde_json::Value; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; @@ -888,7 +903,7 @@ mod tests { config: BootstrapperConfig, _db_initializer: &dyn DbInitializer, _banned_cache_loader: &dyn BannedCacheLoader, - _accountant_subs_factory: &dyn AccountantSubsFactory, + _accountant_subs_factory: &dyn SubsFactory, ) -> AccountantSubs { self.parameters .accountant_params @@ -930,6 +945,7 @@ mod tests { fn make_and_start_blockchain_bridge( &self, config: &BootstrapperConfig, + subs_factory: &dyn SubsFactory, ) -> BlockchainBridgeSubs { self.parameters .blockchain_bridge_params @@ -1050,6 +1066,107 @@ mod tests { } } + #[test] + fn make_and_start_actors_happy_path() { + let validate_database_chain_params_arc = Arc::new(Mutex::new(vec![])); + let prepare_initial_messages_params_arc = Arc::new(Mutex::new(vec![])); + let (stream_handler_pool, _, stream_handler_pool_recording_arc) = make_recorder(); + let main_cryptde = main_cryptde(); + let alias_cryptde = alias_cryptde(); + let cryptde_pair = CryptDEPair { + main: main_cryptde, + alias: alias_cryptde, + }; + let main_cryptde_public_key_expected = pk_from_cryptde_null(main_cryptde); + let alias_cryptde_public_key_expected = pk_from_cryptde_null(alias_cryptde); + let actor_factory = Box::new(ActorFactoryReal {}); + let actor_factory_raw_address_expected = addr_of!(*actor_factory); + let persistent_config_expected_arbitrary_id = ArbitraryIdStamp::new(); + let persistent_config = Box::new( + PersistentConfigurationMock::default() + .set_arbitrary_id_stamp(persistent_config_expected_arbitrary_id), + ); + let stream_holder_pool_subs = + make_stream_handler_pool_subs_from_recorder(&stream_handler_pool.start()); + let actor_system_factor_tools = ActorSystemFactoryToolsMock::default() + .validate_database_chain_params(&validate_database_chain_params_arc) + .cryptdes_result(cryptde_pair) + .prepare_initial_messages_params(&prepare_initial_messages_params_arc) + .prepare_initial_messages_result(stream_holder_pool_subs); + let data_dir = PathBuf::new().join("parent_directory/child_directory"); + let subject = ActorSystemFactoryReal::new(Box::new(actor_system_factor_tools)); + let mut bootstrapper_config = BootstrapperConfig::new(); + bootstrapper_config.blockchain_bridge_config.chain = Chain::PolyMainnet; + bootstrapper_config.data_directory = data_dir.clone(); + bootstrapper_config.db_password_opt = Some("password".to_string()); + + let result = + subject.make_and_start_actors(bootstrapper_config, actor_factory, persistent_config); + + let mut validate_database_chain_params = validate_database_chain_params_arc.lock().unwrap(); + let (persistent_config_actual_arbitrary_id, actual_chain) = + validate_database_chain_params.remove(0); + assert_eq!( + persistent_config_actual_arbitrary_id, + persistent_config_expected_arbitrary_id + ); + assert_eq!(actual_chain, Chain::PolyMainnet); + assert!(validate_database_chain_params.is_empty()); + let mut prepare_initial_messages_params = + prepare_initial_messages_params_arc.lock().unwrap(); + let ( + main_cryptde_actual, + alias_cryptde_actual, + bootstrapper_config_actual, + actor_factory_actual, + persistent_config_actual, + ) = prepare_initial_messages_params.remove(0); + let main_cryptde_public_key_actual = pk_from_cryptde_null(main_cryptde_actual.as_ref()); + assert_eq!( + main_cryptde_public_key_actual, + main_cryptde_public_key_expected + ); + let alias_cryptde_public_key_actual = pk_from_cryptde_null(alias_cryptde_actual.as_ref()); + assert_eq!( + alias_cryptde_public_key_actual, + alias_cryptde_public_key_expected + ); + assert_eq!(bootstrapper_config_actual.data_directory, data_dir); + assert_eq!( + bootstrapper_config_actual.db_password_opt, + Some("password".to_string()) + ); + assert_eq!( + addr_of!(*actor_factory_actual), + actor_factory_raw_address_expected + ); + assert_eq!( + persistent_config_actual.arbitrary_id_stamp(), + persistent_config_expected_arbitrary_id + ); + assert!(prepare_initial_messages_params.is_empty()); + verify_recipient(&result.node_from_ui_sub, &stream_handler_pool_recording_arc) + } + + fn verify_recipient( + recipient: &Recipient, + recording_arc: &Arc>, + ) { + let system = System::new("verifying_recipient_returned_in_test"); + let expected_msg = NodeFromUiMessage { + client_id: 5, + body: UiDescriptorRequest {}.tmb(1), + }; + + recipient.try_send(expected_msg.clone()).unwrap(); + + System::current().stop_with_code(0); + system.run(); + let recording = recording_arc.lock().unwrap(); + let actual_msg = recording.get_record::(0); + assert_eq!(actual_msg, &expected_msg); + } + #[test] fn make_and_start_actors_sends_bind_messages() { let actor_factory = ActorFactoryMock::new(); @@ -1863,19 +1980,38 @@ mod tests { ); } - struct AccountantSubsFactoryTestOnly { - address_leaker: Sender>, + struct SubsFactoryTestAddrLeaker + where + A: actix::Actor, + { + address_leaker: Sender>, } - impl AccountantSubsFactory for AccountantSubsFactoryTestOnly { - fn make(&self, addr: &Addr) -> AccountantSubs { + impl SubsFactoryTestAddrLeaker + where + A: actix::Actor, + { + fn send_leaker_msg_and_return_meaningless_subs( + &self, + addr: &Addr, + make_subs_from_recorder_fn: fn(&Addr) -> S, + ) -> S { self.address_leaker.try_send(addr.clone()).unwrap(); - let nonsensical_addr = Recorder::new().start(); - make_accountant_subs_from_recorder(&nonsensical_addr) + let meaningless_addr = Recorder::new().start(); + make_subs_from_recorder_fn(&meaningless_addr) } } - fn check_ongoing_usage_of_user_defined_fns_within_new_delinquencies_for_receivable_dao( + impl SubsFactory for SubsFactoryTestAddrLeaker { + fn make(&self, addr: &Addr) -> AccountantSubs { + self.send_leaker_msg_and_return_meaningless_subs( + addr, + make_accountant_subs_from_recorder, + ) + } + } + + fn verify_presence_of_user_defined_sqlite_fns_in_new_delinquencies_for_receivable_dao( ) -> ShouldWeRunTheTest { fn skip_down_to_first_line_saying_new_delinquencies( previous: impl Iterator, @@ -1890,10 +2026,6 @@ mod tests { }) .skip(1) } - fn user_defined_functions_detected(line_undivided_fn_body: &str) -> bool { - line_undivided_fn_body.contains(" slope_drop_high_bytes(") - && line_undivided_fn_body.contains(" slope_drop_low_bytes(") - } fn assert_is_not_trait_definition(body_lines: impl Iterator) -> String { fn yield_if_contains_semicolon(line: &str) -> Option { line.contains(';').then(|| line.to_string()) @@ -1922,6 +2054,27 @@ mod tests { } line_undivided_fn_body } + fn scope_fn_new_delinquency_alone(reader: BufReader) -> String { + let all_lines_in_the_file = reader.lines().flatten(); + let lines_with_cut_fn_trait_definition = + skip_down_to_first_line_saying_new_delinquencies(all_lines_in_the_file); + let assumed_implemented_function_body = + skip_down_to_first_line_saying_new_delinquencies( + lines_with_cut_fn_trait_definition, + ) + .take_while(|line| { + let adjusted_line: String = line + .chars() + .skip_while(|char| char.is_whitespace()) + .collect(); + !adjusted_line.starts_with("fn") + }); + assert_is_not_trait_definition(assumed_implemented_function_body) + } + fn user_defined_functions_detected(line_undivided_fn_body: &str) -> bool { + line_undivided_fn_body.contains(" slope_drop_high_bytes(") + && line_undivided_fn_body.contains(" slope_drop_low_bytes(") + } let current_dir = current_dir().unwrap(); let file_path = current_dir.join(PathBuf::from_iter([ @@ -1936,169 +2089,135 @@ mod tests { Skip => return Skip, _ => panic!( "if panics, the file receivable_dao.rs probably doesn't exist or \ - has been moved to an unexpected location" + has moved to an unexpected location" ), }, }; let reader = BufReader::new(file); - let lines_without_fn_trait_definition = - skip_down_to_first_line_saying_new_delinquencies(reader.lines().flatten()); - let function_body_ready_for_final_check = { - let assumed_implemented_function_body = - skip_down_to_first_line_saying_new_delinquencies(lines_without_fn_trait_definition) - .take_while(|line| { - let adjusted_line: String = line - .chars() - .skip_while(|char| char.is_whitespace()) - .collect(); - !adjusted_line.starts_with("fn") - }); - assert_is_not_trait_definition(assumed_implemented_function_body) - }; + let function_body_ready_for_final_check = scope_fn_new_delinquency_alone(reader); if user_defined_functions_detected(&function_body_ready_for_final_check) { GoAhead } else { - panic!("was about to test user-defined SQLite functions (slope_drop_high_bytes and slope_drop_low_bytes) - in new_delinquencies() but found out those are absent at the expected place and would leave falsely positive results") + panic!( + "was about to test user-defined SQLite functions (slope_drop_high_bytes and + slope_drop_low_bytes) in new_delinquencies() but found out those are absent at the + expected place and would leave falsely positive results" + ) } } #[test] - fn our_big_int_sqlite_functions_are_linked_to_receivable_dao_within_accountant() { - //condition: .new_delinquencies() still encompasses our user defined functions (that's why a formal check opens this test) + fn accountant_has_db_connection_that_can_make_use_of_our_own_sqlite_functions() { + //precondition: .new_delinquencies() still encompasses our meant functions, otherwise the test is false-positive if let Skip = - check_ongoing_usage_of_user_defined_fns_within_new_delinquencies_for_receivable_dao() + verify_presence_of_user_defined_sqlite_fns_in_new_delinquencies_for_receivable_dao() { - eprintln!("skipping test our_big_int_sqlite_functions_are_linked_to_receivable_dao_within_accountant; - was unable to find receivable_dao.rs"); + eprintln!( + "skipping test accountant_can_make_use_of_our_own_sqlite_functions; was unable to \ + find receivable_dao.rs" + ); return; }; let data_dir = ensure_node_home_directory_exists( "actor_system_factory", - "our_big_int_sqlite_functions_are_linked_to_receivable_dao_within_accountant", + "accountant_can_make_use_of_our_own_sqlite_functions", ); let _ = DbInitializerReal::default() .initialize(data_dir.as_ref(), DbInitializationConfig::test_default()) .unwrap(); let mut b_config = bc_from_earning_wallet(make_wallet("mine")); b_config.data_directory = data_dir; - let system = System::new( - "our_big_int_sqlite_functions_are_linked_to_receivable_dao_within_accountant", - ); let (addr_tx, addr_rv) = bounded(1); + let system = System::new("accountant_can_make_use_of_our_own_sqlite_functions"); let subject = ActorFactoryReal {}; subject.make_and_start_accountant( b_config, &DbInitializerReal::default(), &BannedCacheLoaderMock::default(), - &AccountantSubsFactoryTestOnly { + &SubsFactoryTestAddrLeaker { address_leaker: addr_tx, }, ); let accountant_addr = addr_rv.try_recv().unwrap(); - //this message also stops the system after the check + //the message stops also the system accountant_addr - .try_send(TestUserDefinedSqliteFnsForNewDelinquencies {}) + .try_send(assertion_msg_to_test_registration_of_our_sqlite_fns()) .unwrap(); assert_eq!(system.run(), 0); //we didn't blow up, it recognized the functions //this is an example of the error: "no such function: slope_drop_high_bytes" } - #[test] - fn make_and_start_actors_happy_path() { - let validate_database_chain_params_arc = Arc::new(Mutex::new(vec![])); - let prepare_initial_messages_params_arc = Arc::new(Mutex::new(vec![])); - let (recorder, _, recording_arc) = make_recorder(); - let stream_holder_pool_subs = make_stream_handler_pool_subs_from(Some(recorder)); - let mut bootstrapper_config = BootstrapperConfig::new(); - let irrelevant_data_dir = PathBuf::new().join("big_directory/small_directory"); - bootstrapper_config.blockchain_bridge_config.chain = Chain::PolyMainnet; - bootstrapper_config.data_directory = irrelevant_data_dir.clone(); - bootstrapper_config.db_password_opt = Some("chameleon".to_string()); - let main_cryptde = main_cryptde(); - let main_cryptde_public_key_before = public_key_for_dyn_cryptde_being_null(main_cryptde); - let alias_cryptde = alias_cryptde(); - let alias_cryptde_public_key_before = public_key_for_dyn_cryptde_being_null(alias_cryptde); - let actor_factory = Box::new(ActorFactoryReal {}) as Box; - let actor_factory_before_raw_address = addr_of!(*actor_factory); - let persistent_config_id = ArbitraryIdStamp::new(); - let persistent_config = Box::new( - PersistentConfigurationMock::default().set_arbitrary_id_stamp(persistent_config_id), - ); - let persistent_config_before_raw = addr_of!(*persistent_config); - let tools = ActorSystemFactoryToolsMock::default() - .cryptdes_result(CryptDEPair { - main: main_cryptde, - alias: alias_cryptde, - }) - .validate_database_chain_params(&validate_database_chain_params_arc) - .prepare_initial_messages_params(&prepare_initial_messages_params_arc) - .prepare_initial_messages_result(stream_holder_pool_subs); - let subject = ActorSystemFactoryReal::new(Box::new(tools)); - - let result = - subject.make_and_start_actors(bootstrapper_config, actor_factory, persistent_config); + impl SubsFactory + for SubsFactoryTestAddrLeaker + { + fn make(&self, addr: &Addr) -> BlockchainBridgeSubs { + self.send_leaker_msg_and_return_meaningless_subs(addr, make_blockchain_bridge_subs_from) + } + } - let mut validate_database_chain_params = validate_database_chain_params_arc.lock().unwrap(); - let (persistent_config_id_captured, chain) = validate_database_chain_params.remove(0); - assert!(validate_database_chain_params.is_empty()); - assert_eq!(persistent_config_id_captured, persistent_config_id); - assert_eq!(chain, Chain::PolyMainnet); - let mut prepare_initial_messages_params = - prepare_initial_messages_params_arc.lock().unwrap(); - let ( - main_cryptde_after, - alias_cryptde_after, - bootstrapper_config_after, - actor_factory_after, - persistent_config_after, - ) = prepare_initial_messages_params.remove(0); - assert!(prepare_initial_messages_params.is_empty()); - let main_cryptde_public_key_after = - public_key_for_dyn_cryptde_being_null(main_cryptde_after.as_ref()); - assert_eq!( - main_cryptde_public_key_after, - main_cryptde_public_key_before - ); - let alias_cryptde_public_key_after = - public_key_for_dyn_cryptde_being_null(alias_cryptde_after.as_ref()); - assert_eq!( - alias_cryptde_public_key_after, - alias_cryptde_public_key_before + #[test] + fn blockchain_bridge_connectivity_check() { + let data_dir = ensure_node_home_directory_exists( + "actor_system_factory", + "blockchain_bridge_connectivity_check", ); - assert_eq!( - bootstrapper_config_after.data_directory, - irrelevant_data_dir + let conn = DbInitializerReal::default() + .initialize(&data_dir, DbInitializationConfig::test_default()) + .unwrap(); + let mut persistent_config = PersistentConfigurationReal::from(conn); + let gas_price = 444; + persistent_config.set_gas_price(gas_price).unwrap(); + let port = find_free_port(); + let server_url = format!("http://{}:{}", &Ipv4Addr::LOCALHOST.to_string(), port); + let test_server = TestServer::start( + port, + vec![br#"{"jsonrpc":"2.0","id":0,"result":___}"#.to_vec()], ); - assert_eq!( - bootstrapper_config_after.db_password_opt, - Some("chameleon".to_string()) + let wallet = make_wallet("abc"); + let mut bootstrapper_config = BootstrapperConfig::new(); + let blockchain_service_url_opt = Some(server_url); + bootstrapper_config + .blockchain_bridge_config + .blockchain_service_url_opt = blockchain_service_url_opt; + bootstrapper_config.blockchain_bridge_config.chain = TEST_DEFAULT_CHAIN; + bootstrapper_config.data_directory = data_dir; + let (addr_tx, addr_rv) = bounded(1); + let system = System::new("blockchain_bridge_connectivity_check"); + let subject = ActorFactoryReal {}; + + subject.make_and_start_blockchain_bridge( + &bootstrapper_config, + &SubsFactoryTestAddrLeaker { + address_leaker: addr_tx, + }, ); + + let blockchain_addr = addr_rv.try_recv().unwrap(); + //the message stops also the system + blockchain_addr + .try_send(assertion_msg_to_test_blockchain_bridge_connectivity( + wallet.clone(), + gas_price, + )) + .unwrap(); + assert_eq!(system.run(), 0); + let requests = test_server.requests_so_far(); + let bodies: Vec = requests + .into_iter() + .map(|request| serde_json::from_slice(&request.body()).unwrap()) + .collect(); + eprintln!("{:?} {:?}", bodies, TEST_DEFAULT_CHAIN.rec().contract); assert_eq!( - addr_of!(*actor_factory_after), - actor_factory_before_raw_address + bodies[0]["params"][0]["data"].to_string()[35..75], + wallet.to_string()[2..] ); assert_eq!( - addr_of!(*persistent_config_after), - persistent_config_before_raw + bodies[0]["params"][0]["to"], + format!("{:?}", TEST_DEFAULT_CHAIN.rec().contract) ); - let system = System::new("make_and_start_actors_happy_path"); - let msg_of_irrelevant_choice = NodeFromUiMessage { - client_id: 5, - body: UiDescriptorRequest {}.tmb(1), - }; - result - .node_from_ui_sub - .try_send(msg_of_irrelevant_choice.clone()) - .unwrap(); - System::current().stop_with_code(0); - system.run(); - let recording = recording_arc.lock().unwrap(); - let msg = recording.get_record::(0); - assert_eq!(msg, &msg_of_irrelevant_choice); } #[test] @@ -2119,7 +2238,7 @@ mod tests { assert_on_initialization_with_panic_on_migration(&data_dir, &act); } - fn public_key_for_dyn_cryptde_being_null(cryptde: &dyn CryptDE) -> &PublicKey { + fn pk_from_cryptde_null(cryptde: &dyn CryptDE) -> &PublicKey { let null_cryptde = <&CryptDENull>::from(cryptde); null_cryptde.public_key() } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index ecb02185c..fcb0496a0 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -9,6 +9,7 @@ use crate::accountant::{ ReceivedPayments, ResponseSkeleton, ScanError, SentPayables, SkeletonOptHolder, }; use crate::accountant::{ReportTransactionReceipts, RequestTransactionReceipts}; +use crate::actor_system_factory::SubsFactory; use crate::blockchain::blockchain_interface::{ BlockchainError, BlockchainInterface, BlockchainInterfaceClandestine, BlockchainInterfaceNonClandestine, PayableTransactionError, ProcessedPayableFallible, @@ -36,7 +37,7 @@ use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use masq_lib::messages::ScanType; use masq_lib::ui_gateway::NodeFromUiMessage; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::time::SystemTime; use web3::transports::{EventLoopHandle, Http}; use web3::types::{TransactionReceipt, H256}; @@ -213,23 +214,29 @@ impl BlockchainBridge { } } - pub fn initialize_persistent_configuration(data_directory: &Path)->Box{ + pub fn initialize_persistent_configuration( + data_directory: &Path, + ) -> Box { let config_dao = Box::new(ConfigDaoReal::new( DbInitializerReal::default() - .initialize( - data_directory, - DbInitializationConfig::panic_on_migration(), - ) + .initialize(data_directory, DbInitializationConfig::panic_on_migration()) .unwrap_or_else(|err| db_connection_launch_panic(err, data_directory)), )); Box::new(PersistentConfigurationReal::new(config_dao)) } - - pub fn initialize_blockchain_interface(blockchain_service_url_opt: Option<&str>, chain: Chain)->Box{ + + pub fn initialize_blockchain_interface( + blockchain_service_url_opt: Option, + chain: Chain, + ) -> Box { match blockchain_service_url_opt { Some(url) => match Http::new(&url) { Ok((event_loop_handle, transport)) => { - Self::initialize_appropriate_definite_interface(event_loop_handle, transport, chain) + Self::initialize_appropriate_definite_interface( + event_loop_handle, + transport, + chain, + ) } Err(e) => panic!("Invalid blockchain node URL: {:?}", e), }, @@ -511,6 +518,14 @@ struct PendingTxInfo { when_sent: SystemTime, } +pub struct BlockchainBridgeSubsFactory {} + +impl SubsFactory for BlockchainBridgeSubsFactory { + fn make(&self, addr: &Addr) -> BlockchainBridgeSubs { + BlockchainBridge::make_subs_from(addr) + } +} + #[cfg(test)] mod tests { use super::*; @@ -536,7 +551,7 @@ mod tests { use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use crate::test_utils::unshared_test_utils::{ assert_on_initialization_with_panic_on_migration, configure_default_persistent_config, - prove_that_crash_request_handler_is_hooked_up, ZERO, + prove_that_crash_request_handler_is_hooked_up, AssertionsMessage, ZERO, }; use crate::test_utils::{make_paying_wallet, make_wallet}; use actix::System; @@ -554,6 +569,18 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160, H256, U256}; + impl Handler> for BlockchainBridge { + type Result = (); + + fn handle( + &mut self, + msg: AssertionsMessage, + ctx: &mut Self::Context, + ) -> Self::Result { + (msg.assertions)(self) + } + } + #[test] fn constants_have_correct_values() { assert_eq!(CRASH_KEY, "BLOCKCHAINBRIDGE"); @@ -619,8 +646,7 @@ mod tests { #[test] #[should_panic(expected = "Invalid blockchain node URL")] fn invalid_blockchain_url_produces_panic() { - let data_directory = PathBuf::new(); //never reached - let blockchain_service_url = Some("http://λ:8545"); + let blockchain_service_url = Some("http://λ:8545".to_string()); let _ = BlockchainBridge::initialize_blockchain_interface( blockchain_service_url, DEFAULT_CHAIN, @@ -1880,9 +1906,7 @@ mod tests { ); let act = |data_dir: &Path| { - BlockchainBridge::initialize_persistent_configuration( - data_dir - ); + BlockchainBridge::initialize_persistent_configuration(data_dir); }; assert_on_initialization_with_panic_on_migration(&data_dir, &act); @@ -1897,3 +1921,27 @@ mod tests { assert_eq!(web3_gas_limit_const_part(Chain::Dev), 55_000); } } + +#[cfg(test)] +pub mod assertion_messages_with_exposed_private_actor_body { + use super::*; + use crate::test_utils::unshared_test_utils::AssertionsMessage; + use actix::System; + + pub fn assertion_msg_to_test_blockchain_bridge_connectivity( + wallet: Wallet, + expected_gas_price: u64, + ) -> AssertionsMessage { + AssertionsMessage { + assertions: Box::new(move |bb: &mut BlockchainBridge| { + //the first assertion is made outside, it checks receiving this request + let _result = bb.blockchain_interface.get_token_balance(&wallet); + assert_eq!( + bb.persistent_config.gas_price().unwrap(), + expected_gas_price + ); + System::current().stop(); + }), + } + } +} diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index 2c2dd5055..f7dd9bd63 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -733,6 +733,7 @@ mod tests { }; use crate::sub_lib::blockchain_bridge::web3_gas_limit_const_part; use crate::sub_lib::wallet::Wallet; + use crate::test_utils::http_test_server::TestServer; use crate::test_utils::make_paying_wallet; use crate::test_utils::recorder::{make_recorder, Recorder}; use crate::test_utils::unshared_test_utils::decode_hex; @@ -778,69 +779,6 @@ mod tests { assert_eq!(GWEI, U256([1_000_000_000u64, 0, 0, 0])); } - struct TestServer { - port: u16, - rx: Receiver>>, - } - - impl Drop for TestServer { - fn drop(&mut self) { - self.stop(); - } - } - - impl TestServer { - fn start(port: u16, bodies: Vec>) -> Self { - std::env::set_var("SIMPLESERVER_THREADS", "1"); - let (tx, rx) = unbounded(); - let _ = thread::spawn(move || { - let bodies_arc = Arc::new(Mutex::new(bodies)); - Server::new(move |req, mut rsp| { - if req.headers().get("X-Quit").is_some() { - panic!("Server stop requested"); - } - tx.send(req).unwrap(); - let body = bodies_arc.lock().unwrap().remove(0); - Ok(rsp.body(body)?) - }) - .listen(&Ipv4Addr::LOCALHOST.to_string(), &format!("{}", port)); - }); - let deadline = Instant::now().add(Duration::from_secs(5)); - loop { - thread::sleep(Duration::from_millis(10)); - match TcpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port)) { - Ok(_) => break, - Err(e) => eprintln!("No: {:?}", e), - } - if Instant::now().gt(&deadline) { - panic!("TestServer still not started after 5sec"); - } - } - TestServer { port, rx } - } - - fn requests_so_far(&self) -> Vec>> { - let mut requests = vec![]; - while let Ok(request) = self.rx.try_recv() { - requests.push(request); - } - return requests; - } - - fn stop(&mut self) { - let mut stream = match TcpStream::connect(SocketAddr::new( - IpAddr::V4(Ipv4Addr::LOCALHOST), - self.port, - )) { - Ok(s) => s, - Err(_) => return, - }; - stream - .write(b"DELETE /irrelevant.htm HTTP/1.1\r\nX-Quit: Yes") - .unwrap(); - } - } - #[test] fn blockchain_interface_non_clandestine_returns_contract() { all_chains().iter().for_each(|chain| { @@ -890,8 +828,8 @@ mod tests { .map(|request| serde_json::from_slice(&request.body()).unwrap()) .collect(); assert_eq!( - format!("\"0x000000000000000000000000{}\"", &to[2..]), bodies[0]["params"][0]["topics"][2].to_string(), + format!("\"0x000000000000000000000000{}\"", &to[2..]), ); assert_eq!( result, @@ -1285,7 +1223,6 @@ mod tests { let _test_server = TestServer::start (port, vec![ br#"{"jsonrpc":"2.0","id":0,"result":"0x000000000000000000000000000000000000000000000000000000000000FFFQ"}"#.to_vec() ]); - let (event_loop_handle, transport) = Http::with_max_parallel( &format!("http://{}:{}", &Ipv4Addr::LOCALHOST.to_string(), port), REQUESTS_IN_PARALLEL, @@ -1523,7 +1460,7 @@ mod tests { } #[test] - fn non_clandestine_interface_send_batch_of_payables_components_are_used_together_properly() { + fn non_clandestine_interface_send_batch_of_payables_components_work_together_as_expected() { let sign_transaction_params_arc = Arc::new(Mutex::new(vec![])); let append_transaction_to_batch_params_arc = Arc::new(Mutex::new(vec![])); let new_payable_fingerprint_params_arc = Arc::new(Mutex::new(vec![])); @@ -1828,7 +1765,6 @@ mod tests { chain, web3_gas_limit_const_part(chain), ); - let system = System::new("test"); let (accountant, _, accountant_recording_arc) = make_recorder(); let recipient = accountant.start().recipient(); diff --git a/node/src/bootstrapper.rs b/node/src/bootstrapper.rs index 533c9cb41..edf2b452c 100644 --- a/node/src/bootstrapper.rs +++ b/node/src/bootstrapper.rs @@ -724,9 +724,8 @@ mod tests { use crate::discriminator::Discriminator; use crate::discriminator::UnmaskedChunk; use crate::listener_handler::{ListenerHandler, ListenerHandlerFactory}; - use crate::node_test_utils::make_stream_handler_pool_subs_from; - use crate::node_test_utils::TestLogOwner; use crate::node_test_utils::{extract_log, DirsWrapperMock, IdWrapperMock}; + use crate::node_test_utils::{make_stream_handler_pool_subs_from_recorder, TestLogOwner}; use crate::server_initializer::test_utils::LoggerInitializerWrapperMock; use crate::server_initializer::LoggerInitializerWrapper; use crate::stream_handler_pool::StreamHandlerPoolSubs; @@ -753,8 +752,8 @@ mod tests { }; use crate::test_utils::{assert_contains, rate_pack}; use crate::test_utils::{main_cryptde, make_wallet}; - use actix::Recipient; use actix::System; + use actix::{Actor, Recipient}; use crossbeam_channel::unbounded; use futures::Future; use lazy_static::lazy_static; @@ -2227,7 +2226,9 @@ mod tests { StreamHandlerPoolCluster { recording: Some(recording), awaiter: Some(awaiter), - subs: make_stream_handler_pool_subs_from(Some(stream_handler_pool)), + subs: make_stream_handler_pool_subs_from_recorder( + &stream_handler_pool.start(), + ), } }; diff --git a/node/src/dispatcher.rs b/node/src/dispatcher.rs index 583677035..415f12612 100644 --- a/node/src/dispatcher.rs +++ b/node/src/dispatcher.rs @@ -211,7 +211,7 @@ mod tests { use super::*; use crate::actor_system_factory::{ActorFactory, ActorFactoryReal}; use crate::bootstrapper::BootstrapperConfig; - use crate::node_test_utils::make_stream_handler_pool_subs_from; + use crate::node_test_utils::make_stream_handler_pool_subs_from_recorder; use crate::stream_messages::NonClandestineAttributes; use crate::sub_lib::cryptde::CryptDE; use crate::sub_lib::dispatcher::Endpoint; @@ -426,7 +426,7 @@ mod tests { let mut peer_actors = peer_actors_builder().build(); peer_actors.dispatcher = Dispatcher::make_subs_from(&subject_addr); let stream_handler_pool_subs = - make_stream_handler_pool_subs_from(Some(stream_handler_pool)); + make_stream_handler_pool_subs_from_recorder(&stream_handler_pool.start()); subject_addr .try_send(PoolBindMessage { dispatcher_subs: peer_actors.dispatcher.clone(), @@ -440,14 +440,11 @@ mod tests { System::current().stop_with_code(0); system.run(); - awaiter.await_message_count(1); let recording = recording_arc.lock().unwrap(); - let message = recording.get_record::(0); let actual_endpoint = message.endpoint.clone(); let actual_data = message.data.clone(); - assert_eq!(actual_endpoint, Endpoint::Socket(socket_addr)); assert_eq!(actual_data, data); assert_eq!(recording.len(), 1); diff --git a/node/src/node_test_utils.rs b/node/src/node_test_utils.rs index b82c663a3..8d2db493b 100644 --- a/node/src/node_test_utils.rs +++ b/node/src/node_test_utils.rs @@ -289,17 +289,6 @@ pub fn start_recorder_refcell_opt(recorder: &RefCell>) -> Addr< recorder.borrow_mut().take().unwrap().start() } -pub fn make_stream_handler_pool_subs_from( - stream_handler_pool_opt: Option, -) -> StreamHandlerPoolSubs { - let recorder = match stream_handler_pool_opt { - Some(recorder) => recorder, - None => Recorder::new(), - }; - let addr = recorder.start(); - make_stream_handler_pool_subs_from_recorder(&addr) -} - pub fn make_stream_handler_pool_subs_from_recorder(addr: &Addr) -> StreamHandlerPoolSubs { StreamHandlerPoolSubs { add_sub: recipient!(addr, AddStreamMsg), diff --git a/node/src/stream_messages.rs b/node/src/stream_messages.rs index 4b838ecdc..957dfa85d 100644 --- a/node/src/stream_messages.rs +++ b/node/src/stream_messages.rs @@ -77,10 +77,13 @@ impl Debug for PoolBindMessage { #[cfg(test)] mod tests { use super::*; - use crate::node_test_utils::make_stream_handler_pool_subs_from; - use crate::test_utils::recorder::peer_actors_builder; - use actix::System; + use crate::node_test_utils::make_stream_handler_pool_subs_from_recorder; + use crate::test_utils::recorder::{ + make_dispatcher_subs_from, make_recorder, peer_actors_builder, + }; + use actix::{Actor, System}; + //TODO can we also implement this with the newly developed infrastructure around recorder and msgs not implementing PartialEq?? impl PartialEq for AddStreamMsg { fn eq(&self, _other: &Self) -> bool { // We need to implement PartialEq so that AddStreamMsg can be received by the Recorder; @@ -96,8 +99,11 @@ mod tests { #[test] fn pool_bind_message_is_debug() { let _system = System::new("test"); - let dispatcher_subs = peer_actors_builder().build().dispatcher; - let stream_handler_pool_subs = make_stream_handler_pool_subs_from(None); + let (dispatcher, _, _) = make_recorder(); + let dispatcher_subs = make_dispatcher_subs_from(&dispatcher.start()); + let (stream_handler_pool, _, _) = make_recorder(); + let stream_handler_pool_subs = + make_stream_handler_pool_subs_from_recorder(&stream_handler_pool.start()); let neighborhood_subs = peer_actors_builder().build().neighborhood; let subject = PoolBindMessage { dispatcher_subs, diff --git a/node/src/stream_reader.rs b/node/src/stream_reader.rs index 6f297f806..f089a0226 100644 --- a/node/src/stream_reader.rs +++ b/node/src/stream_reader.rs @@ -213,7 +213,7 @@ mod tests { use crate::json_discriminator_factory::JsonDiscriminatorFactory; use crate::json_masquerader::JsonMasquerader; use crate::masquerader::Masquerader; - use crate::node_test_utils::{check_timestamp, make_stream_handler_pool_subs_from}; + use crate::node_test_utils::{check_timestamp, make_stream_handler_pool_subs_from_recorder}; use crate::stream_handler_pool::StreamHandlerPoolSubs; use crate::stream_messages::RemovedStreamType::NonClandestine; use crate::sub_lib::dispatcher::DispatcherSubs; @@ -238,7 +238,10 @@ mod tests { fn stream_handler_pool_stuff() -> (Arc>, StreamHandlerPoolSubs) { let (shp, _, recording) = make_recorder(); - (recording, make_stream_handler_pool_subs_from(Some(shp))) + ( + recording, + make_stream_handler_pool_subs_from_recorder(&shp.start()), + ) } fn dispatcher_stuff() -> (Arc>, DispatcherSubs) { diff --git a/node/src/sub_lib/accountant.rs b/node/src/sub_lib/accountant.rs index 2987fa598..07f33058a 100644 --- a/node/src/sub_lib/accountant.rs +++ b/node/src/sub_lib/accountant.rs @@ -8,6 +8,7 @@ use crate::accountant::{ checked_conversion, Accountant, ReceivedPayments, ReportTransactionReceipts, ScanError, SentPayables, }; +use crate::actor_system_factory::SubsFactory; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; use crate::sub_lib::peer_actors::{BindMessage, StartMessage}; use crate::sub_lib::wallet::Wallet; @@ -110,13 +111,9 @@ impl Debug for AccountantSubs { } } -pub trait AccountantSubsFactory { - fn make(&self, addr: &Addr) -> AccountantSubs; -} - -pub struct AccountantSubsFactoryReal {} +pub struct AccountantSubsFactory {} -impl AccountantSubsFactory for AccountantSubsFactoryReal { +impl SubsFactory for AccountantSubsFactory { fn make(&self, addr: &Addr) -> AccountantSubs { Accountant::make_subs_from(addr) } @@ -197,10 +194,9 @@ mod tests { use crate::accountant::test_utils::AccountantBuilder; use crate::accountant::{checked_conversion, Accountant}; use crate::sub_lib::accountant::{ - AccountantSubsFactory, AccountantSubsFactoryReal, MessageIdGenerator, - MessageIdGeneratorReal, PaymentThresholds, ScanIntervals, DEFAULT_EARNING_WALLET, - DEFAULT_PAYMENT_THRESHOLDS, DEFAULT_SCAN_INTERVALS, MSG_ID_INCREMENTER, - TEMPORARY_CONSUMING_WALLET, + AccountantSubsFactory, MessageIdGenerator, MessageIdGeneratorReal, PaymentThresholds, + ScanIntervals, SubsFactory, DEFAULT_EARNING_WALLET, DEFAULT_PAYMENT_THRESHOLDS, + DEFAULT_SCAN_INTERVALS, MSG_ID_INCREMENTER, TEMPORARY_CONSUMING_WALLET, }; use crate::sub_lib::wallet::Wallet; use crate::test_utils::recorder::{make_accountant_subs_from_recorder, Recorder}; @@ -257,7 +253,7 @@ mod tests { #[test] fn accountant_subs_factory_produces_proper_subs() { - let subject = AccountantSubsFactoryReal {}; + let subject = AccountantSubsFactory {}; let accountant = AccountantBuilder::default().build(); let addr = accountant.start(); diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 004954101..c30d8d2c6 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -18,6 +18,8 @@ use web3::types::U256; pub struct BlockchainBridgeConfig { pub blockchain_service_url_opt: Option, pub chain: Chain, + //TODO: actually totally ignored during the setup of the BlockchainBridge actor! + // Use it in the body or delete this field pub gas_price: u64, } @@ -65,7 +67,11 @@ pub fn web3_gas_limit_const_part(chain: Chain) -> u64 { #[cfg(test)] mod tests { + use crate::actor_system_factory::SubsFactory; + use crate::blockchain::blockchain_bridge::{BlockchainBridge, BlockchainBridgeSubsFactory}; + use crate::blockchain::test_utils::BlockchainInterfaceMock; use crate::sub_lib::blockchain_bridge::web3_gas_limit_const_part; + use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::{make_blockchain_bridge_subs_from, Recorder}; use actix::Actor; use masq_lib::blockchains::chains::Chain; @@ -88,4 +94,22 @@ mod tests { assert_eq!(web3_gas_limit_const_part(Chain::EthRopsten), 55_000); assert_eq!(web3_gas_limit_const_part(Chain::Dev), 55_000) } + + #[test] + fn blockchain_bridge_subs_factory_produces_proper_subs() { + let subject = BlockchainBridgeSubsFactory {}; + let blockchain_interface = BlockchainInterfaceMock::default(); + let persistent_config = PersistentConfigurationMock::new(); + let accountant = BlockchainBridge::new( + Box::new(blockchain_interface), + Box::new(persistent_config), + false, + None, + ); + let addr = accountant.start(); + + let subs = subject.make(&addr); + + assert_eq!(subs, BlockchainBridge::make_subs_from(&addr)) + } } diff --git a/node/src/test_utils/http_test_server.rs b/node/src/test_utils/http_test_server.rs new file mode 100644 index 000000000..97b2046c0 --- /dev/null +++ b/node/src/test_utils/http_test_server.rs @@ -0,0 +1,71 @@ +// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. + +use crossbeam_channel::{unbounded, Receiver}; +use simple_server::{Request, Server}; +use std::io::Write; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}; +use std::ops::Add; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant}; + +pub struct TestServer { + port: u16, + rx: Receiver>>, +} + +impl Drop for TestServer { + fn drop(&mut self) { + self.stop(); + } +} + +impl TestServer { + pub fn start(port: u16, bodies: Vec>) -> Self { + std::env::set_var("SIMPLESERVER_THREADS", "1"); + let (tx, rx) = unbounded(); + let _ = thread::spawn(move || { + let bodies_arc = Arc::new(Mutex::new(bodies)); + Server::new(move |req, mut rsp| { + if req.headers().get("X-Quit").is_some() { + panic!("Server stop requested"); + } + tx.send(req).unwrap(); + let body = bodies_arc.lock().unwrap().remove(0); + Ok(rsp.body(body)?) + }) + .listen(&Ipv4Addr::LOCALHOST.to_string(), &format!("{}", port)); + }); + let deadline = Instant::now().add(Duration::from_secs(5)); + loop { + thread::sleep(Duration::from_millis(10)); + match TcpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port)) { + Ok(_) => break, + Err(e) => eprintln!("No: {:?}", e), + } + if Instant::now().gt(&deadline) { + panic!("TestServer still not started after 5sec"); + } + } + TestServer { port, rx } + } + + pub fn requests_so_far(&self) -> Vec>> { + let mut requests = vec![]; + while let Ok(request) = self.rx.try_recv() { + requests.push(request); + } + return requests; + } + + fn stop(&mut self) { + let mut stream = + match TcpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), self.port)) { + Ok(s) => s, + Err(_) => return, + }; + stream + .write(b"DELETE /irrelevant.htm HTTP/1.1\r\nX-Quit: Yes") + .unwrap(); + } +} diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index bd6dbb2d7..a95b8ad03 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -6,6 +6,7 @@ pub mod automap_mocks; pub mod data_hunk; pub mod data_hunk_framer; pub mod database_utils; +pub mod http_test_server; pub mod little_tcp_server; pub mod logfile_name_guard; pub mod neighborhood_test_utils; @@ -15,6 +16,7 @@ pub mod recorder_stop_conditions; pub mod stream_connector_mock; pub mod tcp_wrapper_mocks; pub mod tokio_wrapper_mocks; + use crate::blockchain::bip32::Bip32ECKeyProvider; use crate::blockchain::payer::Payer; use crate::bootstrapper::CryptDEPair; From 9e1bfae7494d2a99fbdf98dc2bdfb7b9e939bcdc Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 13 Aug 2023 10:30:51 +0200 Subject: [PATCH 04/10] GH-672: more refactoring and little changes --- node/src/accountant/mod.rs | 4 +- node/src/accountant/payment_adjuster.rs | 6 +-- node/src/accountant/scanners/mod.rs | 8 +-- .../mod.rs | 0 .../payable_scanner/agent_abstract_layer.rs | 0 .../payable_scanner/agent_web3.rs | 8 +-- .../payable_scanner/mod.rs | 2 +- .../payable_scanner/setup_msg.rs | 2 +- node/src/accountant/test_utils.rs | 6 +-- node/src/blockchain/blockchain_bridge.rs | 10 ++-- node/src/blockchain/blockchain_interface.rs | 50 +++++++++++++++---- node/src/blockchain/test_utils.rs | 12 ++--- node/src/sub_lib/accountant.rs | 2 +- node/src/sub_lib/blockchain_bridge.rs | 4 +- node/src/test_utils/recorder.rs | 4 +- 15 files changed, 75 insertions(+), 43 deletions(-) rename node/src/accountant/scanners/{mid_scan_procedures => scanner_mid_procedures}/mod.rs (100%) rename node/src/accountant/scanners/{mid_scan_procedures => scanner_mid_procedures}/payable_scanner/agent_abstract_layer.rs (100%) rename node/src/accountant/scanners/{mid_scan_procedures => scanner_mid_procedures}/payable_scanner/agent_web3.rs (93%) rename node/src/accountant/scanners/{mid_scan_procedures => scanner_mid_procedures}/payable_scanner/mod.rs (92%) rename node/src/accountant/scanners/{mid_scan_procedures => scanner_mid_procedures}/payable_scanner/setup_msg.rs (92%) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 936ce1ced..493c3879a 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -30,7 +30,7 @@ use crate::accountant::database_access_objects::utils::{ use crate::accountant::financials::visibility_restricted_module::{ check_query_is_within_tech_limits, financials_entry_check, }; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::scanners::{ScanSchedulers, Scanners}; @@ -3163,7 +3163,7 @@ mod tests { let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_result(Ok(transaction_fee_balance)) .get_token_balance_result(Ok(token_balance)) - .mobilize_payable_payments_agent_result(Box::new(agent)) + .build_payable_payments_agent_result(Box::new(agent)) .get_transaction_count_result(Ok(web3::types::U256::from(1))) .get_transaction_count_result(Ok(web3::types::U256::from(2))) // because we cannot have both, resolution on the high level and also of what's inside blockchain interface, diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index d9ca32b84..2fb47f8bf 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::PreparedAdjustment; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::PreparedAdjustment; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use masq_lib::logger::Logger; #[cfg(test)] @@ -73,7 +73,7 @@ pub enum AnalysisError {} #[cfg(test)] mod tests { use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; - use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ + use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::test_utils::{make_payable_account, PayablePaymentsAgentMock}; diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 8374d370a..cb0245eaa 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod mid_scan_procedures; +pub mod scanner_mid_procedures; pub mod scanners_utils; use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PayableDao, PendingPayable}; @@ -55,8 +55,8 @@ use std::time::{Duration, SystemTime}; use time::format_description::parse; use time::OffsetDateTime; use web3::types::{TransactionReceipt, H256}; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, PayableScannerMidScanProcedures}; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{PayablePaymentsSetupMsg, QualifiedPayablesMessage}; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, PayableScannerMidScanProcedures}; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{PayablePaymentsSetupMsg, QualifiedPayablesMessage}; pub struct Scanners { pub payable: Box>, @@ -1032,7 +1032,7 @@ mod tests { }; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoError; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t}; - use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; + use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::PendingPayableScanReport; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::{Correct, Failed}; use crate::blockchain::blockchain_interface::{ diff --git a/node/src/accountant/scanners/mid_scan_procedures/mod.rs b/node/src/accountant/scanners/scanner_mid_procedures/mod.rs similarity index 100% rename from node/src/accountant/scanners/mid_scan_procedures/mod.rs rename to node/src/accountant/scanners/scanner_mid_procedures/mod.rs diff --git a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_abstract_layer.rs b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_abstract_layer.rs similarity index 100% rename from node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_abstract_layer.rs rename to node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_abstract_layer.rs diff --git a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs similarity index 93% rename from node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs rename to node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs index dcdb125ed..6c46d3e05 100644 --- a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/agent_web3.rs +++ b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use web3::types::U256; @@ -35,7 +35,7 @@ impl PayablePaymentsAgent for PayablePaymentsAgentWeb3 { fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128 { let gas_price = self .gwei_per_computed_unit_opt - .expect("gas price was not set") as u128; + .expect("gas price must be set before this") as u128; number_of_transactions as u128 * gas_price * (self.maximum_added_gas_margin + self.gas_limit_const_part) as u128 @@ -72,8 +72,8 @@ impl PayablePaymentsAgentWeb3 { #[cfg(test)] mod tests { - use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; - use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_web3::{ + use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; + use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::{ PayablePaymentsAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::db_config::persistent_configuration::PersistentConfigError; diff --git a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs similarity index 92% rename from node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs rename to node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs index b2ece800c..144e2566a 100644 --- a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/mod.rs +++ b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs @@ -5,7 +5,7 @@ pub mod agent_web3; pub mod setup_msg; use crate::accountant::payment_adjuster::Adjustment; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::scanners::Scanner; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use actix::Message; diff --git a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs similarity index 92% rename from node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs rename to node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs index ab4521f74..a54ea8907 100644 --- a/node/src/accountant/scanners/mid_scan_procedures/payable_scanner/setup_msg.rs +++ b/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; use actix::Message; use std::fmt::Debug; diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 4cc8f74d3..e6a159adb 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -14,11 +14,11 @@ use crate::accountant::database_access_objects::receivable_dao::{ }; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t, CustomQuery}; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::{ +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::{ MultistagePayableScanner, PayableScannerMidScanProcedures, PreparedAdjustment, }; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableThresholdsGauge; diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index fcb0496a0..be2e38bb8 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::{ @@ -319,7 +319,7 @@ impl BlockchainBridge { } }; - let mut agent = self.blockchain_interface.mobilize_payable_payments_agent(); + let mut agent = self.blockchain_interface.build_payable_payments_agent(); agent.set_consuming_wallet_balances(consuming_wallet_balances); match agent.set_required_fee_per_computed_unit(self.persistent_config.as_ref()) { @@ -679,7 +679,7 @@ mod tests { .get_transaction_fee_balance_result(Ok(transaction_fee_balance)) .get_token_balance_params(&get_token_balance_params_arc) .get_token_balance_result(Ok(token_balance)) - .mobilize_payable_payments_agent_result(Box::new(agent)); + .build_payable_payments_agent_result(Box::new(agent)); let consuming_wallet = make_paying_wallet(b"somewallet"); let persistent_config_id_stamp = ArbitraryIdStamp::new(); let persistent_configuration = PersistentConfigurationMock::default() @@ -883,7 +883,7 @@ mod tests { let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_result(Ok(U256::from(456789))) .get_token_balance_result(Ok(U256::from(7890123456_u64))) - .mobilize_payable_payments_agent_result(Box::new(agent)); + .build_payable_payments_agent_result(Box::new(agent)); let persistent_configuration = PersistentConfigurationMock::default(); let consuming_wallet = make_wallet("our wallet"); let mut subject = BlockchainBridge::new( diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index f7dd9bd63..0cfe69dc2 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -1,7 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::PayablePaymentsAgentWeb3; use crate::accountant::{comma_joined_stringifiable, gwei_to_wei}; use crate::blockchain::batch_payable_tools::{BatchPayableTools, BatchPayableToolsReal}; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; @@ -139,7 +140,7 @@ pub trait BlockchainInterface { recipient: &Wallet, ) -> Result; - fn mobilize_payable_payments_agent(&self) -> Box; + fn build_payable_payments_agent(&self) -> Box; fn send_batch_of_payables( &self, @@ -194,8 +195,8 @@ impl BlockchainInterface for BlockchainInterfaceClandestine { Err(BlockchainError::QueryFailed(msg)) } - fn mobilize_payable_payments_agent(&self) -> Box { - todo!() + fn build_payable_payments_agent(&self) -> Box { + todo!("fill me up with code when merged with master having the NullScanner and its own test suite") } fn send_batch_of_payables( @@ -350,8 +351,8 @@ where .wait() } - fn mobilize_payable_payments_agent(&self) -> Box { - todo!() + fn build_payable_payments_agent(&self) -> Box { + Box::new(PayablePaymentsAgentWeb3::new(self.gas_limit_const_part)) } fn send_batch_of_payables( @@ -363,10 +364,10 @@ where ) -> Result, PayableTransactionError> { let gas_price = payable_payments_agent .required_fee_per_computed_unit() - .expect("agent screwed gas price"); + .expect("agent should know the gas price but doesn't"); let pending_nonce = payable_payments_agent .pending_transaction_id() - .expect("agent screwed nonce"); + .expect("agent should know the nonce but doesn't"); debug!( self.logger, @@ -720,7 +721,7 @@ mod tests { use super::*; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::gwei_to_wei; - use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; + use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::accountant::test_utils::{ make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, PayablePaymentsAgentMock, @@ -731,10 +732,12 @@ mod tests { make_default_signed_transaction, make_fake_event_loop_handle, make_tx_hash, BatchPayableToolsMock, TestTransport, }; + use crate::db_config::persistent_configuration::PersistentConfiguration; use crate::sub_lib::blockchain_bridge::web3_gas_limit_const_part; use crate::sub_lib::wallet::Wallet; use crate::test_utils::http_test_server::TestServer; use crate::test_utils::make_paying_wallet; + use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::{make_recorder, Recorder}; use crate::test_utils::unshared_test_utils::decode_hex; use crate::test_utils::{make_wallet, TestRawTransaction}; @@ -1215,6 +1218,35 @@ mod tests { assert_error_during_requesting_balance(act, "Invalid hex"); } + #[test] + fn blockchain_interface_can_build_payable_payments_agent() { + // these numbers mean gwei + [ + (Chain::EthMainnet, 21523032), + (Chain::PolyMainnet, 27058032), + ] + .into_iter() + .for_each(|(chain, expected_estimation)| { + let subject = BlockchainInterfaceNonClandestine::new( + TestTransport::default(), + make_fake_event_loop_handle(), + chain, + web3_gas_limit_const_part(chain), + ); + + let mut result = subject.build_payable_payments_agent(); + + let persistent_config = PersistentConfigurationMock::new().gas_price_result(Ok(123)); + result + .set_required_fee_per_computed_unit(&persistent_config) + .unwrap(); + assert_eq!( + result.estimated_transaction_fee_total(3), + expected_estimation + ) + }); + } + fn assert_error_during_requesting_balance(act: F, expected_err_msg_fragment: &str) where F: FnOnce(&BlockchainInterfaceNonClandestine, &Wallet) -> ResultForBalance, diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index 70d511d4d..66f5f9c48 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; use crate::blockchain::batch_payable_tools::BatchPayableTools; use web3::transports::{Batch, EventLoopHandle, Http}; use web3::types::{Address, Bytes, SignedTransaction, TransactionParameters, U256}; @@ -61,7 +61,7 @@ pub struct BlockchainInterfaceMock { retrieve_transactions_parameters: Arc>>, retrieve_transactions_results: RefCell>>, - mobilize_payable_payments_agent_results: RefCell>>, + build_payable_payments_agent_results: RefCell>>, send_batch_of_payables_params: Arc< Mutex< Vec<( @@ -101,8 +101,8 @@ impl BlockchainInterface for BlockchainInterfaceMock { self.retrieve_transactions_results.borrow_mut().remove(0) } - fn mobilize_payable_payments_agent(&self) -> Box { - self.mobilize_payable_payments_agent_results + fn build_payable_payments_agent(&self) -> Box { + self.build_payable_payments_agent_results .borrow_mut() .remove(0) } @@ -178,11 +178,11 @@ impl BlockchainInterfaceMock { self } - pub fn mobilize_payable_payments_agent_result( + pub fn build_payable_payments_agent_result( self, result: Box, ) -> Self { - self.mobilize_payable_payments_agent_results + self.build_payable_payments_agent_results .borrow_mut() .push(result); self diff --git a/node/src/sub_lib/accountant.rs b/node/src/sub_lib/accountant.rs index 07f33058a..88dec3949 100644 --- a/node/src/sub_lib/accountant.rs +++ b/node/src/sub_lib/accountant.rs @@ -3,7 +3,7 @@ use crate::accountant::database_access_objects::banned_dao::BannedDaoFactory; use crate::accountant::database_access_objects::payable_dao::PayableDaoFactory; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoFactory; use crate::accountant::database_access_objects::receivable_dao::ReceivableDaoFactory; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::{ checked_conversion, Accountant, ReceivedPayments, ReportTransactionReceipts, ScanError, SentPayables, diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index c30d8d2c6..6cb914493 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index 19e687291..ba8f7a1b5 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. #![cfg(test)] -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; -use crate::accountant::scanners::mid_scan_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::ReportTransactionReceipts; use crate::accountant::{ ReceivedPayments, RequestTransactionReceipts, ScanError, ScanForPayables, From 874e9ee35eb2a80a55644e99a9dfcee49e3564d2 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 13 Aug 2023 12:57:02 +0200 Subject: [PATCH 05/10] GH-672: fixing stuff araound blockchain_interface web3 and its initialization --- .../tests/verify_bill_payment.rs | 9 +- node/src/actor_system_factory.rs | 9 +- node/src/blockchain/blockchain_bridge.rs | 65 +---- node/src/blockchain/blockchain_interface.rs | 247 ++++++------------ .../blockchain_interface_initializer.rs | 95 +++++++ node/src/blockchain/mod.rs | 1 + node/src/sub_lib/blockchain_bridge.rs | 19 -- 7 files changed, 199 insertions(+), 246 deletions(-) create mode 100644 node/src/blockchain/blockchain_interface_initializer.rs diff --git a/multinode_integration_tests/tests/verify_bill_payment.rs b/multinode_integration_tests/tests/verify_bill_payment.rs index 658ddcc1c..ad3fc51b9 100644 --- a/multinode_integration_tests/tests/verify_bill_payment.rs +++ b/multinode_integration_tests/tests/verify_bill_payment.rs @@ -61,13 +61,8 @@ fn verify_bill_payment() { "Ganache is not as predictable as we thought: Update blockchain_interface::MULTINODE_CONTRACT_ADDRESS with {:?}", contract_addr ); - let web3_gas_const_part = web3_gas_limit_const_part(cluster.chain); - let blockchain_interface = BlockchainInterfaceNonClandestine::new( - http, - _event_loop_handle, - cluster.chain, - web3_gas_const_part, - ); + let blockchain_interface = + BlockchainInterfaceNonClandestine::new(http, _event_loop_handle, cluster.chain); assert_balances( &contract_owner_wallet, &blockchain_interface, diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index 0040ba20c..06b6c981d 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -33,7 +33,7 @@ use crate::sub_lib::proxy_client::ProxyClientConfig; use crate::sub_lib::proxy_client::ProxyClientSubs; use crate::sub_lib::proxy_server::ProxyServerSubs; use crate::sub_lib::ui_gateway::UiGatewaySubs; -use actix::{Actor, Recipient}; +use actix::Recipient; use actix::{Addr, Arbiter}; use automap_lib::comm_layer::AutomapError; use automap_lib::control_layer::automap_control::{ @@ -664,10 +664,8 @@ mod tests { }; use crate::test_utils::recorder::{make_recorder, Recorder}; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; + use crate::test_utils::unshared_test_utils::assert_on_initialization_with_panic_on_migration; use crate::test_utils::unshared_test_utils::system_killer_actor::SystemKillerActor; - use crate::test_utils::unshared_test_utils::{ - assert_on_initialization_with_panic_on_migration, AssertionsMessage, - }; use crate::test_utils::{alias_cryptde, rate_pack}; use crate::test_utils::{main_cryptde, make_cryptde_pair}; use crate::{hopper, proxy_client, proxy_server, stream_handler_pool, ui_gateway}; @@ -2174,7 +2172,7 @@ mod tests { let server_url = format!("http://{}:{}", &Ipv4Addr::LOCALHOST.to_string(), port); let test_server = TestServer::start( port, - vec![br#"{"jsonrpc":"2.0","id":0,"result":___}"#.to_vec()], + vec![br#"{"jsonrpc":"2.0","id":0,"result":someGarbage}"#.to_vec()], ); let wallet = make_wallet("abc"); let mut bootstrapper_config = BootstrapperConfig::new(); @@ -2209,7 +2207,6 @@ mod tests { .into_iter() .map(|request| serde_json::from_slice(&request.body()).unwrap()) .collect(); - eprintln!("{:?} {:?}", bodies, TEST_DEFAULT_CHAIN.rec().contract); assert_eq!( bodies[0]["params"][0]["data"].to_string()[35..75], wallet.to_string()[2..] diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index be2e38bb8..859142b21 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -11,17 +11,17 @@ use crate::accountant::{ use crate::accountant::{ReportTransactionReceipts, RequestTransactionReceipts}; use crate::actor_system_factory::SubsFactory; use crate::blockchain::blockchain_interface::{ - BlockchainError, BlockchainInterface, BlockchainInterfaceClandestine, - BlockchainInterfaceNonClandestine, PayableTransactionError, ProcessedPayableFallible, + BlockchainError, BlockchainInterface, BlockchainInterfaceClandestine, PayableTransactionError, + ProcessedPayableFallible, }; +use crate::blockchain::blockchain_interface_initializer::BlockchainInterfaceInitializer; use crate::database::db_initializer::{DbInitializationConfig, DbInitializer, DbInitializerReal}; use crate::db_config::config_dao::ConfigDaoReal; use crate::db_config::persistent_configuration::{ PersistentConfiguration, PersistentConfigurationReal, }; use crate::sub_lib::blockchain_bridge::{ - web3_gas_limit_const_part, BlockchainBridgeSubs, ConsumingWalletBalances, - OutboundPaymentsInstructions, + BlockchainBridgeSubs, ConsumingWalletBalances, OutboundPaymentsInstructions, }; use crate::sub_lib::peer_actors::BindMessage; use crate::sub_lib::set_consuming_wallet_message::SetConsumingWalletMessage; @@ -39,7 +39,6 @@ use masq_lib::messages::ScanType; use masq_lib::ui_gateway::NodeFromUiMessage; use std::path::Path; use std::time::SystemTime; -use web3::transports::{EventLoopHandle, Http}; use web3::types::{TransactionReceipt, H256}; pub const CRASH_KEY: &str = "BLOCKCHAINBRIDGE"; @@ -230,36 +229,20 @@ impl BlockchainBridge { chain: Chain, ) -> Box { match blockchain_service_url_opt { - Some(url) => match Http::new(&url) { - Ok((event_loop_handle, transport)) => { - Self::initialize_appropriate_definite_interface( - event_loop_handle, - transport, - chain, - ) + Some(url) => //match Http::new(&url) { + // Ok((event_loop_handle, transport)) => { + { + let initializer = BlockchainInterfaceInitializer {}; + initializer.initialize_chain_compatible_interface(&url, chain) + // } +// Err(e) => panic!("Invalid blockchain node URL: {:?}", e), + // } } - Err(e) => panic!("Invalid blockchain node URL: {:?}", e), - }, - None => Box::new(BlockchainInterfaceClandestine::new(chain)), //TODO make sure this is tested (after the merge??) + , + None => Box::new(BlockchainInterfaceClandestine::new(chain)), //TODO make sure this is tested for BlockchainInterfaceNull (after the merge??) } } - // TODO when we have multiple chains of fundamentally different architectures and also ability to switch them, - // this should probably be replaced by a HashMap of a distinct blockchain interface for each chain - fn initialize_appropriate_definite_interface( - http_event_loop_handle: EventLoopHandle, - transport: Http, - chain: Chain, - ) -> Box { - let gas_limit_const_part = web3_gas_limit_const_part(chain); - Box::new(BlockchainInterfaceNonClandestine::new( - transport, - http_event_loop_handle, - chain, - gas_limit_const_part, - )) - } - pub fn make_subs_from(addr: &Addr) -> BlockchainBridgeSubs { BlockchainBridgeSubs { bind: recipient!(addr, BindMessage), @@ -557,7 +540,6 @@ mod tests { use actix::System; use ethereum_types::U64; use ethsign_crypto::Keccak256; - use masq_lib::constants::DEFAULT_CHAIN; use masq_lib::messages::ScanType; use masq_lib::test_utils::logging::init_test_logging; use masq_lib::test_utils::logging::TestLogHandler; @@ -643,16 +625,6 @@ mod tests { ); } - #[test] - #[should_panic(expected = "Invalid blockchain node URL")] - fn invalid_blockchain_url_produces_panic() { - let blockchain_service_url = Some("http://λ:8545".to_string()); - let _ = BlockchainBridge::initialize_blockchain_interface( - blockchain_service_url, - DEFAULT_CHAIN, - ); - } - #[test] fn payable_payments_setup_msg_payload_is_handled_and_new_setup_msg_containing_agent_returns_to_accountant( ) { @@ -1911,15 +1883,6 @@ mod tests { assert_on_initialization_with_panic_on_migration(&data_dir, &act); } - - #[test] - fn web3_gas_limit_const_part_gives_reasonable_values() { - assert_eq!(web3_gas_limit_const_part(Chain::EthMainnet), 55_000); - assert_eq!(web3_gas_limit_const_part(Chain::EthRopsten), 55_000); - assert_eq!(web3_gas_limit_const_part(Chain::PolyMainnet), 70_000); - assert_eq!(web3_gas_limit_const_part(Chain::PolyMumbai), 70_000); - assert_eq!(web3_gas_limit_const_part(Chain::Dev), 55_000); - } } #[cfg(test)] diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index 0cfe69dc2..eb0637b87 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -465,18 +465,14 @@ impl BlockchainInterfaceNonClandestine where T: BatchTransport + Debug + 'static, { - pub fn new( - transport: T, - event_loop_handle: EventLoopHandle, - chain: Chain, - gas_limit_const_part: u64, - ) -> Self { + pub fn new(transport: T, event_loop_handle: EventLoopHandle, chain: Chain) -> Self { let web3 = Web3::new(transport.clone()); let batch_web3 = Web3::new(Batch::new(transport)); let batch_payable_tools = Box::new(BatchPayableToolsReal::::default()); let contract = Contract::from_json(web3.eth(), chain.rec().contract, CONTRACT_ABI.as_bytes()) .expect("Unable to initialize contract."); + let gas_limit_const_part = Self::web3_gas_limit_const_part(chain); Self { logger: Logger::new("BlockchainInterface"), @@ -710,6 +706,13 @@ where .expect("Internal error") } + fn web3_gas_limit_const_part(chain: Chain) -> u64 { + match chain { + Chain::EthMainnet | Chain::EthRopsten | Chain::Dev => 55_000, + Chain::PolyMainnet | Chain::PolyMumbai => 70_000, + } + } + #[cfg(test)] fn web3(&self) -> &Web3 { &self.web3 @@ -732,8 +735,6 @@ mod tests { make_default_signed_transaction, make_fake_event_loop_handle, make_tx_hash, BatchPayableToolsMock, TestTransport, }; - use crate::db_config::persistent_configuration::PersistentConfiguration; - use crate::sub_lib::blockchain_bridge::web3_gas_limit_const_part; use crate::sub_lib::wallet::Wallet; use crate::test_utils::http_test_server::TestServer; use crate::test_utils::make_paying_wallet; @@ -742,7 +743,6 @@ mod tests { use crate::test_utils::unshared_test_utils::decode_hex; use crate::test_utils::{make_wallet, TestRawTransaction}; use actix::{Actor, System}; - use crossbeam_channel::{unbounded, Receiver}; use ethereum_types::U64; use ethsign_crypto::Keccak256; use jsonrpc_core::Version::V2; @@ -753,14 +753,10 @@ mod tests { use serde_derive::Deserialize; use serde_json::json; use serde_json::Value; - use simple_server::{Request, Server}; - use std::io::Write; - use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}; - use std::ops::Add; + use std::net::Ipv4Addr; use std::str::FromStr; use std::sync::{Arc, Mutex}; - use std::thread; - use std::time::{Duration, Instant, SystemTime}; + use std::time::SystemTime; use web3::transports::Http; use web3::types::H2048; use web3::Error as Web3Error; @@ -789,7 +785,6 @@ mod tests { TestTransport::default(), make_fake_event_loop_handle(), *chain, - web3_gas_limit_const_part(*chain), ); assert_eq!(subject.contract_address(), chain.rec().contract) @@ -811,12 +806,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject .retrieve_transactions( @@ -893,12 +883,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject .retrieve_transactions( @@ -949,12 +934,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject .retrieve_transactions(42, &Wallet::new("0x3f69f9efd4f2592fd70beecd9dce71c472fc")); @@ -978,12 +958,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.retrieve_transactions( 42, @@ -1009,12 +984,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.retrieve_transactions( 42, @@ -1037,12 +1007,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.retrieve_transactions( 42, @@ -1071,12 +1036,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject .get_transaction_fee_balance( @@ -1098,12 +1058,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.get_transaction_fee_balance(&Wallet::new( "0x3f69f9efd4f2592fd70be8c32ecd9dce71c472fQ", @@ -1127,12 +1082,7 @@ mod tests { )) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.get_transaction_fee_balance( &Wallet::from_str("0x3f69f9efd4f2592fd70be8c32ecd9dce71c472fc").unwrap(), @@ -1168,12 +1118,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject .get_token_balance( @@ -1195,12 +1140,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = subject.get_token_balance(&Wallet::new("0x3f69f9efd4f2592fd70be8c32ecd9dce71c472fQ")); @@ -1231,7 +1171,6 @@ mod tests { TestTransport::default(), make_fake_event_loop_handle(), chain, - web3_gas_limit_const_part(chain), ); let mut result = subject.build_payable_payments_agent(); @@ -1261,12 +1200,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let result = act( &subject, @@ -1314,7 +1248,6 @@ mod tests { transport.clone(), make_fake_event_loop_handle(), chain, - web3_gas_limit_const_part(chain), ); subject.logger = logger; let amount_1 = gwei_to_wei(900_000_000_u64); @@ -1507,12 +1440,8 @@ mod tests { let batch_wide_timestamp_expected = SystemTime::now(); let transport = TestTransport::default().initiate_reference_counter(&reference_counter_arc); let chain = Chain::EthMainnet; - let mut subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let mut subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); let first_tx_parameters = TransactionParameters { nonce: Some(U256::from(4)), to: Some(subject.contract_address()), @@ -1679,36 +1608,53 @@ mod tests { assert_eq!(accountant_recording.len(), 1) } + #[test] + fn web3_gas_limit_const_part_returns_reasonable_values() { + type Subject = BlockchainInterfaceNonClandestine; + assert_eq!( + Subject::web3_gas_limit_const_part(Chain::EthMainnet), + 55_000 + ); + assert_eq!( + Subject::web3_gas_limit_const_part(Chain::EthRopsten), + 55_000 + ); + assert_eq!( + Subject::web3_gas_limit_const_part(Chain::PolyMainnet), + 70_000 + ); + assert_eq!( + Subject::web3_gas_limit_const_part(Chain::PolyMumbai), + 70_000 + ); + assert_eq!(Subject::web3_gas_limit_const_part(Chain::Dev), 55_000); + } + #[test] fn non_clandestine_gas_limit_for_polygon_mainnet_lies_within_limits_for_raw_transaction() { let transport = TestTransport::default(); let chain = Chain::PolyMainnet; - let gas_limit_const_part = 123456; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - gas_limit_const_part, - ); + let gas_limit_const_part = + BlockchainInterfaceNonClandestine::::web3_gas_limit_const_part(chain); + let subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); + let maximal_possible_value = gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN; - assert_gas_limit_is_between(subject, 123456, maximal_possible_value); + assert_gas_limit_is_between(subject, gas_limit_const_part, maximal_possible_value); } #[test] fn non_clandestine_gas_limit_for_eth_mainnet_lies_within_limits_for_raw_transaction() { let transport = TestTransport::default(); let chain = Chain::EthMainnet; - let gas_limit_const_part = 456789; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - gas_limit_const_part, - ); + let gas_limit_const_part = + BlockchainInterfaceNonClandestine::::web3_gas_limit_const_part(chain); + let subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); let maximal_possible_value = gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN; - assert_gas_limit_is_between(subject, 456789, maximal_possible_value) + assert_gas_limit_is_between(subject, gas_limit_const_part, maximal_possible_value) } fn assert_gas_limit_is_between( @@ -1737,8 +1683,18 @@ mod tests { let mut sign_transaction_params = sign_transaction_params_arc.lock().unwrap(); let (transaction_params, _, secret) = sign_transaction_params.remove(0); assert!(sign_transaction_params.is_empty()); - assert!(transaction_params.gas >= U256::from(not_under_this_value)); - assert!(transaction_params.gas <= U256::from(not_above_this_value)); + assert!( + transaction_params.gas >= U256::from(not_under_this_value), + "actual gas limit {} isn't above {}", + transaction_params.gas, + not_under_this_value + ); + assert!( + transaction_params.gas <= U256::from(not_above_this_value), + "actual gas limit {} isn't below {}", + transaction_params.gas, + not_above_this_value + ); assert_eq!( secret, (&Bip32ECKeyProvider::from_raw_secret(&consuming_wallet_secret_raw_bytes.keccak256()) @@ -1758,12 +1714,8 @@ mod tests { ))) //we return after meeting the first result .sign_transaction_result(Err(Web3Error::Internal)); - let mut subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let mut subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); subject.batch_payable_tools = Box::new(batch_payable_tools); let recipient = Recorder::new().start().recipient(); let consuming_wallet = make_paying_wallet(&b"consume, you greedy fool!"[..]); @@ -1791,12 +1743,8 @@ mod tests { let incomplete_consuming_wallet = Wallet::from_str("0x3f69f9efd4f2592fd70be8c32ecd9dce71c472fc").unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); let system = System::new("test"); let (accountant, _, accountant_recording_arc) = make_recorder(); let recipient = accountant.start().recipient(); @@ -1837,12 +1785,8 @@ mod tests { .submit_batch_result(Err(Web3Error::Transport("Transaction crashed".to_string()))); let consuming_wallet_secret_raw_bytes = b"okay-wallet"; let chain = Chain::PolyMumbai; - let mut subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let mut subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); subject.batch_payable_tools = Box::new(batch_payable_tools); let unimportant_recipient = Recorder::new().start().recipient(); let account = make_payable_account_with_wallet_and_balance_and_timestamp_opt( @@ -1880,12 +1824,8 @@ mod tests { ))); let consuming_wallet_secret_raw_bytes = b"okay-wallet"; let chain = Chain::PolyMumbai; - let mut subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let mut subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); subject.batch_payable_tools = Box::new(batch_payable_tools); let recipient = make_wallet("unlucky man"); let consuming_wallet = make_paying_wallet(consuming_wallet_secret_raw_bytes); @@ -1929,12 +1869,8 @@ mod tests { template: &[u8], ) { let transport = TestTransport::default(); - let subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); let consuming_wallet = test_consuming_wallet_with_secret(); let recipient_wallet = test_recipient_wallet(); let nonce_correct_type = U256::from(nonce); @@ -2143,12 +2079,8 @@ mod tests { ][..], ]; let transport = TestTransport::default(); - let subject = BlockchainInterfaceNonClandestine::new( - transport, - make_fake_event_loop_handle(), - chain, - web3_gas_limit_const_part(chain), - ); + let subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); let lengths_of_constant_parts: Vec = constant_parts.iter().map(|part| part.len()).collect(); for (((tx, signed), length), constant_part) in txs @@ -2204,7 +2136,6 @@ mod tests { transport.clone(), make_fake_event_loop_handle(), chain, - web3_gas_limit_const_part(chain), ); let result = subject.get_transaction_count(&make_paying_wallet(b"gdasgsa")); @@ -2248,12 +2179,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let tx_hash = H256::from_str("a128f9ca1e705cc20a936a24a7fa1df73bad6e0aaf58e8e6ffcc154a7cff6e0e") .unwrap(); @@ -2285,12 +2211,7 @@ mod tests { ) .unwrap(); let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainInterfaceNonClandestine::new( - transport, - event_loop_handle, - chain, - web3_gas_limit_const_part(chain), - ); + let subject = BlockchainInterfaceNonClandestine::new(transport, event_loop_handle, chain); let tx_hash = make_tx_hash(4564546); let result = subject.get_transaction_receipt(tx_hash); diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs new file mode 100644 index 000000000..735362d0b --- /dev/null +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -0,0 +1,95 @@ +// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. + +use crate::blockchain::blockchain_interface::{ + BlockchainInterface, BlockchainInterfaceNonClandestine, +}; +use masq_lib::blockchains::chains::Chain; +use web3::transports::Http; + +pub(in crate::blockchain) struct BlockchainInterfaceInitializer {} + +impl BlockchainInterfaceInitializer { + // TODO when we have multiple chains of fundamentally different architectures and also the ability to switch them, + // this should probably be replaced by a HashMap of distinct blockchain interfaces for each chain + pub fn initialize_chain_compatible_interface( + &self, + blockchain_service_url: &str, + chain: Chain, + ) -> Box { + self.initialize_web3_interface(blockchain_service_url, chain) + } + + fn initialize_web3_interface( + &self, + blockchain_service_url: &str, + chain: Chain, + ) -> Box { + match Http::new(blockchain_service_url) { + Ok((event_loop_handle, transport)) => Box::new(BlockchainInterfaceNonClandestine::new( + transport, + event_loop_handle, + chain, + )), + Err(e) => panic!( + "Invalid blockchain service URL \"{}\". Error: {:?}. Chain: {}", + blockchain_service_url, + e, + chain.rec().literal_identifier + ), + } + } +} + +#[cfg(test)] +mod tests { + use crate::blockchain::blockchain_interface_initializer::BlockchainInterfaceInitializer; + use crate::test_utils::http_test_server::TestServer; + use crate::test_utils::make_wallet; + use masq_lib::blockchains::chains::Chain; + use masq_lib::constants::DEFAULT_CHAIN; + use masq_lib::utils::find_free_port; + use serde_json::Value; + use std::net::Ipv4Addr; + + #[test] + fn initialize_web3_interface_works() { + let port = find_free_port(); + let server_url = format!("http://{}:{}", &Ipv4Addr::LOCALHOST.to_string(), port); + let test_server = TestServer::start( + port, + vec![br#"{"jsonrpc":"2.0","id":0,"result":someGarbage}"#.to_vec()], + ); + let wallet = make_wallet("123"); + let subject = BlockchainInterfaceInitializer {}; + let chain = Chain::PolyMainnet; + + let interface = subject.initialize_web3_interface(&server_url, chain); + + //no result assertion, we anticipate a badly formatted response from the server + let _ = interface.get_token_balance(&wallet); + + let requests = test_server.requests_so_far(); + let bodies: Vec = requests + .into_iter() + .map(|request| serde_json::from_slice(&request.body()).unwrap()) + .collect(); + assert_eq!( + bodies[0]["params"][0]["data"].to_string()[35..75], + wallet.to_string()[2..] + ); + assert_eq!( + bodies[0]["params"][0]["to"], + format!("{:?}", chain.rec().contract) + ); + } + + #[test] + #[should_panic(expected = "Invalid blockchain service URL \"http://λ:8545\". \ + Error: Transport(\"InvalidUri(InvalidUriChar)\"). Chain: polygon-mainnet")] + fn invalid_blockchain_url_for_produces_panic_for_web3_interface() { + let blockchain_service_url = "http://λ:8545"; + let subject = BlockchainInterfaceInitializer {}; + + subject.initialize_web3_interface(blockchain_service_url, DEFAULT_CHAIN); + } +} diff --git a/node/src/blockchain/mod.rs b/node/src/blockchain/mod.rs index 7375b60e9..176fd5683 100644 --- a/node/src/blockchain/mod.rs +++ b/node/src/blockchain/mod.rs @@ -4,6 +4,7 @@ pub mod bip32; pub mod bip39; pub mod blockchain_bridge; pub mod blockchain_interface; +pub mod blockchain_interface_initializer; pub mod payer; pub mod signature; diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 6cb914493..47cc80fc1 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -58,23 +58,14 @@ pub struct ConsumingWalletBalances { pub masq_token_balance_in_minor_units: U256, } -pub fn web3_gas_limit_const_part(chain: Chain) -> u64 { - match chain { - Chain::EthMainnet | Chain::EthRopsten | Chain::Dev => 55_000, - Chain::PolyMainnet | Chain::PolyMumbai => 70_000, - } -} - #[cfg(test)] mod tests { use crate::actor_system_factory::SubsFactory; use crate::blockchain::blockchain_bridge::{BlockchainBridge, BlockchainBridgeSubsFactory}; use crate::blockchain::test_utils::BlockchainInterfaceMock; - use crate::sub_lib::blockchain_bridge::web3_gas_limit_const_part; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; use crate::test_utils::recorder::{make_blockchain_bridge_subs_from, Recorder}; use actix::Actor; - use masq_lib::blockchains::chains::Chain; #[test] fn blockchain_bridge_subs_debug() { @@ -85,16 +76,6 @@ mod tests { assert_eq!(format!("{:?}", subject), "BlockchainBridgeSubs"); } - #[test] - fn web3_gas_limit_const_part_gives_right_values() { - assert_eq!(web3_gas_limit_const_part(Chain::PolyMainnet), 70_000); - assert_eq!(web3_gas_limit_const_part(Chain::PolyMumbai), 70_000); - assert_eq!(web3_gas_limit_const_part(Chain::EthMainnet), 55_000); - assert_eq!(web3_gas_limit_const_part(Chain::EthRopsten), 55_000); - assert_eq!(web3_gas_limit_const_part(Chain::EthRopsten), 55_000); - assert_eq!(web3_gas_limit_const_part(Chain::Dev), 55_000) - } - #[test] fn blockchain_bridge_subs_factory_produces_proper_subs() { let subject = BlockchainBridgeSubsFactory {}; From 4b237241509a5cbfb48a426e3b58301e449e09d5 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 13 Aug 2023 18:36:50 +0200 Subject: [PATCH 06/10] GH-672: savepoint --- node/src/blockchain/blockchain_interface.rs | 35 +++++++-------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index eb0637b87..15c401e96 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -1632,39 +1632,26 @@ mod tests { #[test] fn non_clandestine_gas_limit_for_polygon_mainnet_lies_within_limits_for_raw_transaction() { - let transport = TestTransport::default(); - let chain = Chain::PolyMainnet; - let gas_limit_const_part = - BlockchainInterfaceNonClandestine::::web3_gas_limit_const_part(chain); - let subject = - BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); - - let maximal_possible_value = gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN; - - assert_gas_limit_is_between(subject, gas_limit_const_part, maximal_possible_value); + test_gas_limit_is_between_limits(Chain::PolyMainnet); } #[test] fn non_clandestine_gas_limit_for_eth_mainnet_lies_within_limits_for_raw_transaction() { - let transport = TestTransport::default(); - let chain = Chain::EthMainnet; - let gas_limit_const_part = - BlockchainInterfaceNonClandestine::::web3_gas_limit_const_part(chain); - let subject = - BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); - let maximal_possible_value = gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN; - - assert_gas_limit_is_between(subject, gas_limit_const_part, maximal_possible_value) + test_gas_limit_is_between_limits(Chain::EthMainnet) } - fn assert_gas_limit_is_between( - mut subject: BlockchainInterfaceNonClandestine, - not_under_this_value: u64, - not_above_this_value: u64, + fn test_gas_limit_is_between_limits( + chain: Chain ) { let sign_transaction_params_arc = Arc::new(Mutex::new(vec![])); + let transport = TestTransport::default(); + let mut subject = + BlockchainInterfaceNonClandestine::new(transport, make_fake_event_loop_handle(), chain); + let not_under_this_value = + BlockchainInterfaceNonClandestine::::web3_gas_limit_const_part(chain); + let not_above_this_value = not_under_this_value + WEB3_MAXIMAL_GAS_LIMIT_MARGIN; let consuming_wallet_secret_raw_bytes = b"my-wallet"; - let batch_payable_tools = BatchPayableToolsMock::::default() + let batch_payable_tools = BatchPayableToolsMock::::default() .sign_transaction_params(&sign_transaction_params_arc) .sign_transaction_result(Ok(make_default_signed_transaction())); subject.batch_payable_tools = Box::new(batch_payable_tools); From 772a600340a98adc95cf38735112b03d99d2df13 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 13 Aug 2023 18:55:53 +0200 Subject: [PATCH 07/10] GH-672: renaming --- .../big_int_db_processor.rs | 10 +++++----- .../{big_int_processing => big_int}/big_int_divider.rs | 4 ++-- .../accountant/{big_int_processing => big_int}/mod.rs | 0 .../{big_int_processing => big_int}/test_utils.rs | 6 +++--- .../accountant/database_access_objects/payable_dao.rs | 8 ++++---- .../database_access_objects/pending_payable_dao.rs | 4 ++-- .../database_access_objects/receivable_dao.rs | 8 ++++---- node/src/accountant/database_access_objects/utils.rs | 2 +- node/src/accountant/mod.rs | 4 ++-- node/src/accountant/payment_adjuster.rs | 6 +++--- .../mod.rs | 0 .../payable_scanner/agent.rs} | 0 .../payable_scanner/agent_web3.rs | 6 +++--- .../payable_scanner/mod.rs | 4 ++-- .../payable_scanner/setup_msg.rs | 2 +- node/src/accountant/scanners/mod.rs | 8 ++++---- node/src/accountant/test_utils.rs | 6 +++--- node/src/blockchain/blockchain_bridge.rs | 4 ++-- node/src/blockchain/blockchain_interface.rs | 6 +++--- node/src/blockchain/test_utils.rs | 2 +- .../db_migrations/migrations/migration_6_to_7.rs | 2 +- node/src/sub_lib/accountant.rs | 2 +- node/src/sub_lib/blockchain_bridge.rs | 4 ++-- node/src/test_utils/recorder.rs | 4 ++-- 24 files changed, 51 insertions(+), 51 deletions(-) rename node/src/accountant/{big_int_processing => big_int}/big_int_db_processor.rs (99%) rename node/src/accountant/{big_int_processing => big_int}/big_int_divider.rs (99%) rename node/src/accountant/{big_int_processing => big_int}/mod.rs (100%) rename node/src/accountant/{big_int_processing => big_int}/test_utils.rs (75%) rename node/src/accountant/scanners/{scanner_mid_procedures => mid_scan_msg_handling}/mod.rs (100%) rename node/src/accountant/scanners/{scanner_mid_procedures/payable_scanner/agent_abstract_layer.rs => mid_scan_msg_handling/payable_scanner/agent.rs} (100%) rename node/src/accountant/scanners/{scanner_mid_procedures => mid_scan_msg_handling}/payable_scanner/agent_web3.rs (94%) rename node/src/accountant/scanners/{scanner_mid_procedures => mid_scan_msg_handling}/payable_scanner/mod.rs (90%) rename node/src/accountant/scanners/{scanner_mid_procedures => mid_scan_msg_handling}/payable_scanner/setup_msg.rs (92%) diff --git a/node/src/accountant/big_int_processing/big_int_db_processor.rs b/node/src/accountant/big_int/big_int_db_processor.rs similarity index 99% rename from node/src/accountant/big_int_processing/big_int_db_processor.rs rename to node/src/accountant/big_int/big_int_db_processor.rs index 5c57bc1b5..e06ba9745 100644 --- a/node/src/accountant/big_int_processing/big_int_db_processor.rs +++ b/node/src/accountant/big_int/big_int_db_processor.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::checked_conversion; use crate::accountant::database_access_objects::payable_dao::PayableDaoError; use crate::accountant::database_access_objects::receivable_dao::ReceivableDaoError; @@ -498,12 +498,12 @@ big_int_db_error_from!(PayableDaoError, ReceivableDaoError); #[cfg(test)] mod tests { use super::*; - use crate::accountant::big_int_processing::big_int_db_processor::ByteMagnitude::{High, Low}; - use crate::accountant::big_int_processing::big_int_db_processor::KnownKeyVariants::TestKey; - use crate::accountant::big_int_processing::big_int_db_processor::WeiChange::{ + use crate::accountant::big_int::big_int_db_processor::ByteMagnitude::{High, Low}; + use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::TestKey; + use crate::accountant::big_int::big_int_db_processor::WeiChange::{ Addition, Subtraction, }; - use crate::accountant::big_int_processing::test_utils::restricted::{ + use crate::accountant::big_int::test_utils::restricted::{ create_new_empty_db, test_database_key, }; use crate::database::connection_wrapper::{ConnectionWrapper, ConnectionWrapperReal}; diff --git a/node/src/accountant/big_int_processing/big_int_divider.rs b/node/src/accountant/big_int/big_int_divider.rs similarity index 99% rename from node/src/accountant/big_int_processing/big_int_divider.rs rename to node/src/accountant/big_int/big_int_divider.rs index 40d5a15f1..acea1a86e 100644 --- a/node/src/accountant/big_int_processing/big_int_divider.rs +++ b/node/src/accountant/big_int/big_int_divider.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_divider::UserDefinedFunctionError::InvalidInputValue; +use crate::accountant::big_int::big_int_divider::UserDefinedFunctionError::InvalidInputValue; use crate::accountant::gwei_to_wei; use rusqlite::functions::{Context, FunctionFlags}; use rusqlite::Connection; @@ -135,7 +135,7 @@ impl Display for UserDefinedFunctionError { #[cfg(test)] mod tests { use super::*; - use crate::accountant::big_int_processing::test_utils::restricted::create_new_empty_db; + use crate::accountant::big_int::test_utils::restricted::create_new_empty_db; use rusqlite::Error::SqliteFailure; use rusqlite::ErrorCode; diff --git a/node/src/accountant/big_int_processing/mod.rs b/node/src/accountant/big_int/mod.rs similarity index 100% rename from node/src/accountant/big_int_processing/mod.rs rename to node/src/accountant/big_int/mod.rs diff --git a/node/src/accountant/big_int_processing/test_utils.rs b/node/src/accountant/big_int/test_utils.rs similarity index 75% rename from node/src/accountant/big_int_processing/test_utils.rs rename to node/src/accountant/big_int/test_utils.rs index b231db20c..e9d89f09d 100644 --- a/node/src/accountant/big_int_processing/test_utils.rs +++ b/node/src/accountant/big_int/test_utils.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub(in crate::accountant::big_int_processing) mod restricted { - use crate::accountant::big_int_processing::big_int_db_processor::KnownKeyVariants::TestKey; - use crate::accountant::big_int_processing::big_int_db_processor::{ +pub(in crate::accountant::big_int) mod restricted { + use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::TestKey; + use crate::accountant::big_int::big_int_db_processor::{ ExtendedParamsMarker, KnownKeyVariants, }; use masq_lib::test_utils::utils::ensure_node_home_directory_exists; diff --git a/node/src/accountant/database_access_objects/payable_dao.rs b/node/src/accountant/database_access_objects/payable_dao.rs index 0036134e6..d870d18c6 100644 --- a/node/src/accountant/database_access_objects/payable_dao.rs +++ b/node/src/accountant/database_access_objects/payable_dao.rs @@ -1,15 +1,15 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_db_processor::KnownKeyVariants::{ +use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::{ PendingPayableRowid, WalletAddress, }; -use crate::accountant::big_int_processing::big_int_db_processor::WeiChange::{ +use crate::accountant::big_int::big_int_db_processor::WeiChange::{ Addition, Subtraction, }; -use crate::accountant::big_int_processing::big_int_db_processor::{ +use crate::accountant::big_int::big_int_db_processor::{ BigIntDbProcessor, BigIntSqlConfig, Param, SQLParamsBuilder, TableNameDAO, }; -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::database_access_objects::utils; use crate::accountant::database_access_objects::utils::{ sum_i128_values_from_table, to_time_t, AssemblerFeeder, CustomQuery, DaoFactoryReal, diff --git a/node/src/accountant/database_access_objects/pending_payable_dao.rs b/node/src/accountant/database_access_objects/pending_payable_dao.rs index 462030704..b04356406 100644 --- a/node/src/accountant/database_access_objects/pending_payable_dao.rs +++ b/node/src/accountant/database_access_objects/pending_payable_dao.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::database_access_objects::utils::{ from_time_t, to_time_t, DaoFactoryReal, VigilantRusqliteFlatten, }; @@ -241,7 +241,7 @@ impl<'a> PendingPayableDaoReal<'a> { #[cfg(test)] mod tests { - use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; + use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::checked_conversion; use crate::accountant::database_access_objects::pending_payable_dao::{ PendingPayableDao, PendingPayableDaoError, PendingPayableDaoReal, diff --git a/node/src/accountant/database_access_objects/receivable_dao.rs b/node/src/accountant/database_access_objects/receivable_dao.rs index db91cbe93..76dd9a0bc 100644 --- a/node/src/accountant/database_access_objects/receivable_dao.rs +++ b/node/src/accountant/database_access_objects/receivable_dao.rs @@ -1,13 +1,13 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_db_processor::KnownKeyVariants::WalletAddress; -use crate::accountant::big_int_processing::big_int_db_processor::WeiChange::{ +use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::WalletAddress; +use crate::accountant::big_int::big_int_db_processor::WeiChange::{ Addition, Subtraction, }; -use crate::accountant::big_int_processing::big_int_db_processor::{ +use crate::accountant::big_int::big_int_db_processor::{ BigIntDbProcessor, BigIntSqlConfig, Param, SQLParamsBuilder, TableNameDAO, }; -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::checked_conversion; use crate::accountant::database_access_objects::receivable_dao::ReceivableDaoError::RusqliteError; use crate::accountant::database_access_objects::utils; diff --git a/node/src/accountant/database_access_objects/utils.rs b/node/src/accountant/database_access_objects/utils.rs index 39671afe9..b7d0b416b 100644 --- a/node/src/accountant/database_access_objects/utils.rs +++ b/node/src/accountant/database_access_objects/utils.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::database_access_objects::payable_dao::PayableAccount; use crate::accountant::database_access_objects::receivable_dao::ReceivableAccount; use crate::accountant::{checked_conversion, gwei_to_wei, sign_conversion}; diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 493c3879a..bd572f301 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod big_int_processing; +pub mod big_int; pub mod database_access_objects; pub mod financials; pub mod payment_adjuster; @@ -30,7 +30,7 @@ use crate::accountant::database_access_objects::utils::{ use crate::accountant::financials::visibility_restricted_module::{ check_query_is_within_tech_limits, financials_entry_check, }; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::scanners::{ScanSchedulers, Scanners}; diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index 2fb47f8bf..e881205b9 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::PreparedAdjustment; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::PreparedAdjustment; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use masq_lib::logger::Logger; #[cfg(test)] @@ -73,7 +73,7 @@ pub enum AnalysisError {} #[cfg(test)] mod tests { use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; - use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::test_utils::{make_payable_account, PayablePaymentsAgentMock}; diff --git a/node/src/accountant/scanners/scanner_mid_procedures/mod.rs b/node/src/accountant/scanners/mid_scan_msg_handling/mod.rs similarity index 100% rename from node/src/accountant/scanners/scanner_mid_procedures/mod.rs rename to node/src/accountant/scanners/mid_scan_msg_handling/mod.rs diff --git a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_abstract_layer.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs similarity index 100% rename from node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_abstract_layer.rs rename to node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs diff --git a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs similarity index 94% rename from node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs rename to node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs index 6c46d3e05..969894ab1 100644 --- a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/agent_web3.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use web3::types::U256; @@ -72,8 +72,8 @@ impl PayablePaymentsAgentWeb3 { #[cfg(test)] mod tests { - use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; - use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::{ + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::{ PayablePaymentsAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::db_config::persistent_configuration::PersistentConfigError; diff --git a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs similarity index 90% rename from node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs rename to node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs index 144e2566a..7f708908c 100644 --- a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/mod.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs @@ -1,11 +1,11 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod agent_abstract_layer; +pub mod agent; pub mod agent_web3; pub mod setup_msg; use crate::accountant::payment_adjuster::Adjustment; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::scanners::Scanner; use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; use actix::Message; diff --git a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/setup_msg.rs similarity index 92% rename from node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs rename to node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/setup_msg.rs index a54ea8907..048afe50b 100644 --- a/node/src/accountant/scanners/scanner_mid_procedures/payable_scanner/setup_msg.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/setup_msg.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; use actix::Message; use std::fmt::Debug; diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index cb0245eaa..376e346fa 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod scanner_mid_procedures; +pub mod mid_scan_msg_handling; pub mod scanners_utils; use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PayableDao, PendingPayable}; @@ -55,8 +55,8 @@ use std::time::{Duration, SystemTime}; use time::format_description::parse; use time::OffsetDateTime; use web3::types::{TransactionReceipt, H256}; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, PayableScannerMidScanProcedures}; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{PayablePaymentsSetupMsg, QualifiedPayablesMessage}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, PayableScannerMidScanProcedures}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{PayablePaymentsSetupMsg, QualifiedPayablesMessage}; pub struct Scanners { pub payable: Box>, @@ -1032,7 +1032,7 @@ mod tests { }; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoError; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t}; - use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::PendingPayableScanReport; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::{Correct, Failed}; use crate::blockchain::blockchain_interface::{ diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index e6a159adb..443cb5439 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -14,11 +14,11 @@ use crate::accountant::database_access_objects::receivable_dao::{ }; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t, CustomQuery}; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::{ +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::{ MultistagePayableScanner, PayableScannerMidScanProcedures, PreparedAdjustment, }; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableThresholdsGauge; diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 859142b21..387cabe14 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::{ +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; use crate::accountant::{ diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index 15c401e96..f6df95621 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::PayablePaymentsAgentWeb3; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::PayablePaymentsAgentWeb3; use crate::accountant::{comma_joined_stringifiable, gwei_to_wei}; use crate::blockchain::batch_payable_tools::{BatchPayableTools, BatchPayableToolsReal}; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; @@ -724,7 +724,7 @@ mod tests { use super::*; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::gwei_to_wei; - use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::accountant::test_utils::{ make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, PayablePaymentsAgentMock, diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index 66f5f9c48..bb0906895 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; use crate::blockchain::batch_payable_tools::BatchPayableTools; use web3::transports::{Batch, EventLoopHandle, Http}; use web3::types::{Address, Bytes, SignedTransaction, TransactionParameters, U256}; diff --git a/node/src/database/db_migrations/migrations/migration_6_to_7.rs b/node/src/database/db_migrations/migrations/migration_6_to_7.rs index 0fa8ab6c9..373e71239 100644 --- a/node/src/database/db_migrations/migrations/migration_6_to_7.rs +++ b/node/src/database/db_migrations/migrations/migration_6_to_7.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::big_int_processing::big_int_divider::BigIntDivider; +use crate::accountant::big_int::big_int_divider::BigIntDivider; use crate::accountant::database_access_objects::utils::VigilantRusqliteFlatten; use crate::accountant::gwei_to_wei; use crate::database::db_migrations::db_migrator::DatabaseMigration; diff --git a/node/src/sub_lib/accountant.rs b/node/src/sub_lib/accountant.rs index 88dec3949..e2c8a1770 100644 --- a/node/src/sub_lib/accountant.rs +++ b/node/src/sub_lib/accountant.rs @@ -3,7 +3,7 @@ use crate::accountant::database_access_objects::banned_dao::BannedDaoFactory; use crate::accountant::database_access_objects::payable_dao::PayableDaoFactory; use crate::accountant::database_access_objects::pending_payable_dao::PendingPayableDaoFactory; use crate::accountant::database_access_objects::receivable_dao::ReceivableDaoFactory; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::PayablePaymentsSetupMsg; use crate::accountant::{ checked_conversion, Accountant, ReceivedPayments, ReportTransactionReceipts, ScanError, SentPayables, diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 47cc80fc1..48f8ead25 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::agent_abstract_layer::PayablePaymentsAgent; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index ba8f7a1b5..7bd9b0879 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. #![cfg(test)] -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::PayablePaymentsSetupMsg; -use crate::accountant::scanners::scanner_mid_procedures::payable_scanner::setup_msg::QualifiedPayablesMessage; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::PayablePaymentsSetupMsg; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::QualifiedPayablesMessage; use crate::accountant::ReportTransactionReceipts; use crate::accountant::{ ReceivedPayments, RequestTransactionReceipts, ScanError, ScanForPayables, From f2b7f17b3ef7b080d2bfbf1a30e975a071312e77 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 14 Aug 2023 11:44:31 +0200 Subject: [PATCH 08/10] GH-672: almost all things done; AgentDigest fully in --- .../big_int/big_int_db_processor.rs | 4 +- .../database_access_objects/receivable_dao.rs | 4 +- node/src/accountant/mod.rs | 52 +++-- .../payable_scanner/agent.rs | 24 ++- .../payable_scanner/agent_null.rs | 201 ++++++++++++++++++ .../payable_scanner/agent_web3.rs | 154 ++++++++++---- .../payable_scanner/mod.rs | 1 + node/src/accountant/test_utils.rs | 108 ++++++---- node/src/actor_system_factory.rs | 3 +- node/src/blockchain/blockchain_bridge.rs | 132 ++++++------ node/src/blockchain/blockchain_interface.rs | 79 ++++--- node/src/blockchain/payer.rs | 4 +- node/src/blockchain/test_utils.rs | 16 +- node/src/sub_lib/blockchain_bridge.rs | 9 + node/src/sub_lib/cryptde.rs | 2 +- node/src/sub_lib/cryptde_null.rs | 4 +- node/src/sub_lib/cryptde_real.rs | 2 +- node/src/sub_lib/wallet.rs | 2 +- 18 files changed, 571 insertions(+), 230 deletions(-) create mode 100644 node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs diff --git a/node/src/accountant/big_int/big_int_db_processor.rs b/node/src/accountant/big_int/big_int_db_processor.rs index e06ba9745..c8d83b621 100644 --- a/node/src/accountant/big_int/big_int_db_processor.rs +++ b/node/src/accountant/big_int/big_int_db_processor.rs @@ -500,9 +500,7 @@ mod tests { use super::*; use crate::accountant::big_int::big_int_db_processor::ByteMagnitude::{High, Low}; use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::TestKey; - use crate::accountant::big_int::big_int_db_processor::WeiChange::{ - Addition, Subtraction, - }; + use crate::accountant::big_int::big_int_db_processor::WeiChange::{Addition, Subtraction}; use crate::accountant::big_int::test_utils::restricted::{ create_new_empty_db, test_database_key, }; diff --git a/node/src/accountant/database_access_objects/receivable_dao.rs b/node/src/accountant/database_access_objects/receivable_dao.rs index 76dd9a0bc..0519778cf 100644 --- a/node/src/accountant/database_access_objects/receivable_dao.rs +++ b/node/src/accountant/database_access_objects/receivable_dao.rs @@ -1,9 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::big_int::big_int_db_processor::KnownKeyVariants::WalletAddress; -use crate::accountant::big_int::big_int_db_processor::WeiChange::{ - Addition, Subtraction, -}; +use crate::accountant::big_int::big_int_db_processor::WeiChange::{Addition, Subtraction}; use crate::accountant::big_int::big_int_db_processor::{ BigIntDbProcessor, BigIntSqlConfig, Param, SQLParamsBuilder, TableNameDAO, }; diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index bd572f301..b93a72be1 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -996,10 +996,10 @@ mod tests { }; use crate::accountant::test_utils::{ bc_from_earning_wallet, bc_from_wallets, make_payable_account, make_payables, - BannedDaoFactoryMock, MessageIdGeneratorMock, NullScanner, PayableDaoFactoryMock, - PayableDaoMock, PayablePaymentsAgentMock, PayableScannerBuilder, PaymentAdjusterMock, - PendingPayableDaoFactoryMock, PendingPayableDaoMock, ReceivableDaoFactoryMock, - ReceivableDaoMock, ScannerMock, + AgentDigestMock, BannedDaoFactoryMock, MessageIdGeneratorMock, NullScanner, + PayableDaoFactoryMock, PayableDaoMock, PayablePaymentsAgentMock, PayableScannerBuilder, + PaymentAdjusterMock, PendingPayableDaoFactoryMock, PendingPayableDaoMock, + ReceivableDaoFactoryMock, ReceivableDaoMock, ScannerMock, }; use crate::accountant::test_utils::{AccountantBuilder, BannedDaoMock}; use crate::accountant::Accountant; @@ -3116,7 +3116,9 @@ mod tests { #[test] fn pending_transaction_is_registered_and_monitored_until_it_gets_confirmed_or_canceled() { init_test_logging(); - let set_up_consuming_balances_params_arc = Arc::new(Mutex::new(vec![])); + let set_consuming_balances_params_arc = Arc::new(Mutex::new(vec![])); + let set_agreed_fee_per_computation_unit_params_arc = Arc::new(Mutex::new(vec![])); + let make_agent_digest_params_arc = Arc::new(Mutex::new(vec![])); let mark_pending_payable_params_arc = Arc::new(Mutex::new(vec![])); let transactions_confirmed_params_arc = Arc::new(Mutex::new(vec![])); let get_transaction_receipt_params_arc = Arc::new(Mutex::new(vec![])); @@ -3155,17 +3157,25 @@ mod tests { let transaction_receipt_tx_2_third_round = TransactionReceipt::default(); let mut transaction_receipt_tx_2_fourth_round = TransactionReceipt::default(); transaction_receipt_tx_2_fourth_round.status = Some(U64::from(1)); // confirmed + let agent_digest_id_stamp = ArbitraryIdStamp::new(); + let agent_digest = AgentDigestMock::default().set_arbitrary_id_stamp(agent_digest_id_stamp); let agent = PayablePaymentsAgentMock::default() - .set_consuming_wallet_balances_params(&set_up_consuming_balances_params_arc) - .set_required_fee_per_computed_unit_result(Ok(())); + .set_consuming_wallet_balances_params(&set_consuming_balances_params_arc) + .set_agreed_fee_per_computation_unit_params( + &set_agreed_fee_per_computation_unit_params_arc, + ) + .set_agreed_fee_per_computation_unit_result(Ok(())) + .make_agent_digest_params(&make_agent_digest_params_arc) + .make_agent_digest_result(Ok(Box::new(agent_digest))); let transaction_fee_balance = U256::from(444_555_666_777_u64); let token_balance = U256::from(111_111_111_111_111_111_u64); + let blockchain_interface_id_stamp = ArbitraryIdStamp::new(); let blockchain_interface = BlockchainInterfaceMock::default() + .set_arbitrary_id_stamp(blockchain_interface_id_stamp) .get_transaction_fee_balance_result(Ok(transaction_fee_balance)) .get_token_balance_result(Ok(token_balance)) .build_payable_payments_agent_result(Box::new(agent)) .get_transaction_count_result(Ok(web3::types::U256::from(1))) - .get_transaction_count_result(Ok(web3::types::U256::from(2))) // because we cannot have both, resolution on the high level and also of what's inside blockchain interface, // there is one component missing in this wholesome test - the part where we send a request for // a fingerprint of that payable in the DB - this happens inside send_raw_transaction() @@ -3189,12 +3199,15 @@ mod tests { .get_transaction_receipt_result(Ok(Some(transaction_receipt_tx_2_fourth_round))); let consuming_wallet = make_paying_wallet(b"wallet"); let system = System::new("pending_transaction"); - let persistent_config = PersistentConfigurationMock::default().gas_price_result(Ok(130)); + let persistent_config_id_stamp = ArbitraryIdStamp::new(); + let persistent_config = PersistentConfigurationMock::default() + .set_arbitrary_id_stamp(persistent_config_id_stamp) + .gas_price_result(Ok(130)); let blockchain_bridge = BlockchainBridge::new( Box::new(blockchain_interface), Box::new(persistent_config), false, - Some(consuming_wallet), + Some(consuming_wallet.clone()), ); let account_1 = PayableAccount { wallet: wallet_account_1.clone(), @@ -3366,16 +3379,29 @@ mod tests { pending_tx_hash_2, ] ); - let set_up_consuming_wallet_balances_params = - set_up_consuming_balances_params_arc.lock().unwrap(); + let set_consuming_wallet_balances_params = + set_consuming_balances_params_arc.lock().unwrap(); let expected_consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: transaction_fee_balance, masq_token_balance_in_minor_units: token_balance, }; assert_eq!( - *set_up_consuming_wallet_balances_params, + *set_consuming_wallet_balances_params, vec![expected_consuming_wallet_balances] ); + let set_agreed_fee_per_computation_unit_params = + set_agreed_fee_per_computation_unit_params_arc + .lock() + .unwrap(); + assert_eq!( + *set_agreed_fee_per_computation_unit_params, + vec![persistent_config_id_stamp] + ); + let make_agent_digest_params = make_agent_digest_params_arc.lock().unwrap(); + assert_eq!( + *make_agent_digest_params, + vec![(blockchain_interface_id_stamp, consuming_wallet)] + ); let update_fingerprints_params = update_fingerprint_params_arc.lock().unwrap(); assert_eq!( *update_fingerprints_params, diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs index b2d3b75b9..eece3c0db 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs @@ -2,10 +2,14 @@ #[cfg(test)] use crate::arbitrary_id_stamp_in_trait; +use crate::blockchain::blockchain_interface::{BlockchainError, BlockchainInterface}; use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::wallet::Wallet; #[cfg(test)] use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; +#[cfg(test)] +use std::any::Any; use web3::types::U256; // Table of chains by @@ -25,17 +29,29 @@ use web3::types::U256; //* defaulted limit pub trait PayablePaymentsAgent: Send { - fn set_required_fee_per_computed_unit( + fn set_agreed_fee_per_computation_unit( &mut self, persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError>; - fn set_pending_transaction_id(&mut self, id: U256); fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances); fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128; fn consuming_wallet_balances(&self) -> Option; - fn required_fee_per_computed_unit(&self) -> Option; - fn pending_transaction_id(&self) -> Option; + fn make_agent_digest( + &self, + blockchain_interface: &dyn BlockchainInterface, + wallet: &Wallet, + ) -> Result, BlockchainError>; + + #[cfg(test)] + arbitrary_id_stamp_in_trait!(); +} + +// designed not to include unnecessary setter methods +pub trait AgentDigest: Send { + fn agreed_fee_per_computation_unit(&self) -> u64; + fn pending_transaction_id(&self) -> U256; + declare_as_any!(); #[cfg(test)] arbitrary_id_stamp_in_trait!(); } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs new file mode 100644 index 000000000..cae4fff8a --- /dev/null +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs @@ -0,0 +1,201 @@ +// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. + +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, +}; +use crate::blockchain::blockchain_interface::{BlockchainError, BlockchainInterface}; +use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::wallet::Wallet; +use ethereum_types::U256; +use masq_lib::logger::Logger; +#[cfg(test)] +use std::any::Any; + +pub struct PayablePaymentsAgentNull { + logger: Logger, +} + +impl PayablePaymentsAgent for PayablePaymentsAgentNull { + fn set_agreed_fee_per_computation_unit( + &mut self, + _persistent_config: &dyn PersistentConfiguration, + ) -> Result<(), PersistentConfigError> { + self.log_function_call("set_agreed_fee_per_computation_unit()"); + Ok(()) + } + + fn set_consuming_wallet_balances(&mut self, _balances: ConsumingWalletBalances) { + self.log_function_call("set_consuming_wallet_balances()") + } + + fn estimated_transaction_fee_total(&self, _number_of_transactions: usize) -> u128 { + self.log_function_call("estimated_transaction_fee_total()"); + 0 + } + + fn consuming_wallet_balances(&self) -> Option { + self.log_function_call("consuming_wallet_balances()"); + None + } + + fn make_agent_digest( + &self, + _blockchain_interface: &dyn BlockchainInterface, + _wallet: &Wallet, + ) -> Result, BlockchainError> { + self.log_function_call("make_agent_digest()"); + Ok(Box::new(AgentDigestNull::new())) + } +} + +impl PayablePaymentsAgentNull { + pub fn new() -> Self { + Self { + logger: Logger::new("PayablePaymentsAgentNull"), + } + } + + fn log_function_call(&self, function_call: &str) { + error!( + self.logger, + "calling null version of {function_call} will be without effect" + ); + } +} + +pub struct AgentDigestNull {} + +impl AgentDigest for AgentDigestNull { + fn agreed_fee_per_computation_unit(&self) -> u64 { + todo!() + } + + fn pending_transaction_id(&self) -> U256 { + todo!() + } + + implement_as_any!(); +} + +impl AgentDigestNull { + pub fn new() -> Self { + Self {} + } +} + +#[cfg(test)] +mod tests { + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_null::{ + AgentDigestNull, PayablePaymentsAgentNull, + }; + use crate::blockchain::test_utils::BlockchainInterfaceMock; + use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; + use crate::test_utils::make_wallet; + use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; + use masq_lib::logger::Logger; + use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; + use web3::types::U256; + + #[test] + fn payable_payments_agent_null_constructor_works() { + init_test_logging(); + + let result = PayablePaymentsAgentNull::new(); + + warning!( + result.logger, + "payable_payments_agent_null_constructor_works" + ); + TestLogHandler::default().exists_log_containing( + "WARN: PayablePaymentsAgentNull: \ + payable_payments_agent_null_constructor_works", + ); + } + + #[test] + fn null_agent_set_agreed_fee_per_computation_unit() { + init_test_logging(); + let test_name = "null_agent_set_agreed_fee_per_computation_unit"; + let mut subject = PayablePaymentsAgentNull::new(); + subject.logger = Logger::new(test_name); + let persistent_config = PersistentConfigurationMock::new(); + + let result = subject.set_agreed_fee_per_computation_unit(&persistent_config); + + assert_eq!(result, Ok(())); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling null \ + version of set_agreed_fee_per_computation_unit() will be without effect" + )); + } + + #[test] + fn null_agent_set_consuming_wallet_balances() { + init_test_logging(); + let test_name = "null_agent_set_consuming_wallet_balances"; + let mut subject = PayablePaymentsAgentNull::new(); + subject.logger = Logger::new(test_name); + let balances = ConsumingWalletBalances::new(U256::from(45678), U256::from(12345)); + + subject.set_consuming_wallet_balances(balances); + + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling \ + null version of set_consuming_wallet_balances() will be without effect" + )); + } + + #[test] + fn null_agent_estimated_transaction_fee_total() { + init_test_logging(); + let test_name = "null_agent_estimated_transaction_fee_total"; + let mut subject = PayablePaymentsAgentNull::new(); + subject.logger = Logger::new(test_name); + + let result = subject.estimated_transaction_fee_total(4); + + assert_eq!(result, 0); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling \ + null version of estimated_transaction_fee_total() will be without effect" + )); + } + + #[test] + fn null_agent_consuming_wallet_balances() { + init_test_logging(); + let test_name = "null_agent_consuming_wallet_balances"; + let mut subject = PayablePaymentsAgentNull::new(); + subject.logger = Logger::new(test_name); + + let result = subject.consuming_wallet_balances(); + + assert_eq!(result, None); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling \ + null version of consuming_wallet_balances() will be without effect" + )); + } + + #[test] + fn null_agent_make_agent_digest() { + init_test_logging(); + let test_name = "null_agent_make_agent_digest"; + let mut subject = PayablePaymentsAgentNull::new(); + subject.logger = Logger::new(test_name); + let blockchain_interface = BlockchainInterfaceMock::default(); + let wallet = make_wallet("abc"); + + let result = subject + .make_agent_digest(&blockchain_interface, &wallet) + .unwrap(); + + result.as_any().downcast_ref::().unwrap(); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling \ + null version of make_agent_digest() will be without effect" + )); + } +} diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs index 969894ab1..b02b1f914 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_web3.rs @@ -1,8 +1,15 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, +}; +use crate::blockchain::blockchain_interface::{BlockchainError, BlockchainInterface}; use crate::db_config::persistent_configuration::{PersistentConfigError, PersistentConfiguration}; +use crate::masq_lib::utils::ExpectValue; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::wallet::Wallet; +#[cfg(test)] +use std::any::Any; use web3::types::U256; #[derive(Debug, Clone)] @@ -10,12 +17,11 @@ pub struct PayablePaymentsAgentWeb3 { gas_limit_const_part: u64, maximum_added_gas_margin: u64, consuming_wallet_balances_opt: Option, - pending_transaction_id_opt: Option, gwei_per_computed_unit_opt: Option, } impl PayablePaymentsAgent for PayablePaymentsAgentWeb3 { - fn set_required_fee_per_computed_unit( + fn set_agreed_fee_per_computation_unit( &mut self, persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError> { @@ -24,33 +30,28 @@ impl PayablePaymentsAgent for PayablePaymentsAgentWeb3 { Ok(()) } - fn set_pending_transaction_id(&mut self, id: U256) { - self.pending_transaction_id_opt.replace(id); - } - fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { self.consuming_wallet_balances_opt.replace(balances); } fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128 { - let gas_price = self - .gwei_per_computed_unit_opt - .expect("gas price must be set before this") as u128; - number_of_transactions as u128 - * gas_price - * (self.maximum_added_gas_margin + self.gas_limit_const_part) as u128 + let gas_price = self.gwei_per_computed_unit_opt.expectv("gas price") as u128; + let max_gas_limit = (self.maximum_added_gas_margin + self.gas_limit_const_part) as u128; + number_of_transactions as u128 * gas_price * max_gas_limit } fn consuming_wallet_balances(&self) -> Option { self.consuming_wallet_balances_opt } - fn required_fee_per_computed_unit(&self) -> Option { - self.gwei_per_computed_unit_opt - } - - fn pending_transaction_id(&self) -> Option { - self.pending_transaction_id_opt + fn make_agent_digest( + &self, + blockchain_interface: &dyn BlockchainInterface, + wallet: &Wallet, + ) -> Result, BlockchainError> { + let id = blockchain_interface.get_transaction_count(wallet)?; + let gas_price_gwei = self.gwei_per_computed_unit_opt.expectv("gas price"); + Ok(Box::new(AgentDigestWeb3::new(gas_price_gwei, id))) } } @@ -64,21 +65,52 @@ impl PayablePaymentsAgentWeb3 { gas_limit_const_part, maximum_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, consuming_wallet_balances_opt: None, - pending_transaction_id_opt: None, gwei_per_computed_unit_opt: None, } } } +pub struct AgentDigestWeb3 { + gas_price_gwei: u64, + pending_transaction_id: U256, +} + +impl AgentDigest for AgentDigestWeb3 { + fn agreed_fee_per_computation_unit(&self) -> u64 { + self.gas_price_gwei + } + + fn pending_transaction_id(&self) -> U256 { + self.pending_transaction_id + } + + implement_as_any!(); +} + +impl AgentDigestWeb3 { + pub fn new(gas_price_gwei: u64, pending_transaction_id: U256) -> Self { + Self { + gas_price_gwei, + pending_transaction_id, + } + } +} + #[cfg(test)] mod tests { - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, + }; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::{ - PayablePaymentsAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + AgentDigestWeb3, PayablePaymentsAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; + use crate::blockchain::blockchain_interface::BlockchainError; + use crate::blockchain::test_utils::BlockchainInterfaceMock; use crate::db_config::persistent_configuration::PersistentConfigError; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; + use crate::test_utils::make_wallet; use crate::test_utils::persistent_configuration_mock::PersistentConfigurationMock; + use std::sync::{Arc, Mutex}; use web3::types::U256; #[test] @@ -95,42 +127,21 @@ mod tests { subject.maximum_added_gas_margin, WEB3_MAXIMAL_GAS_LIMIT_MARGIN ); - assert_eq!(subject.pending_transaction_id_opt, None); assert_eq!(subject.gwei_per_computed_unit_opt, None); assert_eq!(subject.consuming_wallet_balances_opt, None) } #[test] - fn set_and_get_methods_for_required_fee_per_computed_unit_happy_path() { - let persistent_config = PersistentConfigurationMock::default().gas_price_result(Ok(130)); - let mut subject = PayablePaymentsAgentWeb3::new(12345); - - let result = subject.set_required_fee_per_computed_unit(&persistent_config); - - assert_eq!(result, Ok(())); - assert_eq!(subject.required_fee_per_computed_unit(), Some(130)) - } - - #[test] - fn set_and_get_methods_for_required_fee_per_computed_unit_sad_path() { + fn set_and_get_methods_for_agreed_fee_per_computation_unit_sad_path() { let persistent_config = PersistentConfigurationMock::default() .gas_price_result(Err(PersistentConfigError::TransactionError)); let mut subject = PayablePaymentsAgentWeb3::new(12345); - let result = subject.set_required_fee_per_computed_unit(&persistent_config); + let result = subject.set_agreed_fee_per_computation_unit(&persistent_config); assert_eq!(result, Err(PersistentConfigError::TransactionError)); } - #[test] - fn set_and_get_methods_for_pending_transaction_id_work() { - let mut subject = PayablePaymentsAgentWeb3::new(12345); - - subject.set_pending_transaction_id(U256::from(654)); - - assert_eq!(subject.pending_transaction_id(), Some(U256::from(654))) - } - #[test] fn set_and_get_methods_for_consuming_wallet_balances_work() { let mut subject = PayablePaymentsAgentWeb3::new(12345); @@ -156,10 +167,10 @@ mod tests { let mut second_agent = PayablePaymentsAgentWeb3::new(444); one_agent - .set_required_fee_per_computed_unit(&persistent_config) + .set_agreed_fee_per_computation_unit(&persistent_config) .unwrap(); second_agent - .set_required_fee_per_computed_unit(&persistent_config) + .set_agreed_fee_per_computation_unit(&persistent_config) .unwrap(); assert_eq!( @@ -171,4 +182,53 @@ mod tests { (3 * (444 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) as u128 * 550 ) } + + #[test] + fn make_agent_digest_happy_path() { + let get_transaction_count_params_arc = Arc::new(Mutex::new(vec![])); + let mut subject = PayablePaymentsAgentWeb3::new(12345); + subject.gwei_per_computed_unit_opt = Some(234); + let consuming_wallet = make_wallet("efg"); + let blockchain_interface = BlockchainInterfaceMock::default() + .get_transaction_count_params(&get_transaction_count_params_arc) + .get_transaction_count_result(Ok(U256::from(45))); + + let result = subject + .make_agent_digest(&blockchain_interface, &consuming_wallet) + .unwrap(); + + let digest = result.as_any().downcast_ref::().unwrap(); + assert_eq!(digest.agreed_fee_per_computation_unit(), 234); + assert_eq!(digest.pending_transaction_id(), U256::from(45)); + } + + #[test] + fn make_agent_digest_sad_path() { + let subject = PayablePaymentsAgentWeb3::new(12345); + let consuming_wallet = make_wallet("efg"); + let blockchain_interface = BlockchainInterfaceMock::default() + .get_transaction_count_result(Err(BlockchainError::InvalidResponse)); + + let result = subject.make_agent_digest(&blockchain_interface, &consuming_wallet); + + let err = match result { + Err(e) => e, + Ok(_) => panic!("we expected error but got ok"), + }; + assert_eq!(err, BlockchainError::InvalidResponse); + } + + #[test] + fn agreed_fee_per_computation_unit_works() { + let subject = AgentDigestWeb3::new(111, U256::from(33)); + + assert_eq!(subject.agreed_fee_per_computation_unit(), 111) + } + + #[test] + fn pending_transaction_id_works() { + let subject = AgentDigestWeb3::new(111, U256::from(33)); + + assert_eq!(subject.pending_transaction_id(), U256::from(33)) + } } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs index 7f708908c..7c87ac823 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/mod.rs @@ -1,6 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. pub mod agent; +pub mod agent_null; pub mod agent_web3; pub mod setup_msg; diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 443cb5439..f117ea432 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -14,7 +14,9 @@ use crate::accountant::database_access_objects::receivable_dao::{ }; use crate::accountant::database_access_objects::utils::{from_time_t, to_time_t, CustomQuery}; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, +}; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::setup_msg::{ PayablePaymentsSetupMsg, QualifiedPayablesMessage, }; @@ -30,7 +32,9 @@ use crate::accountant::{ gwei_to_wei, Accountant, ResponseSkeleton, SentPayables, DEFAULT_PENDING_TOO_LONG_SEC, }; use crate::blockchain::blockchain_bridge::PendingPayableFingerprint; -use crate::blockchain::blockchain_interface::BlockchainTransaction; +use crate::blockchain::blockchain_interface::{ + BlockchainError, BlockchainInterface, BlockchainTransaction, +}; use crate::blockchain::test_utils::make_tx_hash; use crate::bootstrapper::BootstrapperConfig; use crate::db_config::config_dao::{ConfigDao, ConfigDaoFactory}; @@ -1687,36 +1691,28 @@ impl ScanSchedulers { #[derive(Default)] pub struct PayablePaymentsAgentMock { - set_required_fee_per_computed_unit_params: Arc>>, - set_required_fee_per_computed_unit_results: RefCell>>, - set_pending_transaction_id_params: Arc>>, + set_agreed_fee_per_computation_unit_params: Arc>>, + set_agreed_fee_per_computation_unit_results: RefCell>>, set_consuming_wallet_balances_params: Arc>>, - required_fee_per_computed_unit_results: RefCell>>, - pending_transaction_id_results: RefCell>>, + make_agent_digest_params: Arc>>, + make_agent_digest_results: RefCell, BlockchainError>>>, arbitrary_id_stamp_opt: Option, } impl PayablePaymentsAgent for PayablePaymentsAgentMock { - fn set_required_fee_per_computed_unit( + fn set_agreed_fee_per_computation_unit( &mut self, persistent_config: &dyn PersistentConfiguration, ) -> Result<(), PersistentConfigError> { - self.set_required_fee_per_computed_unit_params + self.set_agreed_fee_per_computation_unit_params .lock() .unwrap() .push(persistent_config.arbitrary_id_stamp()); - self.set_required_fee_per_computed_unit_results + self.set_agreed_fee_per_computation_unit_results .borrow_mut() .remove(0) } - fn set_pending_transaction_id(&mut self, id: U256) { - self.set_pending_transaction_id_params - .lock() - .unwrap() - .push(id); - } - fn set_consuming_wallet_balances(&mut self, balances: ConsumingWalletBalances) { self.set_consuming_wallet_balances_params .lock() @@ -1732,43 +1728,40 @@ impl PayablePaymentsAgent for PayablePaymentsAgentMock { todo!("to be implemented by GH-711") } - fn required_fee_per_computed_unit(&self) -> Option { - self.required_fee_per_computed_unit_results - .borrow_mut() - .remove(0) - } - - fn pending_transaction_id(&self) -> Option { - self.pending_transaction_id_results.borrow_mut().remove(0) + fn make_agent_digest( + &self, + blockchain_interface: &dyn BlockchainInterface, + wallet: &Wallet, + ) -> Result, BlockchainError> { + self.make_agent_digest_params + .lock() + .unwrap() + .push((blockchain_interface.arbitrary_id_stamp(), wallet.clone())); + self.make_agent_digest_results.borrow_mut().remove(0) } arbitrary_id_stamp_in_trait_impl!(); } impl PayablePaymentsAgentMock { - pub fn set_required_fee_per_computed_unit_params( + pub fn set_agreed_fee_per_computation_unit_params( mut self, params: &Arc>>, ) -> Self { - self.set_required_fee_per_computed_unit_params = params.clone(); + self.set_agreed_fee_per_computation_unit_params = params.clone(); self } - pub fn set_required_fee_per_computed_unit_result( + pub fn set_agreed_fee_per_computation_unit_result( self, result: Result<(), PersistentConfigError>, ) -> Self { - self.set_required_fee_per_computed_unit_results + self.set_agreed_fee_per_computation_unit_results .borrow_mut() .push(result); self } - pub fn set_pending_transaction_id_params(mut self, params: &Arc>>) -> Self { - self.set_pending_transaction_id_params = params.clone(); - self - } - pub fn set_consuming_wallet_balances_params( mut self, params: &Arc>>, @@ -1777,14 +1770,55 @@ impl PayablePaymentsAgentMock { self } - pub fn desired_fee_per_computed_unit_result(self, result: Option) -> Self { - self.required_fee_per_computed_unit_results + pub fn make_agent_digest_params( + mut self, + params: &Arc>>, + ) -> Self { + self.make_agent_digest_params = params.clone(); + self + } + + pub fn make_agent_digest_result( + self, + result: Result, BlockchainError>, + ) -> Self { + self.make_agent_digest_results.borrow_mut().push(result); + self + } + + set_arbitrary_id_stamp_in_mock_impl!(); +} + +#[derive(Default)] +pub struct AgentDigestMock { + agreed_fee_per_computation_unit_results: RefCell>, + pending_transaction_id_results: RefCell>, + arbitrary_id_stamp_opt: Option, +} + +impl AgentDigest for AgentDigestMock { + fn agreed_fee_per_computation_unit(&self) -> u64 { + self.agreed_fee_per_computation_unit_results + .borrow_mut() + .remove(0) + } + + fn pending_transaction_id(&self) -> U256 { + self.pending_transaction_id_results.borrow_mut().remove(0) + } + + arbitrary_id_stamp_in_trait_impl!(); +} + +impl AgentDigestMock { + pub fn agreed_fee_per_computation_unit_result(self, result: u64) -> Self { + self.agreed_fee_per_computation_unit_results .borrow_mut() .push(result); self } - pub fn pending_transaction_id_result(self, result: Option) -> Self { + pub fn pending_transaction_id(self, result: U256) -> Self { self.pending_transaction_id_results .borrow_mut() .push(result); diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index 06b6c981d..5ae3aef38 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -13,6 +13,7 @@ use super::ui_gateway::UiGateway; use crate::accountant::database_access_objects::banned_dao::{ BannedCacheLoader, BannedCacheLoaderReal, }; +use crate::arbitrary_id_stamp_in_trait; use crate::blockchain::blockchain_bridge::{BlockchainBridge, BlockchainBridgeSubsFactory}; use crate::bootstrapper::CryptDEPair; use crate::database::db_initializer::DbInitializationConfig; @@ -943,7 +944,7 @@ mod tests { fn make_and_start_blockchain_bridge( &self, config: &BootstrapperConfig, - subs_factory: &dyn SubsFactory, + _subs_factory: &dyn SubsFactory, ) -> BlockchainBridgeSubs { self.parameters .blockchain_bridge_params diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 387cabe14..8f001de29 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -229,16 +229,10 @@ impl BlockchainBridge { chain: Chain, ) -> Box { match blockchain_service_url_opt { - Some(url) => //match Http::new(&url) { - // Ok((event_loop_handle, transport)) => { - { - let initializer = BlockchainInterfaceInitializer {}; - initializer.initialize_chain_compatible_interface(&url, chain) - // } -// Err(e) => panic!("Invalid blockchain node URL: {:?}", e), - // } - } - , + Some(url) => { + let initializer = BlockchainInterfaceInitializer {}; + initializer.initialize_chain_compatible_interface(&url, chain) + } None => Box::new(BlockchainInterfaceClandestine::new(chain)), //TODO make sure this is tested for BlockchainInterfaceNull (after the merge??) } } @@ -295,17 +289,13 @@ impl BlockchainBridge { } }; - let consuming_wallet_balances = { - ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: transaction_fee_balance, - masq_token_balance_in_minor_units: token_balance, - } - }; + let consuming_wallet_balances = + ConsumingWalletBalances::new(transaction_fee_balance, token_balance); let mut agent = self.blockchain_interface.build_payable_payments_agent(); agent.set_consuming_wallet_balances(consuming_wallet_balances); - match agent.set_required_fee_per_computed_unit(self.persistent_config.as_ref()) { + match agent.set_agreed_fee_per_computation_unit(self.persistent_config.as_ref()) { Ok(()) => (), Err(e) => { return Err(format!( @@ -331,9 +321,9 @@ impl BlockchainBridge { msg: OutboundPaymentsInstructions, ) -> Result<(), String> { let skeleton_opt = msg.response_skeleton_opt; - let mut agent = msg.agent; + let agent = msg.agent; let checked_accounts = msg.affordable_accounts; - let result = self.process_payments(agent.as_mut(), checked_accounts); + let result = self.process_payments(&*agent, checked_accounts); let locally_produced_result = match &result { Err(e) => Err(format!("ReportAccountsPayable: {}", e)), @@ -462,26 +452,21 @@ impl BlockchainBridge { fn process_payments( &self, - agent: &mut dyn PayablePaymentsAgent, + agent: &dyn PayablePaymentsAgent, affordable_accounts: Vec, ) -> Result, PayableTransactionError> { let consuming_wallet = self .consuming_wallet_opt .as_ref() .ok_or(PayableTransactionError::MissingConsumingWallet)?; - - let pending_tx_id = self - .blockchain_interface - .get_transaction_count(consuming_wallet) + let agent_digest = agent + .make_agent_digest(&*self.blockchain_interface, consuming_wallet) .map_err(PayableTransactionError::TransactionCount)?; - - agent.set_pending_transaction_id(pending_tx_id); - let new_fingerprints_recipient = self.new_fingerprints_recipient(); self.blockchain_interface.send_batch_of_payables( consuming_wallet, - agent, + agent_digest, new_fingerprints_recipient, &affordable_accounts, ) @@ -515,7 +500,8 @@ mod tests { use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::test_utils::{ - make_pending_payable_fingerprint, make_qualified_payables_message, PayablePaymentsAgentMock, + make_pending_payable_fingerprint, make_qualified_payables_message, AgentDigestMock, + PayablePaymentsAgentMock, }; use crate::blockchain::bip32::Bip32ECKeyProvider; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::Correct; @@ -557,7 +543,7 @@ mod tests { fn handle( &mut self, msg: AssertionsMessage, - ctx: &mut Self::Context, + _ctx: &mut Self::Context, ) -> Self::Result { (msg.assertions)(self) } @@ -633,19 +619,19 @@ mod tests { ); let get_transaction_fee_balance_params_arc = Arc::new(Mutex::new(vec![])); let get_token_balance_params_arc = Arc::new(Mutex::new(vec![])); - let set_up_consuming_wallet_balances_params_arc = Arc::new(Mutex::new(vec![])); - let conclude_required_fee_per_computed_unit_params_arc = Arc::new(Mutex::new(vec![])); + let set_consuming_wallet_balances_params_arc = Arc::new(Mutex::new(vec![])); + let conclude_agreed_fee_per_computation_unit_params_arc = Arc::new(Mutex::new(vec![])); let (accountant, _, accountant_recording_arc) = make_recorder(); let transaction_fee_balance = U256::from(4455); let token_balance = U256::from(112233); let agent_id_stamp = ArbitraryIdStamp::new(); let agent = PayablePaymentsAgentMock::default() .set_arbitrary_id_stamp(agent_id_stamp) - .set_consuming_wallet_balances_params(&set_up_consuming_wallet_balances_params_arc) - .set_required_fee_per_computed_unit_params( - &conclude_required_fee_per_computed_unit_params_arc, + .set_consuming_wallet_balances_params(&set_consuming_wallet_balances_params_arc) + .set_agreed_fee_per_computation_unit_params( + &conclude_agreed_fee_per_computation_unit_params_arc, ) - .set_required_fee_per_computed_unit_result(Ok(())); + .set_agreed_fee_per_computation_unit_result(Ok(())); let blockchain_interface = BlockchainInterfaceMock::default() .get_transaction_fee_balance_params(&get_transaction_fee_balance_params_arc) .get_transaction_fee_balance_result(Ok(transaction_fee_balance)) @@ -707,21 +693,21 @@ mod tests { ); let get_token_balance_params = get_token_balance_params_arc.lock().unwrap(); assert_eq!(*get_token_balance_params, vec![consuming_wallet]); - let set_up_consuming_wallet_balances_params = - set_up_consuming_wallet_balances_params_arc.lock().unwrap(); + let set_consuming_wallet_balances_params = + set_consuming_wallet_balances_params_arc.lock().unwrap(); assert_eq!( - *set_up_consuming_wallet_balances_params, + *set_consuming_wallet_balances_params, vec![ConsumingWalletBalances { transaction_fee_balance_in_minor_units: transaction_fee_balance, masq_token_balance_in_minor_units: token_balance }] ); - let conclude_required_fee_per_computed_unit_params = - conclude_required_fee_per_computed_unit_params_arc + let conclude_agreed_fee_per_computation_unit_params = + conclude_agreed_fee_per_computation_unit_params_arc .lock() .unwrap(); assert_eq!( - *conclude_required_fee_per_computed_unit_params, + *conclude_agreed_fee_per_computation_unit_params, vec![persistent_config_id_stamp] ); let accountant_received_payment = accountant_recording_arc.lock().unwrap(); @@ -849,7 +835,7 @@ mod tests { #[test] fn handle_payable_payments_setup_msg_payload_fails_on_gas_price_query_on_behalf_of_the_agent() { - let agent = PayablePaymentsAgentMock::default().set_required_fee_per_computed_unit_result( + let agent = PayablePaymentsAgentMock::default().set_agreed_fee_per_computation_unit_result( Err(PersistentConfigError::DatabaseError("siesta".to_string())), ); let blockchain_interface = BlockchainInterfaceMock::default() @@ -890,17 +876,16 @@ mod tests { ) { let system = System::new("handle_outbound_payments_instructions_make_payments_happen_and_sends_payment_results_back_to_accountant"); - let get_transaction_count_params_arc = Arc::new(Mutex::new(vec![])); - let set_up_pending_transaction_id_params_arc = Arc::new(Mutex::new(vec![])); + let make_agent_digest_params_arc = Arc::new(Mutex::new(vec![])); let send_batch_of_payables_params_arc = Arc::new(Mutex::new(vec![])); let (accountant, _, accountant_recording_arc) = make_recorder(); let accountant = accountant.system_stop_conditions(match_every_type_id!(PendingPayableFingerprintSeeds)); let wallet_account_1 = make_wallet("blah"); let wallet_account_2 = make_wallet("foo"); + let blockchain_interface_id_stamp = ArbitraryIdStamp::new(); let blockchain_interface_mock = BlockchainInterfaceMock::default() - .get_transaction_count_params(&get_transaction_count_params_arc) - .get_transaction_count_result(Ok(U256::from(14))) + .set_arbitrary_id_stamp(blockchain_interface_id_stamp) .send_batch_of_payables_params(&send_batch_of_payables_params_arc) .send_batch_of_payables_result(Ok(vec![ Correct(PendingPayable { @@ -936,10 +921,11 @@ mod tests { pending_payable_opt: None, }, ]; - let arbitrary_id_stamp = ArbitraryIdStamp::new(); + let agent_digest_id_stamp = ArbitraryIdStamp::new(); + let agent_digest = AgentDigestMock::default().set_arbitrary_id_stamp(agent_digest_id_stamp); let agent = PayablePaymentsAgentMock::default() - .set_arbitrary_id_stamp(arbitrary_id_stamp) - .set_pending_transaction_id_params(&set_up_pending_transaction_id_params_arc); + .make_agent_digest_params(&make_agent_digest_params_arc) + .make_agent_digest_result(Ok(Box::new(agent_digest))); send_bind_message!(subject_subs, peer_actors); let _ = addr @@ -955,21 +941,22 @@ mod tests { System::current().stop(); system.run(); - let get_transaction_count_params = get_transaction_count_params_arc.lock().unwrap(); + let make_agent_digest_params = make_agent_digest_params_arc.lock().unwrap(); assert_eq!( - *get_transaction_count_params, - vec![consuming_wallet.clone()] + *make_agent_digest_params, + vec![(blockchain_interface_id_stamp, consuming_wallet.clone())] ); - let set_up_pending_transaction_id_params = - set_up_pending_transaction_id_params_arc.lock().unwrap(); - assert_eq!(*set_up_pending_transaction_id_params, vec![U256::from(14)]); let mut send_batch_of_payables_params = send_batch_of_payables_params_arc.lock().unwrap(); //cannot assert on the captured recipient as its actor is gone after the System stops spinning - let (consuming_wallet_actual, agent_arbitrary_id_stamp, _recipient_actual, accounts_actual) = - send_batch_of_payables_params.remove(0); + let ( + consuming_wallet_actual, + actual_agent_digest_id_stamp, + _recipient_actual, + accounts_actual, + ) = send_batch_of_payables_params.remove(0); assert!(send_batch_of_payables_params.is_empty()); assert_eq!(consuming_wallet_actual, consuming_wallet); - assert_eq!(agent_arbitrary_id_stamp, arbitrary_id_stamp); + assert_eq!(actual_agent_digest_id_stamp, agent_digest_id_stamp); assert_eq!(accounts_actual, accounts); let accountant_recording = accountant_recording_arc.lock().unwrap(); let sent_payments_msg = accountant_recording.get_record::(0); @@ -1076,12 +1063,15 @@ mod tests { last_paid_timestamp: from_time_t(150_000_000), pending_payable_opt: None, }]; + let agent_digest = AgentDigestMock::default(); + let agent = PayablePaymentsAgentMock::default() + .make_agent_digest_result(Ok(Box::new(agent_digest))); send_bind_message!(subject_subs, peer_actors); let _ = addr .try_send(OutboundPaymentsInstructions { affordable_accounts: accounts, - agent: Box::new(PayablePaymentsAgentMock::default()), + agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, context_id: 4321, @@ -1123,11 +1113,8 @@ mod tests { } #[test] - fn process_payments_returns_error_fetching_pending_transaction_id() { - let blockchain_interface_mock = BlockchainInterfaceMock::default() - .get_transaction_count_result(Err(BlockchainError::QueryFailed( - "What the hack...??".to_string(), - ))); + fn process_payments_returns_error_making_agent_digest() { + let blockchain_interface_mock = BlockchainInterfaceMock::default(); let consuming_wallet = make_wallet("somewallet"); let persistent_configuration_mock = PersistentConfigurationMock::new().gas_price_result(Ok(3u64)); @@ -1137,7 +1124,9 @@ mod tests { false, Some(consuming_wallet), ); - let mut agent = PayablePaymentsAgentMock::default(); + let agent = PayablePaymentsAgentMock::default().make_agent_digest_result(Err( + BlockchainError::QueryFailed("What the hack...??".to_string()), + )); let checked_accounts = vec![PayableAccount { wallet: make_wallet("blah"), balance_wei: 123_456, @@ -1145,7 +1134,7 @@ mod tests { pending_payable_opt: None, }]; - let result = subject.process_payments(&mut agent, checked_accounts); + let result = subject.process_payments(&agent, checked_accounts); assert_eq!( result, @@ -1161,7 +1150,7 @@ mod tests { let blockchain_interface_mock = BlockchainInterfaceMock::default() .get_transaction_count_result(Ok(web3::types::U256::from(1))) .send_batch_of_payables_result(Err(PayableTransactionError::Sending { - msg: "failure from exhaustion".to_string(), + msg: "failure from chronic exhaustion".to_string(), hashes: vec![transaction_hash], })); let consuming_wallet = make_wallet("somewallet"); @@ -1179,19 +1168,20 @@ mod tests { last_paid_timestamp: SystemTime::now(), pending_payable_opt: None, }]; - let mut agent = PayablePaymentsAgentMock::default(); + let agent = PayablePaymentsAgentMock::default() + .make_agent_digest_result(Ok(Box::new(AgentDigestMock::default()))); let (accountant, _, _) = make_recorder(); let fingerprint_recipient = accountant.start().recipient(); subject .pending_payable_confirmation .new_pp_fingerprints_sub_opt = Some(fingerprint_recipient); - let result = subject.process_payments(&mut agent, checked_accounts); + let result = subject.process_payments(&agent, checked_accounts); assert_eq!( result, Err(PayableTransactionError::Sending { - msg: "failure from exhaustion".to_string(), + msg: "failure from chronic exhaustion".to_string(), hashes: vec![transaction_hash] }) ); diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index f6df95621..d33862948 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -1,15 +1,19 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::database_access_objects::payable_dao::{PayableAccount, PendingPayable}; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, +}; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::PayablePaymentsAgentWeb3; use crate::accountant::{comma_joined_stringifiable, gwei_to_wei}; +use crate::arbitrary_id_stamp_in_trait; use crate::blockchain::batch_payable_tools::{BatchPayableTools, BatchPayableToolsReal}; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; use crate::blockchain::blockchain_interface::BlockchainError::{ InvalidAddress, InvalidResponse, InvalidUrl, QueryFailed, }; use crate::sub_lib::wallet::Wallet; +use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use actix::{Message, Recipient}; use futures::{future, Future}; use itertools::Either::{Left, Right}; @@ -145,7 +149,7 @@ pub trait BlockchainInterface { fn send_batch_of_payables( &self, consuming_wallet: &Wallet, - payable_payments_agent: &dyn PayablePaymentsAgent, + agent_digest: Box, new_fingerprints_recipient: &Recipient, accounts: &[PayableAccount], ) -> Result, PayableTransactionError>; @@ -157,6 +161,9 @@ pub trait BlockchainInterface { fn get_transaction_count(&self, address: &Wallet) -> ResultForNonce; fn get_transaction_receipt(&self, hash: H256) -> ResultForReceipt; + + #[cfg(test)] + arbitrary_id_stamp_in_trait!(); } // TODO: This probably should go away @@ -202,7 +209,7 @@ impl BlockchainInterface for BlockchainInterfaceClandestine { fn send_batch_of_payables( &self, _consuming_wallet: &Wallet, - _payable_payments_agent: &dyn PayablePaymentsAgent, + _agent_digest: Box, _new_fingerprints_recipient: &Recipient, _accounts: &[PayableAccount], ) -> Result, PayableTransactionError> { @@ -358,16 +365,12 @@ where fn send_batch_of_payables( &self, consuming_wallet: &Wallet, - payable_payments_agent: &dyn PayablePaymentsAgent, + agent_digest: Box, new_fingerprints_recipient: &Recipient, accounts: &[PayableAccount], ) -> Result, PayableTransactionError> { - let gas_price = payable_payments_agent - .required_fee_per_computed_unit() - .expect("agent should know the gas price but doesn't"); - let pending_nonce = payable_payments_agent - .pending_transaction_id() - .expect("agent should know the nonce but doesn't"); + let gas_price = agent_digest.agreed_fee_per_computation_unit(); + let pending_nonce = agent_digest.pending_transaction_id(); debug!( self.logger, @@ -724,10 +727,12 @@ mod tests { use super::*; use crate::accountant::database_access_objects::utils::from_time_t; use crate::accountant::gwei_to_wei; - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_null::AgentDigestNull; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::{ + AgentDigestWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + }; use crate::accountant::test_utils::{ make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, - PayablePaymentsAgentMock, }; use crate::blockchain::bip32::Bip32ECKeyProvider; use crate::blockchain::blockchain_interface::ProcessedPayableFallible::{Correct, Failed}; @@ -1177,7 +1182,7 @@ mod tests { let persistent_config = PersistentConfigurationMock::new().gas_price_result(Ok(123)); result - .set_required_fee_per_computed_unit(&persistent_config) + .set_agreed_fee_per_computation_unit(&persistent_config) .unwrap(); assert_eq!( result.estimated_transaction_fee_total(3), @@ -1271,14 +1276,12 @@ mod tests { let accounts_to_process = vec![account_1, account_2, account_3]; let consuming_wallet = make_paying_wallet(b"gdasgsa"); let test_timestamp_before = SystemTime::now(); - let agent = PayablePaymentsAgentMock::default() - .desired_fee_per_computed_unit_result(Some(120)) - .pending_transaction_id_result(Some(U256::from(6))); + let agent_digest = Box::new(AgentDigestWeb3::new(120, U256::from(6))); let result = subject .send_batch_of_payables( &consuming_wallet, - &agent, + agent_digest, &fingerprint_recipient, &accounts_to_process, ) @@ -1512,13 +1515,11 @@ mod tests { second_payment_amount, None, ); - let agent = PayablePaymentsAgentMock::default() - .desired_fee_per_computed_unit_result(Some(123)) - .pending_transaction_id_result(Some(U256::from(4))); + let agent_digest = Box::new(AgentDigestWeb3::new(123, U256::from(4))); let result = subject.send_batch_of_payables( &consuming_wallet, - &agent, + agent_digest, &initiate_fingerprints_recipient, &vec![first_account, second_account], ); @@ -1640,9 +1641,7 @@ mod tests { test_gas_limit_is_between_limits(Chain::EthMainnet) } - fn test_gas_limit_is_between_limits( - chain: Chain - ) { + fn test_gas_limit_is_between_limits(chain: Chain) { let sign_transaction_params_arc = Arc::new(Mutex::new(vec![])); let transport = TestTransport::default(); let mut subject = @@ -1707,12 +1706,10 @@ mod tests { let recipient = Recorder::new().start().recipient(); let consuming_wallet = make_paying_wallet(&b"consume, you greedy fool!"[..]); let accounts = vec![make_payable_account(5555), make_payable_account(6666)]; - let agent = PayablePaymentsAgentMock::default() - .desired_fee_per_computed_unit_result(Some(123)) - .pending_transaction_id_result(Some(U256::from(4))); + let agent_digest = Box::new(AgentDigestWeb3::new(123, U256::from(4))); let result = - subject.send_batch_of_payables(&consuming_wallet, &agent, &recipient, &accounts); + subject.send_batch_of_payables(&consuming_wallet, agent_digest, &recipient, &accounts); assert_eq!( result, @@ -1740,13 +1737,11 @@ mod tests { 9000, None, ); - let agent = PayablePaymentsAgentMock::default() - .desired_fee_per_computed_unit_result(Some(123)) - .pending_transaction_id_result(Some(U256::from(1))); + let agent_digest = Box::new(AgentDigestWeb3::new(123, U256::from(1))); let result = subject.send_batch_of_payables( &incomplete_consuming_wallet, - &agent, + agent_digest, &recipient, &vec![account], ); @@ -1782,13 +1777,11 @@ mod tests { None, ); let consuming_wallet = make_paying_wallet(consuming_wallet_secret_raw_bytes); - let agent = PayablePaymentsAgentMock::default() - .desired_fee_per_computed_unit_result(Some(123)) - .pending_transaction_id_result(Some(U256::from(4))); + let agent_digest = Box::new(AgentDigestWeb3::new(120, U256::from(6))); let result = subject.send_batch_of_payables( &consuming_wallet, - &agent, + agent_digest, &unimportant_recipient, &vec![account], ); @@ -2475,20 +2468,24 @@ mod tests { } #[test] - fn blockchain_interface_clandestine_send_batch_of_payables() { + fn blockchain_interface_clandestine_cannot_send_batch_of_payables() { init_test_logging(); - let test_name = "blockchain_interface_clandestine_send_batch_of_payables"; + let test_name = "blockchain_interface_clandestine_cannot_send_batch_of_payables"; let wallet = make_wallet("blah"); let chains = all_chains(); let (recorder, _, _) = make_recorder(); let recipient = recorder.start().recipient(); - let agent = PayablePaymentsAgentMock::default(); let accounts = vec![make_payable_account(111)]; chains.into_iter().for_each(|chain| { + let agent_digest = Box::new(AgentDigestNull::new()); assert_eq!( - make_clandestine_subject(test_name, chain) - .send_batch_of_payables(&wallet, &agent, &recipient, &accounts), + make_clandestine_subject(test_name, chain).send_batch_of_payables( + &wallet, + agent_digest, + &recipient, + &accounts + ), Err(PayableTransactionError::Sending { msg: "invalid attempt to send txs clandestinely".to_string(), hashes: vec![], diff --git a/node/src/blockchain/payer.rs b/node/src/blockchain/payer.rs index 3979e054e..e0ebb5813 100644 --- a/node/src/blockchain/payer.rs +++ b/node/src/blockchain/payer.rs @@ -74,7 +74,7 @@ mod tests { let public_key = SubPublicKey::new(&b"sign these bytessign these bytes".to_vec()); let payer: Payer = make_payer(&secret, &public_key); - let digest = cryptde::create_digest(&public_key, &TEST_DEFAULT_CHAIN.rec().contract); + let digest = cryptde::make_agent_digest(&public_key, &TEST_DEFAULT_CHAIN.rec().contract); assert!(payer.owns_secret_key(&digest)); } @@ -86,7 +86,7 @@ mod tests { let public_key = SubPublicKey::new(&b"sign these bytessign these bytes".to_vec()); let payer: Payer = make_payer(&secret, &public_key); - let digest = cryptde::create_digest( + let digest = cryptde::make_agent_digest( &SubPublicKey::new(&b"wrong key"[..]), &TEST_DEFAULT_CHAIN.rec().contract, ); diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index bb0906895..529dce863 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -21,8 +21,11 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use crate::accountant::database_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, +}; use crate::blockchain::batch_payable_tools::BatchPayableTools; +use crate::{arbitrary_id_stamp_in_trait_impl, set_arbitrary_id_stamp_in_mock_impl}; use web3::transports::{Batch, EventLoopHandle, Http}; use web3::types::{Address, Bytes, SignedTransaction, TransactionParameters, U256}; use web3::{BatchTransport, Error as Web3Error, Web3}; @@ -82,6 +85,7 @@ pub struct BlockchainInterfaceMock { get_transaction_receipt_results: RefCell>, get_transaction_count_parameters: Arc>>, get_transaction_count_results: RefCell>>, + arbitrary_id_stamp_opt: Option, } impl BlockchainInterface for BlockchainInterfaceMock { @@ -110,13 +114,13 @@ impl BlockchainInterface for BlockchainInterfaceMock { fn send_batch_of_payables( &self, consuming_wallet: &Wallet, - payable_payments_agent: &dyn PayablePaymentsAgent, + agent_digest: Box, //TODO test by clone later on?? new_fingerprints_recipient: &Recipient, accounts: &[PayableAccount], ) -> Result, PayableTransactionError> { self.send_batch_of_payables_params.lock().unwrap().push(( consuming_wallet.clone(), - payable_payments_agent.arbitrary_id_stamp(), + agent_digest.arbitrary_id_stamp(), new_fingerprints_recipient.clone(), accounts.to_vec(), )); @@ -156,6 +160,9 @@ impl BlockchainInterface for BlockchainInterfaceMock { .push(hash); self.get_transaction_receipt_results.borrow_mut().remove(0) } + + #[cfg(test)] + arbitrary_id_stamp_in_trait_impl!(); } impl BlockchainInterfaceMock { @@ -258,6 +265,9 @@ impl BlockchainInterfaceMock { .push(result); self } + + #[cfg(test)] + set_arbitrary_id_stamp_in_mock_impl!(); } #[derive(Debug, Default, Clone)] diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 48f8ead25..ced8f0985 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -58,6 +58,15 @@ pub struct ConsumingWalletBalances { pub masq_token_balance_in_minor_units: U256, } +impl ConsumingWalletBalances { + pub fn new(transaction_fee: U256, masq_token: U256) -> Self { + Self { + transaction_fee_balance_in_minor_units: transaction_fee, + masq_token_balance_in_minor_units: masq_token, + } + } +} + #[cfg(test)] mod tests { use crate::actor_system_factory::SubsFactory; diff --git a/node/src/sub_lib/cryptde.rs b/node/src/sub_lib/cryptde.rs index 3e37449d0..d1ffb8a7c 100644 --- a/node/src/sub_lib/cryptde.rs +++ b/node/src/sub_lib/cryptde.rs @@ -621,7 +621,7 @@ where } } -pub fn create_digest(msg: &dyn AsRef<[u8]>, address: &dyn AsRef<[u8]>) -> [u8; 32] { +pub fn make_agent_digest(msg: &dyn AsRef<[u8]>, address: &dyn AsRef<[u8]>) -> [u8; 32] { [msg.as_ref(), address.as_ref()].concat().keccak256() } diff --git a/node/src/sub_lib/cryptde_null.rs b/node/src/sub_lib/cryptde_null.rs index 4b724ca77..315377d7c 100644 --- a/node/src/sub_lib/cryptde_null.rs +++ b/node/src/sub_lib/cryptde_null.rs @@ -171,7 +171,7 @@ impl CryptDENull { } let private_key = PrivateKey::from(&private_key[..]); let public_key = Self::public_from_private(&private_key); - let digest = cryptde::create_digest(&public_key, &chain.rec().contract); + let digest = cryptde::make_agent_digest(&public_key, &chain.rec().contract); Self { private_key, public_key, @@ -189,7 +189,7 @@ impl CryptDENull { pub fn set_key_pair(&mut self, public_key: &PublicKey, chain: Chain) { self.public_key = public_key.clone(); self.private_key = CryptDENull::private_from_public(public_key); - self.digest = cryptde::create_digest(public_key, &chain.rec().contract); + self.digest = cryptde::make_agent_digest(public_key, &chain.rec().contract); } pub fn private_from_public(in_key: &PublicKey) -> PrivateKey { diff --git a/node/src/sub_lib/cryptde_real.rs b/node/src/sub_lib/cryptde_real.rs index dd299a6bb..f2a54c591 100644 --- a/node/src/sub_lib/cryptde_real.rs +++ b/node/src/sub_lib/cryptde_real.rs @@ -194,7 +194,7 @@ impl CryptDEReal { let (e_public, e_secret) = encryption::gen_keypair(); let (s_public, s_secret) = signing::gen_keypair(); let public_key = Self::local_public_key_from(&e_public, &s_public); - let digest = cryptde::create_digest(&public_key, &chain.rec().contract); + let digest = cryptde::make_agent_digest(&public_key, &chain.rec().contract); let pre_shared_data = chain.rec().contract.0; Self { diff --git a/node/src/sub_lib/wallet.rs b/node/src/sub_lib/wallet.rs index 59898ee44..72e196560 100644 --- a/node/src/sub_lib/wallet.rs +++ b/node/src/sub_lib/wallet.rs @@ -177,7 +177,7 @@ impl Wallet { public_key: &dyn AsRef<[u8]>, contract_address: &dyn AsRef<[u8]>, ) -> Payer { - match self.sign(&cryptde::create_digest(public_key, contract_address)) { + match self.sign(&cryptde::make_agent_digest(public_key, contract_address)) { Ok(proof) => Payer::new(self, &proof), Err(e) => panic!( "Trying to sign for {:?} encountered {:?}", From 03a83de211e328cce5f6b7e022fdbb9ed833db80 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 14 Aug 2023 12:58:34 +0200 Subject: [PATCH 09/10] GH-672: finished last few missing places --- .../payable_scanner/agent_null.rs | 158 +++++++++++++++--- node/src/actor_system_factory.rs | 1 - node/src/blockchain/blockchain_interface.rs | 2 + node/src/test_utils/http_test_server.rs | 2 + 4 files changed, 143 insertions(+), 20 deletions(-) diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs index cae4fff8a..76b0b002d 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent_null.rs @@ -12,10 +12,34 @@ use masq_lib::logger::Logger; #[cfg(test)] use std::any::Any; +trait LoggingNullObject<'a> { + fn logger(&'a self) -> &'a Logger; + + fn name(&self) -> &'static str; + + fn log_function_call(&'a self, function_call: &str) { + error!( + self.logger(), + "calling null version of {function_call} for {} will be without effect", + self.name() + ); + } +} + pub struct PayablePaymentsAgentNull { logger: Logger, } +impl<'a> LoggingNullObject<'a> for PayablePaymentsAgentNull { + fn logger(&'a self) -> &'a Logger { + &self.logger + } + + fn name(&self) -> &'static str { + "PayablePaymentsAgentNull" + } +} + impl PayablePaymentsAgent for PayablePaymentsAgentNull { fn set_agreed_fee_per_computation_unit( &mut self, @@ -55,24 +79,37 @@ impl PayablePaymentsAgentNull { logger: Logger::new("PayablePaymentsAgentNull"), } } +} - fn log_function_call(&self, function_call: &str) { - error!( - self.logger, - "calling null version of {function_call} will be without effect" - ); +impl Default for PayablePaymentsAgentNull { + fn default() -> Self { + Self::new() } } -pub struct AgentDigestNull {} +pub struct AgentDigestNull { + logger: Logger, +} + +impl<'a> LoggingNullObject<'a> for AgentDigestNull { + fn logger(&'a self) -> &'a Logger { + &self.logger + } + + fn name(&self) -> &'static str { + "AgentDigestNull" + } +} impl AgentDigest for AgentDigestNull { fn agreed_fee_per_computation_unit(&self) -> u64 { - todo!() + self.log_function_call("agreed_fee_per_computation_unit()"); + 0 } fn pending_transaction_id(&self) -> U256 { - todo!() + self.log_function_call("pending_transaction_id()"); + U256::zero() } implement_as_any!(); @@ -80,13 +117,23 @@ impl AgentDigest for AgentDigestNull { impl AgentDigestNull { pub fn new() -> Self { - Self {} + Self { + logger: Logger::new("AgentDigestNull"), + } + } +} + +impl Default for AgentDigestNull { + fn default() -> Self { + Self::new() } } #[cfg(test)] mod tests { - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::PayablePaymentsAgent; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent::{ + AgentDigest, PayablePaymentsAgent, + }; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_null::{ AgentDigestNull, PayablePaymentsAgentNull, }; @@ -98,11 +145,13 @@ mod tests { use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use web3::types::U256; - #[test] - fn payable_payments_agent_null_constructor_works() { + fn payable_payments_agent_null_constructor_works(constructor: C) + where + C: Fn() -> PayablePaymentsAgentNull, + { init_test_logging(); - let result = PayablePaymentsAgentNull::new(); + let result = constructor(); warning!( result.logger, @@ -114,6 +163,16 @@ mod tests { ); } + #[test] + fn payable_payments_agent_null_constructor_works_for_new() { + payable_payments_agent_null_constructor_works(PayablePaymentsAgentNull::new) + } + + #[test] + fn payable_payments_agent_null_constructor_works_for_default() { + payable_payments_agent_null_constructor_works(PayablePaymentsAgentNull::default) + } + #[test] fn null_agent_set_agreed_fee_per_computation_unit() { init_test_logging(); @@ -127,7 +186,8 @@ mod tests { assert_eq!(result, Ok(())); TestLogHandler::default().exists_log_containing(&format!( "ERROR: {test_name}: calling null \ - version of set_agreed_fee_per_computation_unit() will be without effect" + version of set_agreed_fee_per_computation_unit() for PayablePaymentsAgentNull \ + will be without effect" )); } @@ -143,7 +203,8 @@ mod tests { TestLogHandler::default().exists_log_containing(&format!( "ERROR: {test_name}: calling \ - null version of set_consuming_wallet_balances() will be without effect" + null version of set_consuming_wallet_balances() for PayablePaymentsAgentNull will \ + be without effect" )); } @@ -159,7 +220,8 @@ mod tests { assert_eq!(result, 0); TestLogHandler::default().exists_log_containing(&format!( "ERROR: {test_name}: calling \ - null version of estimated_transaction_fee_total() will be without effect" + null version of estimated_transaction_fee_total() for PayablePaymentsAgentNull \ + will be without effect" )); } @@ -174,8 +236,8 @@ mod tests { assert_eq!(result, None); TestLogHandler::default().exists_log_containing(&format!( - "ERROR: {test_name}: calling \ - null version of consuming_wallet_balances() will be without effect" + "ERROR: {test_name}: calling null version of consuming_wallet_balances() \ + for PayablePaymentsAgentNull will be without effect" )); } @@ -195,7 +257,65 @@ mod tests { result.as_any().downcast_ref::().unwrap(); TestLogHandler::default().exists_log_containing(&format!( "ERROR: {test_name}: calling \ - null version of make_agent_digest() will be without effect" + null version of make_agent_digest() for PayablePaymentsAgentNull \ + will be without effect" + )); + } + + fn null_agent_digest_constructor_works(constructor: C) + where + C: Fn() -> AgentDigestNull, + { + init_test_logging(); + + let result = constructor(); + + warning!(result.logger, "null_agent_digest_constructor_works"); + TestLogHandler::default().exists_log_containing( + "WARN: AgentDigestNull: \ + null_agent_digest_constructor_works", + ); + } + + #[test] + fn null_agent_digest_constructor_works_for_new() { + null_agent_digest_constructor_works(AgentDigestNull::new) + } + + #[test] + fn null_agent_digest_constructor_works_for_default() { + null_agent_digest_constructor_works(AgentDigestNull::default) + } + + #[test] + fn null_agent_digest_agreed_fee_per_computation_unit() { + init_test_logging(); + let test_name = "null_agent_digest_agreed_fee_per_computation_unit"; + let mut subject = AgentDigestNull::new(); + subject.logger = Logger::new(test_name); + + let result = subject.agreed_fee_per_computation_unit(); + + assert_eq!(result, 0); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling null version of agreed_fee_per_computation_unit() \ + for AgentDigestNull will be without effect" + )); + } + + #[test] + fn null_agent_digest_pending_transaction_id() { + init_test_logging(); + let test_name = "null_agent_digest_pending_transaction_id"; + let mut subject = AgentDigestNull::new(); + subject.logger = Logger::new(test_name); + + let result = subject.pending_transaction_id(); + + assert_eq!(result, U256::zero()); + TestLogHandler::default().exists_log_containing(&format!( + "ERROR: {test_name}: calling null version of pending_transaction_id() \ + for AgentDigestNull will be without effect" )); } } diff --git a/node/src/actor_system_factory.rs b/node/src/actor_system_factory.rs index 5ae3aef38..0cc7c12ff 100644 --- a/node/src/actor_system_factory.rs +++ b/node/src/actor_system_factory.rs @@ -13,7 +13,6 @@ use super::ui_gateway::UiGateway; use crate::accountant::database_access_objects::banned_dao::{ BannedCacheLoader, BannedCacheLoaderReal, }; -use crate::arbitrary_id_stamp_in_trait; use crate::blockchain::blockchain_bridge::{BlockchainBridge, BlockchainBridgeSubsFactory}; use crate::bootstrapper::CryptDEPair; use crate::database::db_initializer::DbInitializationConfig; diff --git a/node/src/blockchain/blockchain_interface.rs b/node/src/blockchain/blockchain_interface.rs index d33862948..fb4056126 100644 --- a/node/src/blockchain/blockchain_interface.rs +++ b/node/src/blockchain/blockchain_interface.rs @@ -6,6 +6,7 @@ use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent:: }; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::PayablePaymentsAgentWeb3; use crate::accountant::{comma_joined_stringifiable, gwei_to_wei}; +#[cfg(test)] use crate::arbitrary_id_stamp_in_trait; use crate::blockchain::batch_payable_tools::{BatchPayableTools, BatchPayableToolsReal}; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; @@ -13,6 +14,7 @@ use crate::blockchain::blockchain_interface::BlockchainError::{ InvalidAddress, InvalidResponse, InvalidUrl, QueryFailed, }; use crate::sub_lib::wallet::Wallet; +#[cfg(test)] use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use actix::{Message, Recipient}; use futures::{future, Future}; diff --git a/node/src/test_utils/http_test_server.rs b/node/src/test_utils/http_test_server.rs index 97b2046c0..56e0daddf 100644 --- a/node/src/test_utils/http_test_server.rs +++ b/node/src/test_utils/http_test_server.rs @@ -1,5 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +#![cfg(test)] + use crossbeam_channel::{unbounded, Receiver}; use simple_server::{Request, Server}; use std::io::Write; From 6080ab18689bd3e3b50187d2727a0213501dead0 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 14 Aug 2023 13:35:33 +0200 Subject: [PATCH 10/10] GH-672: reworking comments and found a little mistake --- .../payable_scanner/agent.rs | 3 ++- node/src/stream_messages.rs | 13 ----------- node/src/test_utils/mod.rs | 22 +++++++++---------- node/src/test_utils/recorder.rs | 4 ++-- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs index eece3c0db..328c348ec 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/agent.rs @@ -46,7 +46,8 @@ pub trait PayablePaymentsAgent: Send { arbitrary_id_stamp_in_trait!(); } -// designed not to include unnecessary setter methods +// Preferably, keep the trait without setter methods. That's actually +// the idea that drove the creation of this object pub trait AgentDigest: Send { fn agreed_fee_per_computation_unit(&self) -> u64; fn pending_transaction_id(&self) -> U256; diff --git a/node/src/stream_messages.rs b/node/src/stream_messages.rs index 957dfa85d..66fb3a613 100644 --- a/node/src/stream_messages.rs +++ b/node/src/stream_messages.rs @@ -83,19 +83,6 @@ mod tests { }; use actix::{Actor, System}; - //TODO can we also implement this with the newly developed infrastructure around recorder and msgs not implementing PartialEq?? - impl PartialEq for AddStreamMsg { - fn eq(&self, _other: &Self) -> bool { - // We need to implement PartialEq so that AddStreamMsg can be received by the Recorder; - // but AddStreamMsg breaks the rules for an actor message by containing references to - // outside resources (namely, an I/O stream) and therefore cannot have a real implementation - // of PartialEq. So here we break the rules again to patch up the problems created by - // the first breach of the rules. Don't move this into the production tree; it only needs - // to be here for the Recorder, and the Recorder is only in the test tree. - intentionally_blank!() - } - } - #[test] fn pool_bind_message_is_debug() { let _system = System::new("test"); diff --git a/node/src/test_utils/mod.rs b/node/src/test_utils/mod.rs index a95b8ad03..9d6efb1a5 100644 --- a/node/src/test_utils/mod.rs +++ b/node/src/test_utils/mod.rs @@ -1046,17 +1046,17 @@ pub mod unshared_test_utils { fn arbitrary_id_stamp(&self) -> ArbitraryIdStamp { match self.arbitrary_id_stamp_opt { Some(id) => id, - // For some mock implementations of methods with args, the best they can do to - // preserve these args for assertions is to take the ArbitraryId of the argument. - // If such code is set once it will happen in all tests using this mock and calling - // the method. However also in cases where we aren't really interested in checking - // that id. If we did nothing the call of this method would blow up because - // the carrying field is likely to be implemented as optional with the value defaulted - // to None. - // As a prevention of confusion from a set, yet useless id stamp, we'll put a null - // type of the id stamp in that place, allowing for both to call this method not risking a direct - // punishment (if the id isn't set manually) but also set the assertion on fire - // if it doesn't match the expected id when we write a test where we do care + // In some implementations of mocks and their methods taking args, the best we can do to + // capture and examine these args for assertions is to grab the ArbitraryIdStamp of the argument. + // If such strategy is once deployed this id transfers will have to happen in all tests relying + // on this mock, while also calling the meant method. So even in cases where we certainly are not + // really interested in checking that id. + // If we ignored that the call of this method would blow up because the holding field has likely + // the characteristic of an optional one with the value defaulted to None. + // As a prevention of confusion that might stem from a requirement to set the id stamp, even though + // we are not planning to use it, we put a null type of the stamp in the place. As result, we don't + // risk a direct punishment (if the None value was a problem) but we will set the assertion on fire + // if it doesn't match the expected id in a test where we do care None => ArbitraryIdStamp::null(), } } diff --git a/node/src/test_utils/recorder.rs b/node/src/test_utils/recorder.rs index 7bd9b0879..ac016c082 100644 --- a/node/src/test_utils/recorder.rs +++ b/node/src/test_utils/recorder.rs @@ -115,7 +115,7 @@ macro_rules! recorder_message_handler_t_p { recorder_message_handler_t_m_p!(AddReturnRouteMessage); recorder_message_handler_t_m_p!(AddRouteMessage); -recorder_message_handler_t_m_p!(AddStreamMsg); +recorder_message_handler_t_p!(AddStreamMsg); recorder_message_handler_t_m_p!(BindMessage); recorder_message_handler_t_m_p!(ConnectionProgressMessage); recorder_message_handler_t_m_p!(CrashNotification); @@ -323,7 +323,7 @@ impl Recording { match item_box.downcast_ref::() { Some(item) => Ok(item), None => { - // checking for less common but possible other type of an actor message, without PartialEq implemented + // double-checking for an uncommon, yet possible other type of an actor message, which doesn't implement PartialEq let item_opt = item_box.downcast_ref::>(); match item_opt {