From 5045ac13407999c1c7b7ac2113ea6f028d57a80a Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 12 Jun 2025 11:21:53 +0200 Subject: [PATCH 01/17] GH-638: ploughed all over, but the main structure has been planted; now let's get rid of 50 c. errors --- .../src/blockchains/blockchain_records.rs | 15 ++ masq_lib/src/blockchains/chains.rs | 1 + node/src/accountant/mod.rs | 16 +- node/src/accountant/payment_adjuster.rs | 2 +- .../payable_scanner/agent_null.rs | 36 ++- .../payable_scanner/agent_web3.rs | 222 +++++++++++++++--- .../payable_scanner/blockchain_agent.rs | 10 +- .../payable_scanner/msgs.rs | 53 ++++- .../payable_scanner/test_utils.rs | 27 ++- node/src/accountant/scanners/mod.rs | 15 +- node/src/blockchain/blockchain_bridge.rs | 57 ++--- .../blockchain_interface_web3/mod.rs | 35 +-- .../blockchain_interface_web3/utils.rs | 123 +++++----- .../blockchain/blockchain_interface/mod.rs | 8 +- .../blockchain_interface_initializer.rs | 12 +- node/src/blockchain/test_utils.rs | 13 +- node/src/sub_lib/blockchain_bridge.rs | 26 +- 17 files changed, 464 insertions(+), 207 deletions(-) diff --git a/masq_lib/src/blockchains/blockchain_records.rs b/masq_lib/src/blockchains/blockchain_records.rs index 67a8870e2..b3795d3d3 100644 --- a/masq_lib/src/blockchains/blockchain_records.rs +++ b/masq_lib/src/blockchains/blockchain_records.rs @@ -17,6 +17,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::PolyMainnet, num_chain_id: 137, literal_identifier: POLYGON_MAINNET_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -24,6 +25,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthMainnet, num_chain_id: 1, literal_identifier: ETH_MAINNET_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -31,6 +33,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::BaseMainnet, num_chain_id: 8453, literal_identifier: BASE_MAINNET_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -38,6 +41,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::BaseSepolia, num_chain_id: 84532, literal_identifier: BASE_SEPOLIA_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, }, @@ -45,6 +49,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::PolyAmoy, num_chain_id: 80002, literal_identifier: POLYGON_AMOY_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, }, @@ -52,6 +57,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthRopsten, num_chain_id: 3, literal_identifier: ETH_ROPSTEN_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, }, @@ -59,6 +65,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::Dev, num_chain_id: 2, literal_identifier: DEV_CHAIN_FULL_IDENTIFIER, + gas_price_recommended_margin_percents: 30, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, }, @@ -69,6 +76,7 @@ pub struct BlockchainRecord { pub self_id: Chain, pub num_chain_id: u64, pub literal_identifier: &'static str, + pub gas_price_recommended_margin_percents: u8, pub contract: Address, pub contract_creation_block: u64, } @@ -194,6 +202,7 @@ mod tests { num_chain_id: 1, self_id: examined_chain, literal_identifier: "eth-mainnet", + gas_price_recommended_margin_percents: 30, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -210,6 +219,7 @@ mod tests { num_chain_id: 3, self_id: examined_chain, literal_identifier: "eth-ropsten", + gas_price_recommended_margin_percents: 30, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, } @@ -226,6 +236,7 @@ mod tests { num_chain_id: 137, self_id: examined_chain, literal_identifier: "polygon-mainnet", + gas_price_recommended_margin_percents: 30, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -242,6 +253,7 @@ mod tests { num_chain_id: 80002, self_id: examined_chain, literal_identifier: "polygon-amoy", + gas_price_recommended_margin_percents: 30, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, } @@ -258,6 +270,7 @@ mod tests { num_chain_id: 8453, self_id: examined_chain, literal_identifier: "base-mainnet", + gas_price_recommended_margin_percents: 30, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -274,6 +287,7 @@ mod tests { num_chain_id: 84532, self_id: examined_chain, literal_identifier: "base-sepolia", + gas_price_recommended_margin_percents: 30, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, } @@ -290,6 +304,7 @@ mod tests { num_chain_id: 2, self_id: examined_chain, literal_identifier: "dev", + gas_price_recommended_margin_percents: 30, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, } diff --git a/masq_lib/src/blockchains/chains.rs b/masq_lib/src/blockchains/chains.rs index b7733b842..2ac9db03f 100644 --- a/masq_lib/src/blockchains/chains.rs +++ b/masq_lib/src/blockchains/chains.rs @@ -141,6 +141,7 @@ mod tests { num_chain_id: 0, self_id: Chain::PolyMainnet, literal_identifier: "", + gas_price_recommended_margin_percents: 0, contract: Default::default(), contract_creation_block: 0, } diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 750c4c1a7..70da7270b 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1464,7 +1464,7 @@ mod tests { assert_eq!( blockchain_bridge_recording.get_record::(0), &QualifiedPayablesMessage { - protected_qualified_payables: protect_payables_in_test(vec![payable_account]), + qualified_payables: protect_payables_in_test(vec![payable_account]), consuming_wallet, response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1551,7 +1551,7 @@ mod tests { let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp); let accounts = vec![account_1, account_2]; let msg = BlockchainAgentWithContextMessage { - protected_qualified_payables: protect_payables_in_test(accounts.clone()), + qualified_payables: protect_payables_in_test(accounts.clone()), agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1566,7 +1566,7 @@ mod tests { let (blockchain_agent_with_context_msg_actual, logger_clone) = is_adjustment_required_params.remove(0); assert_eq!( - blockchain_agent_with_context_msg_actual.protected_qualified_payables, + blockchain_agent_with_context_msg_actual.qualified_payables, protect_payables_in_test(accounts.clone()) ); assert_eq!( @@ -1649,7 +1649,7 @@ mod tests { unadjusted_account_2.clone(), ]); let msg = BlockchainAgentWithContextMessage { - protected_qualified_payables: initial_unadjusted_accounts.clone(), + qualified_payables: initial_unadjusted_accounts.clone(), agent: Box::new(agent), response_skeleton_opt: Some(response_skeleton), }; @@ -1689,7 +1689,7 @@ mod tests { assert_eq!( actual_prepared_adjustment .original_setup_msg - .protected_qualified_payables, + .qualified_payables, initial_unadjusted_accounts ); assert_eq!( @@ -1960,7 +1960,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - protected_qualified_payables: protect_payables_in_test(qualified_payables), + qualified_payables: protect_payables_in_test(qualified_payables), consuming_wallet, response_skeleton_opt: None, } @@ -2351,7 +2351,7 @@ mod tests { .begin_scan_params(&begin_scan_params_arc) .begin_scan_result(Err(BeginScanError::NothingToProcess)) .begin_scan_result(Ok(QualifiedPayablesMessage { - protected_qualified_payables: protect_payables_in_test(vec![make_payable_account( + qualified_payables: protect_payables_in_test(vec![make_payable_account( 123, )]), consuming_wallet: consuming_wallet.clone(), @@ -2651,7 +2651,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - protected_qualified_payables: protect_payables_in_test(qualified_payables), + qualified_payables: protect_payables_in_test(qualified_payables), consuming_wallet, response_skeleton_opt: None, } diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index 88ee13e74..fb474832c 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -86,7 +86,7 @@ mod tests { payable.balance_wei = 100_000_000; let agent = BlockchainAgentMock::default(); let setup_msg = BlockchainAgentWithContextMessage { - protected_qualified_payables: protect_payables_in_test(vec![payable]), + qualified_payables: protect_payables_in_test(vec![payable]), agent: Box::new(agent), response_skeleton_opt: None, }; 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 e95673002..e820b1acf 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 @@ -1,13 +1,16 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::collections::HashMap; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use ethereum_types::U256; +use web3::types::Address; use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; #[derive(Clone)] pub struct BlockchainAgentNull { @@ -16,7 +19,7 @@ pub struct BlockchainAgentNull { } impl BlockchainAgent for BlockchainAgentNull { - fn estimated_transaction_fee_total(&self, _number_of_transactions: usize) -> u128 { + fn estimated_transaction_fee_total(&self) -> u128 { self.log_function_call("estimated_transaction_fee_total()"); 0 } @@ -29,10 +32,13 @@ impl BlockchainAgent for BlockchainAgentNull { } } - fn agreed_fee_per_computation_unit(&self) -> u128 { - self.log_function_call("agreed_fee_per_computation_unit()"); - 0 - } + // fn finalize_gas_price_per_payable(&self, qualified_payables: QualifiedPayablesRawPack) -> QualifiedPayablesRipePack { + // self.log_function_call("finalize_gas_price_per_payable()"); + // let payables = qualified_payables.payables.into_iter().map(|preconfiguration| { + // QualifiedPayableWithGasPrice{ payable: preconfiguration.payable, gas_price_minor: 0 } + // }).collect(); + // QualifiedPayablesRipePack{ payables } + // } fn consuming_wallet(&self) -> &Wallet { self.log_function_call("consuming_wallet()"); @@ -77,10 +83,11 @@ impl Default for BlockchainAgentNull { #[cfg(test)] mod tests { + use std::collections::HashMap; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_null::BlockchainAgentNull; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; - use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; + use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use masq_lib::logger::Logger; @@ -129,7 +136,7 @@ mod tests { let mut subject = BlockchainAgentNull::new(); subject.logger = Logger::new(test_name); - let result = subject.estimated_transaction_fee_total(4); + let result = subject.estimated_transaction_fee_total(); assert_eq!(result, 0); assert_error_log(test_name, "estimated_transaction_fee_total"); @@ -154,19 +161,6 @@ mod tests { assert_error_log(test_name, "consuming_wallet_balances") } - #[test] - fn null_agent_agreed_fee_per_computation_unit() { - init_test_logging(); - let test_name = "null_agent_agreed_fee_per_computation_unit"; - let mut subject = BlockchainAgentNull::new(); - subject.logger = Logger::new(test_name); - - let result = subject.agreed_fee_per_computation_unit(); - - assert_eq!(result, 0); - assert_error_log(test_name, "agreed_fee_per_computation_unit") - } - #[test] fn null_agent_consuming_wallet() { init_test_logging(); 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 725e14f00..6186be236 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,35 +1,33 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::collections::HashMap; +use web3::types::Address; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { - gas_price_wei: u128, - gas_limit_const_part: u128, - maximum_added_gas_margin: u128, + estimated_gas_price_wei: u128, + // gas_price_hashmap: HashMap, + // gas_limit_const_part: u128, + // maximum_added_gas_margin: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, } impl BlockchainAgent for BlockchainAgentWeb3 { - fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128 { - let gas_price = self.gas_price_wei; - let max_gas_limit = self.maximum_added_gas_margin + self.gas_limit_const_part; - number_of_transactions as u128 * gas_price * max_gas_limit + fn estimated_transaction_fee_total(&self) -> u128 { + todo!()// self.gas_price_hashmap.values().sum::() * (self.gas_limit_const_part + self.maximum_added_gas_margin) } fn consuming_wallet_balances(&self) -> ConsumingWalletBalances { self.consuming_wallet_balances } - fn agreed_fee_per_computation_unit(&self) -> u128 { - self.gas_price_wei - } - fn consuming_wallet(&self) -> &Wallet { &self.consuming_wallet } @@ -45,20 +43,34 @@ pub const WEB3_MAXIMAL_GAS_LIMIT_MARGIN: u128 = 3328; impl BlockchainAgentWeb3 { pub fn new( - gas_price_wei: u128, + latest_gas_price_wei: u128, + qualified_payables: QualifiedPayablesRawPack, gas_limit_const_part: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, - ) -> Self { - Self { - gas_price_wei, - gas_limit_const_part, - consuming_wallet, - maximum_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, - consuming_wallet_balances, - chain, - } + ) -> (Box, QualifiedPayablesRipePack) { + todo!() + // let increase_gas_price_by_margin = |gas_price_wei: u128| { (gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100}; + // let gas_price_hashmap: HashMap = match &inputs_for_gas_price_hashmap { + // InputsForGasPriceHashmap::NewPayableMode(addresses) => { + // let common_gas_price_wei = increase_gas_price_by_margin(latest_gas_price_wei); + // addresses.into_iter().map(|addr|(*addr, common_gas_price_wei)).collect() + // }, + // InputsForGasPriceHashmap::RetryPayableMode(addresses_and_previous_attempt_gas_prices) => { + // addresses_and_previous_attempt_gas_prices.into_iter().map(|(addr, gas_price_wei)| (*addr, increase_gas_price_by_margin(*gas_price_wei))).collect() + // } + // }; + // + // Self { + // latest_gas_price_wei, + // gas_price_hashmap, + // gas_limit_const_part, + // consuming_wallet, + // maximum_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + // consuming_wallet_balances, + // chain, + // } } } @@ -68,10 +80,11 @@ mod tests { BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; - use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; + use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances}; use crate::test_utils::make_wallet; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; - use web3::types::U256; + use web3::types::{U256}; + use crate::blockchain::test_utils::{increase_gas_price_by_marginal}; #[test] fn constants_are_correct() { @@ -80,7 +93,6 @@ mod tests { #[test] fn blockchain_agent_can_return_non_computed_input_values() { - let gas_price_gwei = 123; let gas_limit_const_part = 44_000; let consuming_wallet = make_wallet("abcde"); let consuming_wallet_balances = ConsumingWalletBalances { @@ -89,14 +101,14 @@ mod tests { }; let subject = BlockchainAgentWeb3::new( - gas_price_gwei, + 2222, + None, gas_limit_const_part, consuming_wallet.clone(), consuming_wallet_balances, TEST_DEFAULT_CHAIN, ); - assert_eq!(subject.agreed_fee_per_computation_unit(), gas_price_gwei); assert_eq!(subject.consuming_wallet(), &consuming_wallet); assert_eq!( subject.consuming_wallet_balances(), @@ -105,8 +117,125 @@ mod tests { assert_eq!(subject.get_chain(), TEST_DEFAULT_CHAIN); } + // #[test] + // fn returns_correct_gas_price_for_new_payable_scan() { + // let consuming_wallet = make_wallet("efg"); + // let consuming_wallet_balances = ConsumingWalletBalances { + // transaction_fee_balance_in_minor_units: Default::default(), + // masq_token_balance_in_minor_units: Default::default(), + // }; + // let gas_price_from_rpc = 555566667777; + // let chain = TEST_DEFAULT_CHAIN; + // let gas_price_hashmap_inputs = make_populated_new_payable_gas_price_hashmap_inputs(2); + // let addresses = if let InputsForGasPriceHashmap::NewPayableMode(inputs) = &gas_price_hashmap_inputs { + // inputs.clone() + // } else { + // panic!("Expected NewPayableMode, got {:?}", gas_price_hashmap_inputs) + // }; + // let agent = BlockchainAgentWeb3::new( + // gas_price_from_rpc, + // gas_price_hashmap_inputs, + // 77_777, + // consuming_wallet, + // consuming_wallet_balances, + // chain, + // ); + // + // let result = agent.gas_price_for_individual_txs(); + // + // let expected_result = QualifiedPayableGasPriceSetup{ gas_price_arranged_for_individual_txs_minor: addresses.into_iter().map(|addr|(addr, gas_price_from_rpc)).collect(), gas_price_from_last_rpc_minor: gas_price_from_rpc }; + // assert_eq!(result, expected_result); + // } + // + // #[test] + // fn provides_gas_price_for_retry_payable_scan_if_the_latest_value_is_also_the_highest() { + // let gas_price_from_rpc = 500_500_000; + // let wallet_1 = make_wallet("abc"); + // let wallet_2 = make_wallet("def"); + // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 500_500_001, wallet_2.address() => 333_000_000}); + // let chain = TEST_DEFAULT_CHAIN; + // let increase_gas_price_by_margin = |gas_price_wei: u128| { + // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 + // }; + // + // let result = compute_gas_price_for_test( + // chain, + // gas_price_from_rpc, + // previous_attempt_gas_price_values_wei, + // ); + // + // let expected_result = + // QualifiedPayablesRipePack{ payables: vec![] } + // hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_001), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); + // assert_eq!(result, expected_result); + // } + // + // #[test] + // fn provides_gas_price_for_retry_payable_scan_if_the_latest_value_equals_the_previous_attempt() { + // let gas_price_from_rpc = 500_500_000; + // let wallet_1 = make_wallet("abc"); + // let wallet_2 = make_wallet("def"); + // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 499_999_999, wallet_2.address() => 500_500_000}); + // let chain = TEST_DEFAULT_CHAIN; + // let increase_gas_price_by_margin = |gas_price_wei: u128| { + // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 + // }; + // + // let result = compute_gas_price_for_test( + // chain, + // gas_price_from_rpc, + // previous_attempt_gas_price_values_wei, + // ); + // + // let expected_result = hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_000), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); + // assert_eq!(result, expected_result); + // } + // + // #[test] + // fn provides_gas_price_for_retry_payable_scan_if_the_prev_attempt_value_is_under_the_latest() { + // let gas_price_from_rpc = 500_500_000; + // let wallet_1 = make_wallet("abc"); + // let wallet_2 = make_wallet("def"); + // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 500_499_999, wallet_2.address() => 333_000_000}); + // let chain = TEST_DEFAULT_CHAIN; + // let increase_gas_price_by_margin = |gas_price_wei: u128| { + // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 + // }; + // + // let result = compute_gas_price_for_test( + // chain, + // gas_price_from_rpc, + // previous_attempt_gas_price_values_wei, + // ); + // + // let expected_result = hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_000), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); + // assert_eq!(result, expected_result); + // } + // + // fn compute_gas_price_for_test( + // chain: Chain, + // gas_price_from_rpc: u128, + // gas_price_hashmap_inputs: InputsForGasPriceHashmap, + // ) -> QualifiedPayablesRipePack{ + // let consuming_wallet = make_wallet("efg"); + // let consuming_wallet_balances = ConsumingWalletBalances { + // transaction_fee_balance_in_minor_units: Default::default(), + // masq_token_balance_in_minor_units: Default::default(), + // }; + // let agent = BlockchainAgentWeb3::new( + // gas_price_from_rpc, + // gas_price_hashmap_inputs, + // 77_777, + // consuming_wallet, + // consuming_wallet_balances, + // chain, + // ); + // + // agent.finalize_gas_price_per_payable() + // } + #[test] - fn estimated_transaction_fee_works() { + fn estimated_transaction_fee_works_for_new_payable() { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -114,6 +243,7 @@ mod tests { }; let agent = BlockchainAgentWeb3::new( 444, + gas_price_hashmap_inputs, 77_777, consuming_wallet, consuming_wallet_balances, @@ -129,7 +259,41 @@ mod tests { ); assert_eq!( result, - (3 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) as u128 * 444 + (3 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) * 444 ); } + + #[test] + fn estimated_transaction_fee_works_for_retry_payable() { + let consuming_wallet = make_wallet("efg"); + let consuming_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: Default::default(), + masq_token_balance_in_minor_units: Default::default(), + }; + let payable_1 = make_wallet("abc"); + let payable_2 = make_wallet("def"); + let chain = TEST_DEFAULT_CHAIN; + let agent = BlockchainAgentWeb3::new( + 444, + gas_price_hashmap_inputs, + 77_777, + consuming_wallet, + consuming_wallet_balances, + chain, + ); + + let result = agent.estimated_transaction_fee_total(); + + assert_eq!(agent.gas_limit_const_part, 77_777); + assert_eq!( + agent.maximum_added_gas_margin, + WEB3_MAXIMAL_GAS_LIMIT_MARGIN + ); + let first_tx_limit = increase_gas_price_by_marginal(555, chain) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); + let second_tx_limit = increase_gas_price_by_marginal(333, chain) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); + assert_eq!( + result, + first_tx_limit + second_tx_limit + ) + } } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/blockchain_agent.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/blockchain_agent.rs index 2f2af4015..3e826e8e2 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/blockchain_agent.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/blockchain_agent.rs @@ -1,10 +1,12 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::collections::HashMap; +use web3::types::Address; use crate::arbitrary_id_stamp_in_trait; -use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; - +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; // Table of chains by // // a) adoption of the fee market (variations on "gas price") @@ -22,11 +24,9 @@ use masq_lib::blockchains::chains::Chain; //* defaulted limit pub trait BlockchainAgent: Send { - fn estimated_transaction_fee_total(&self, number_of_transactions: usize) -> u128; + fn estimated_transaction_fee_total(&self) -> u128; fn consuming_wallet_balances(&self) -> ConsumingWalletBalances; - fn agreed_fee_per_computation_unit(&self) -> u128; fn consuming_wallet(&self) -> &Wallet; - fn get_chain(&self) -> Chain; #[cfg(test)] diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs index 41a1b3940..b53835ac8 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs @@ -1,27 +1,66 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::collections::{HashMap, HashSet}; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; use crate::sub_lib::wallet::Wallet; use actix::Message; use masq_lib::type_obfuscation::Obfuscated; use std::fmt::Debug; +use crate::accountant::db_access_objects::payable_dao::PayableAccount; #[derive(Debug, Message, PartialEq, Eq, Clone)] pub struct QualifiedPayablesMessage { - pub protected_qualified_payables: Obfuscated, + pub qualified_payables: QualifiedPayablesRawPack, pub consuming_wallet: Wallet, + // // None = NewPayableScanner + // // Some = RetryPayableScanner + // pub previous_attempt_gas_price_values_minor_opt: Option>, pub response_skeleton_opt: Option, } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct QualifiedPayablesRawPack { + pub payables: Vec, +} + +impl From> for QualifiedPayablesRawPack { + fn from(qualified_payable: Vec) -> Self { + todo!() + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct QualifiedPayablesBeforeGasPricePick { + pub payable: PayableAccount, + pub previous_attempt_gas_price_minor_opt: Option +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct QualifiedPayablesRipePack { + pub payables: Vec, +} + +impl Into> for QualifiedPayablesRipePack { + fn into(self) -> Vec { + todo!() + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct QualifiedPayableWithGasPrice{ + pub payable: PayableAccount, + pub gas_price_minor: u128 +} + impl QualifiedPayablesMessage { pub(in crate::accountant) fn new( - protected_qualified_payables: Obfuscated, + qualified_payables: QualifiedPayablesRawPack, consuming_wallet: Wallet, response_skeleton_opt: Option, ) -> Self { Self { - protected_qualified_payables, + qualified_payables, consuming_wallet, response_skeleton_opt, } @@ -36,19 +75,19 @@ impl SkeletonOptHolder for QualifiedPayablesMessage { #[derive(Message)] pub struct BlockchainAgentWithContextMessage { - pub protected_qualified_payables: Obfuscated, + pub qualified_payables: QualifiedPayablesRipePack, pub agent: Box, pub response_skeleton_opt: Option, } impl BlockchainAgentWithContextMessage { pub fn new( - qualified_payables: Obfuscated, + qualified_payables: QualifiedPayablesRipePack, blockchain_agent: Box, response_skeleton_opt: Option, ) -> Self { Self { - protected_qualified_payables: qualified_payables, + qualified_payables, agent: blockchain_agent, response_skeleton_opt, } @@ -67,7 +106,7 @@ mod tests { let cloned_agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(original_agent_id); Self { - protected_qualified_payables: self.protected_qualified_payables.clone(), + qualified_payables: self.qualified_payables.clone(), agent: Box::new(cloned_agent), response_skeleton_opt: self.response_skeleton_opt, } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/test_utils.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/test_utils.rs index d3ab97284..a6cd6c70d 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/test_utils.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/test_utils.rs @@ -3,16 +3,18 @@ #![cfg(test)] use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; +use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use crate::{arbitrary_id_stamp_in_trait_impl, set_arbitrary_id_stamp_in_mock_impl}; use masq_lib::blockchains::chains::Chain; use std::cell::RefCell; +use std::collections::HashMap; +use web3::types::Address; pub struct BlockchainAgentMock { consuming_wallet_balances_results: RefCell>, - agreed_fee_per_computation_unit_results: RefCell>, + gas_price_results: RefCell>, consuming_wallet_result_opt: Option, arbitrary_id_stamp_opt: Option, get_chain_result_opt: Option, @@ -22,7 +24,7 @@ impl Default for BlockchainAgentMock { fn default() -> Self { BlockchainAgentMock { consuming_wallet_balances_results: RefCell::new(vec![]), - agreed_fee_per_computation_unit_results: RefCell::new(vec![]), + gas_price_results: RefCell::new(vec![]), consuming_wallet_result_opt: None, arbitrary_id_stamp_opt: None, get_chain_result_opt: None, @@ -31,7 +33,7 @@ impl Default for BlockchainAgentMock { } impl BlockchainAgent for BlockchainAgentMock { - fn estimated_transaction_fee_total(&self, _number_of_transactions: usize) -> u128 { + fn estimated_transaction_fee_total(&self) -> u128 { todo!("to be implemented by GH-711") } @@ -39,11 +41,14 @@ impl BlockchainAgent for BlockchainAgentMock { todo!("to be implemented by GH-711") } - fn agreed_fee_per_computation_unit(&self) -> u128 { - self.agreed_fee_per_computation_unit_results - .borrow_mut() - .remove(0) - } + // fn gas_price_for_individual_txs(&self) -> QualifiedPayableGasPriceSetup { + // todo!() + // // (&self) -> u128 { + // // self.gas_price_results + // // .borrow_mut() + // // .remove(0) + // // } + // } fn consuming_wallet(&self) -> &Wallet { self.consuming_wallet_result_opt.as_ref().unwrap() @@ -68,8 +73,8 @@ impl BlockchainAgentMock { self } - pub fn agreed_fee_per_computation_unit_result(self, result: u128) -> Self { - self.agreed_fee_per_computation_unit_results + pub fn gas_price_result(self, result: u128) -> Self { + self.gas_price_results .borrow_mut() .push(result); self diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index e8ce95812..fd6559566 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -51,7 +51,7 @@ use time::OffsetDateTime; use web3::types::H256; use masq_lib::type_obfuscation::Obfuscated; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::{PreparedAdjustment, MultistagePayableScanner, SolvencySensitivePaymentInstructor}; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, QualifiedPayablesRawPack}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionReceiptResult, TxStatus}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError; use crate::db_config::persistent_configuration::{PersistentConfiguration, PersistentConfigurationReal}; @@ -222,9 +222,9 @@ impl Scanner for PayableScanner { "Chose {} qualified debts to pay", qualified_payables.len() ); - let protected_payables = self.protect_payables(qualified_payables); + let qualified_payables = QualifiedPayablesRawPack::from(qualified_payables); let outgoing_msg = QualifiedPayablesMessage::new( - protected_payables, + qualified_payables, consuming_wallet, response_skeleton_opt, ); @@ -271,10 +271,9 @@ impl SolvencySensitivePaymentInstructor for PayableScanner { .search_for_indispensable_adjustment(&msg, logger) { Ok(None) => { - let protected = msg.protected_qualified_payables; - let unprotected = self.expose_payables(protected); + let payables = msg.qualified_payables; Ok(Either::Left(OutboundPaymentsInstructions::new( - unprotected, + payables, msg.agent, msg.response_skeleton_opt, ))) @@ -1253,9 +1252,7 @@ mod tests { assert_eq!( result, Ok(QualifiedPayablesMessage { - protected_qualified_payables: protect_payables_in_test( - qualified_payable_accounts.clone() - ), + qualified_payables: todo!(), consuming_wallet, response_skeleton_opt: None, }) diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 1a01087e1..0a878c849 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -1,8 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{ - BlockchainAgentWithContextMessage, QualifiedPayablesMessage, -}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, QualifiedPayablesRipePack}; use crate::accountant::{ ReceivedPayments, ResponseSkeleton, ScanError, SentPayables, SkeletonOptHolder, @@ -263,11 +261,11 @@ impl BlockchainBridge { let accountant_recipient = self.payable_payments_setup_subs_opt.clone(); Box::new( self.blockchain_interface - .build_blockchain_agent(incoming_message.consuming_wallet) + .introduce_blockchain_agent(incoming_message.consuming_wallet, incoming_message.qualified_payables) .map_err(|e| format!("Blockchain agent build error: {:?}", e)) - .and_then(move |agent| { + .and_then(move |(agent, qualified_payables_with_finalized_gas_price)| { let outgoing_message = BlockchainAgentWithContextMessage::new( - incoming_message.protected_qualified_payables, + qualified_payables_with_finalized_gas_price, agent, incoming_message.response_skeleton_opt, ); @@ -485,7 +483,7 @@ impl BlockchainBridge { fn process_payments( &self, agent: Box, - affordable_accounts: Vec, + affordable_accounts: QualifiedPayablesRipePack, ) -> Box, Error = PayableTransactionError>> { let new_fingerprints_recipient = self.new_fingerprints_recipient(); @@ -553,7 +551,7 @@ mod tests { use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::test_utils::BlockchainAgentMock; use crate::accountant::scanners::test_utils::protect_payables_in_test; use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint}; - use crate::blockchain::blockchain_interface::blockchain_interface_web3::BlockchainInterfaceWeb3; + use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError::TransactionID; use crate::blockchain::blockchain_interface::data_structures::errors::{ BlockchainAgentBuildError, PayableTransactionError, @@ -679,15 +677,16 @@ mod tests { } #[test] - fn qualified_payables_msg_is_handled_and_new_msg_with_an_added_blockchain_agent_returns_to_accountant( + fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant( ) { let system = System::new( - "qualified_payables_msg_is_handled_and_new_msg_with_an_added_blockchain_agent_returns_to_accountant", + " fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant( +", ); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .ok_response("0x230000000".to_string(), 1) // 9395240960 - .ok_response("0x23".to_string(), 1) + .ok_response("0xAAAA".to_string(), 1) .ok_response( "0x000000000000000000000000000000000000000000000000000000000000FFFF".to_string(), 0, @@ -696,6 +695,7 @@ mod tests { let (accountant, _, accountant_recording_arc) = make_recorder(); let accountant_recipient = accountant.start().recipient(); let blockchain_interface = make_blockchain_interface_web3(port); + let chain = blockchain_interface.get_chain(); let consuming_wallet = make_paying_wallet(b"somewallet"); let persistent_configuration = PersistentConfigurationMock::default(); let wallet_1 = make_wallet("booga"); @@ -726,8 +726,9 @@ mod tests { subject.payable_payments_setup_subs_opt = Some(accountant_recipient); let qualified_payables = protect_payables_in_test(qualified_payables.clone()); let qualified_payables_msg = QualifiedPayablesMessage { - protected_qualified_payables: qualified_payables.clone(), + qualified_payables: qualified_payables.clone(), consuming_wallet: consuming_wallet.clone(), + previous_attempt_gas_price_values_minor_opt: None, response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, context_id: 444, @@ -746,7 +747,7 @@ mod tests { let blockchain_agent_with_context_msg_actual: &BlockchainAgentWithContextMessage = accountant_received_payment.get_record(0); assert_eq!( - blockchain_agent_with_context_msg_actual.protected_qualified_payables, + blockchain_agent_with_context_msg_actual.qualified_payables, qualified_payables ); assert_eq!( @@ -755,19 +756,20 @@ mod tests { .consuming_wallet(), &consuming_wallet ); + let gas_price_for_individual_txs_wei = blockchain_agent_with_context_msg_actual + .agent + .gas_price_for_individual_txs(); assert_eq!( - blockchain_agent_with_context_msg_actual - .agent - .agreed_fee_per_computation_unit(), - 0x230000000 + gas_price_for_individual_txs_wei, + hashmap!(wallet_1.address() => 0, wallet_2.address() => 0) //TODO past right values ); assert_eq!( blockchain_agent_with_context_msg_actual .agent .consuming_wallet_balances(), ConsumingWalletBalances::new( - 35.into(), - 0x000000000000000000000000000000000000000000000000000000000000FFFF.into() + 0xAAAA.into(), + 0xFFFF.into() ) ); let gas_limit_const_part = @@ -776,7 +778,7 @@ mod tests { blockchain_agent_with_context_msg_actual .agent .estimated_transaction_fee_total(1), - (1 * 0x230000000 * (gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) + 0 //TODO past right values ); assert_eq!( blockchain_agent_with_context_msg_actual.response_skeleton_opt, @@ -789,9 +791,9 @@ mod tests { } #[test] - fn qualified_payables_msg_is_handled_but_fails_on_build_blockchain_agent() { + fn qualified_payables_msg_is_handled_but_fails_on_introduce_blockchain_agent() { let system = - System::new("qualified_payables_msg_is_handled_but_fails_on_build_blockchain_agent"); + System::new("qualified_payables_msg_is_handled_but_fails_on_introduce_blockchain_agent"); let port = find_free_port(); // build blockchain agent fails by not providing the third response. let _blockchain_client_server = MBCSBuilder::new(port) @@ -810,8 +812,9 @@ mod tests { subject.payable_payments_setup_subs_opt = Some(accountant_recipient); let qualified_payables = protect_payables_in_test(vec![]); let qualified_payables_msg = QualifiedPayablesMessage { - protected_qualified_payables: qualified_payables, + qualified_payables: qualified_payables, consuming_wallet: consuming_wallet.clone(), + previous_attempt_gas_price_values_minor_opt: None, response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, context_id: 444, @@ -882,7 +885,7 @@ mod tests { let agent_id_stamp = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default() .set_arbitrary_id_stamp(agent_id_stamp) - .agreed_fee_per_computation_unit_result(123) + .gas_price_result(123) .consuming_wallet_result(consuming_wallet) .get_chain_result(Chain::PolyMainnet); @@ -972,7 +975,7 @@ mod tests { let consuming_wallet = make_paying_wallet(b"consuming_wallet"); let agent = BlockchainAgentMock::default() .consuming_wallet_result(consuming_wallet) - .agreed_fee_per_computation_unit_result(123) + .gas_price_result(123) .get_chain_result(Chain::PolyMainnet); send_bind_message!(subject_subs, peer_actors); @@ -1045,7 +1048,7 @@ mod tests { let system = System::new(test_name); let agent = BlockchainAgentMock::default() .consuming_wallet_result(consuming_wallet) - .agreed_fee_per_computation_unit_result(1) + .gas_price_result(1) .get_chain_result(Chain::PolyMainnet); let msg = OutboundPaymentsInstructions::new(accounts, Box::new(agent), None); let persistent_config = PersistentConfigurationMock::new(); @@ -1103,7 +1106,7 @@ mod tests { let agent = BlockchainAgentMock::default() .get_chain_result(TEST_DEFAULT_CHAIN) .consuming_wallet_result(consuming_wallet) - .agreed_fee_per_computation_unit_result(123); + .gas_price_result(123); let msg = OutboundPaymentsInstructions::new(vec![], Box::new(agent), None); let persistent_config = configure_default_persistent_config(ZERO); let mut subject = BlockchainBridge::new( diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 92f8e9145..dbad74757 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -4,6 +4,7 @@ pub mod lower_level_interface_web3; mod utils; use std::cmp::PartialEq; +use std::collections::HashMap; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainError, PayableTransactionError}; use crate::blockchain::blockchain_interface::data_structures::{BlockchainTransaction, ProcessedPayableFallible}; @@ -22,10 +23,15 @@ use ethereum_types::U64; use web3::transports::{EventLoopHandle, Http}; use web3::types::{Address, Log, H256, U256, FilterBuilder, TransactionReceipt, BlockNumber}; use crate::accountant::db_access_objects::payable_dao::PayableAccount; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{LowBlockchainIntWeb3, TransactionReceiptResult, TxReceipt, TxStatus}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::utils::{create_blockchain_agent_web3, send_payables_within_batch, BlockchainAgentFutureResult}; +// TODO We probably should begin to attach these constants more tightly to the interface, so that we aren't baffled +// which constant belongs to which interface. I suggest to declare them inside the inherent impl block. They will then +// need to be preceded by the class name if you want to use them. That could be the distinction we desire, though. + const CONTRACT_ABI: &str = indoc!( r#"[{ "constant":true, @@ -156,10 +162,11 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { ) } - fn build_blockchain_agent( + fn introduce_blockchain_agent( &self, consuming_wallet: Wallet, - ) -> Box, Error = BlockchainAgentBuildError>> { + qualified_payables: QualifiedPayablesRawPack, + ) -> Box, QualifiedPayablesRipePack), Error = BlockchainAgentBuildError>> { let wallet_address = consuming_wallet.address(); let gas_limit_const_part = self.gas_limit_const_part; // TODO: Would it be better to wrap these 3 calls into a single batch call? @@ -194,6 +201,7 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { }; Ok(create_blockchain_agent_web3( gas_limit_const_part, + qualified_payables, blockchain_agent_future_result, consuming_wallet, chain, @@ -246,7 +254,7 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { logger: Logger, agent: Box, fingerprints_recipient: Recipient, - affordable_accounts: Vec, + affordable_accounts: QualifiedPayablesRipePack, ) -> Box, Error = PayableTransactionError>> { let consuming_wallet = agent.consuming_wallet().clone(); @@ -254,7 +262,6 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { let get_transaction_id = self .lower_interface() .get_transaction_id(consuming_wallet.address()); - let gas_price_wei = agent.agreed_fee_per_computation_unit(); let chain = agent.get_chain(); Box::new( @@ -266,7 +273,6 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { chain, &web3_batch, consuming_wallet, - gas_price_wei, pending_nonce, fingerprints_recipient, affordable_accounts, @@ -441,9 +447,7 @@ mod tests { BlockchainAgentBuildError, BlockchainError, BlockchainInterface, RetrievedBlockchainTransactions, }; - use crate::blockchain::test_utils::{ - all_chains, make_blockchain_interface_web3, ReceiptResponseBuilder, - }; + use crate::blockchain::test_utils::{all_chains, make_blockchain_interface_web3, ReceiptResponseBuilder}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use crate::test_utils::make_paying_wallet; @@ -831,7 +835,7 @@ mod tests { } #[test] - fn blockchain_interface_web3_can_build_blockchain_agent() { + fn blockchain_interface_web3_can_introduce_blockchain_agent() { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) // gas_price @@ -849,13 +853,13 @@ mod tests { let subject = make_blockchain_interface_web3(port); let result = subject - .build_blockchain_agent(wallet.clone()) + .introduce_blockchain_agent(wallet.clone(), gas_price_hashmap_inputs) .wait() .unwrap(); let expected_transaction_fee_balance = U256::from(65_520); let expected_masq_balance = U256::from(65_535); - let expected_gas_price_wei = 1_000_000_000; + let expected_gas_price_wei = (1_000_000_000 * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100; assert_eq!(result.consuming_wallet(), &wallet); assert_eq!( result.consuming_wallet_balances(), @@ -865,8 +869,8 @@ mod tests { } ); assert_eq!( - result.agreed_fee_per_computation_unit(), - expected_gas_price_wei + result.gas_price_for_individual_txs(), + hashmap!() ); let expected_fee_estimation = (3 * (BlockchainInterfaceWeb3::web3_gas_limit_const_part(chain) @@ -886,7 +890,7 @@ mod tests { { let wallet = make_wallet("bcd"); let subject = make_blockchain_interface_web3(port); - let result = subject.build_blockchain_agent(wallet.clone()).wait(); + let result = subject.introduce_blockchain_agent(wallet.clone(), gas_price_hashmap_inputs).wait(); let err = match result { Err(e) => e, _ => panic!("we expected Err() but got Ok()"), @@ -900,9 +904,10 @@ mod tests { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port).start(); let wallet = make_wallet("abc"); + let gas_price_hashmap_inputs = make_populated_new_payable_gas_price_hashmap_inputs(1); let subject = make_blockchain_interface_web3(port); - let err = subject.build_blockchain_agent(wallet).wait().err().unwrap(); + let err = subject.introduce_blockchain_agent(wallet, gas_price_hashmap_inputs).wait().err().unwrap(); let expected_err = BlockchainAgentBuildError::GasPrice(QueryFailed( "Transport error: Error(IncompleteMessage)".to_string(), diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index ee2e49786..b1c72415d 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -1,13 +1,12 @@ // Copyright (c) 2024, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::fmt::Display; use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::agent_web3::BlockchainAgentWeb3; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; -use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ - BlockchainInterfaceWeb3, HashAndAmount, TRANSFER_METHOD_ID, -}; +use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3, HashAndAmount, TRANSFER_METHOD_ID}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError; use crate::blockchain::blockchain_interface::data_structures::{ ProcessedPayableFallible, RpcPayableFailure, @@ -20,13 +19,13 @@ use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use secp256k1secrets::SecretKey; use serde_json::Value; -use std::iter::once; use std::time::SystemTime; use thousands::Separable; use web3::transports::{Batch, Http}; use web3::types::{Bytes, SignedTransaction, TransactionParameters, U256}; use web3::Error as Web3Error; use web3::Web3; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; #[derive(Debug)] pub struct BlockchainAgentFutureResult { @@ -85,35 +84,47 @@ pub fn merged_output_data( pub fn transmission_log( chain: Chain, - accounts: &[PayableAccount], - gas_price_in_wei: u128, + accounts: &QualifiedPayablesRipePack, ) -> String { - let chain_name = chain - .rec() - .literal_identifier - .chars() - .skip_while(|char| char != &'-') - .skip(1) - .collect::(); - let introduction = once(format!( - "\ - Paying to creditors...\n\ - Transactions in the batch:\n\ - \n\ - gas price: {} wei\n\ - chain: {}\n\ - \n\ - [wallet address] [payment in wei]\n", - gas_price_in_wei, chain_name - )); - let body = accounts.iter().map(|account| { - format!( - "{} {}\n", - account.wallet, - account.balance_wei.separate_with_commas() - ) - }); - introduction.chain(body).collect() + todo!() + // let chain_name = chain + // .rec() + // .literal_identifier + // .chars() + // .skip_while(|char| char != &'-') + // .skip(1) + // .collect::(); + // const PAYMENT_VALUE_MAX_LENGTH_INCLUDING_COMMAS: usize = 24; + // let introduction = once(format!( + // "\ + // Paying to creditors...\n\ + // Transactions in the batch:\n\ + // \n\ + // chain: {}\n\ + // \n\ + // {:wallet_address_length$} {: value, + // None => &"NA" + // }; + // format!( + // "{:wallet_address_length$} {: [u8; 68] { @@ -215,12 +226,12 @@ pub fn sign_and_append_multiple_payments( chain: Chain, web3_batch: &Web3>, consuming_wallet: Wallet, - gas_price_in_wei: u128, mut pending_nonce: U256, - accounts: &[PayableAccount], + accounts: &QualifiedPayablesRipePack, ) -> Vec { let mut hash_and_amount_list = vec![]; - accounts.iter().for_each(|payable| { + accounts.payables.iter().for_each(|payable_pack| { + let payable = &payable_pack.payable; debug!( logger, "Preparing payable future of {} wei to {} with nonce {}", @@ -235,7 +246,7 @@ pub fn sign_and_append_multiple_payments( payable, consuming_wallet.clone(), pending_nonce, - gas_price_in_wei, + payable_pack.gas_price_minor, ); pending_nonce = advance_used_nonce(pending_nonce); @@ -250,19 +261,17 @@ pub fn send_payables_within_batch( chain: Chain, web3_batch: &Web3>, consuming_wallet: Wallet, - gas_price_in_wei: u128, pending_nonce: U256, new_fingerprints_recipient: Recipient, - accounts: Vec, + accounts: QualifiedPayablesRipePack, ) -> Box, Error = PayableTransactionError> + 'static> { debug!( logger, - "Common attributes of payables to be transacted: sender wallet: {}, contract: {:?}, chain_id: {}, gas_price: {}", + "Common attributes of payables to be transacted: sender wallet: {}, contract: {:?}, chain_id: {}", consuming_wallet, chain.rec().contract, chain.rec().num_chain_id, - gas_price_in_wei ); let hashes_and_paid_amounts = sign_and_append_multiple_payments( @@ -270,7 +279,6 @@ pub fn send_payables_within_batch( chain, web3_batch, consuming_wallet, - gas_price_in_wei, pending_nonce, &accounts, ); @@ -290,7 +298,7 @@ pub fn send_payables_within_batch( info!( logger, "{}", - transmission_log(chain, &accounts, gas_price_in_wei) + transmission_log(chain, &accounts) ); Box::new( @@ -302,7 +310,7 @@ pub fn send_payables_within_batch( Ok(merged_output_data( batch_response, hashes_and_paid_amounts_ok, - accounts, + accounts.into(), )) }), ) @@ -310,21 +318,25 @@ pub fn send_payables_within_batch( pub fn create_blockchain_agent_web3( gas_limit_const_part: u128, + qualified_payables: QualifiedPayablesRawPack, blockchain_agent_future_result: BlockchainAgentFutureResult, wallet: Wallet, chain: Chain, -) -> Box { - Box::new(BlockchainAgentWeb3::new( +) -> (Box, QualifiedPayablesRipePack) { + let cons_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: blockchain_agent_future_result + .transaction_fee_balance, + masq_token_balance_in_minor_units: blockchain_agent_future_result.masq_token_balance, + }; + + BlockchainAgentWeb3::new( blockchain_agent_future_result.gas_price_wei.as_u128(), + qualified_payables, gas_limit_const_part, wallet, - ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: blockchain_agent_future_result - .transaction_fee_balance, - masq_token_balance_in_minor_units: blockchain_agent_future_result.masq_token_balance, - }, + cons_wallet_balances, chain, - )) + ) } #[cfg(test)] @@ -575,7 +587,7 @@ mod tests { fn execute_send_payables_test( test_name: &str, - accounts: Vec, + accounts: QualifiedPayablesRipePack, expected_result: Result, PayableTransactionError>, port: u16, ) { @@ -585,7 +597,6 @@ mod tests { REQUESTS_IN_PARALLEL, ) .unwrap(); - let gas_price = 1_000_000_000; let pending_nonce: U256 = 1.into(); let web3_batch = Web3::new(Batch::new(transport)); let (accountant, _, accountant_recording) = make_recorder(); @@ -601,7 +612,6 @@ mod tests { chain, &web3_batch, consuming_wallet.clone(), - gas_price, pending_nonce, new_fingerprints_recipient, accounts.clone(), @@ -619,16 +629,15 @@ mod tests { assert!(timestamp_after >= ppfs_message.batch_wide_timestamp); let tlh = TestLogHandler::new(); tlh.exists_log_containing( - &format!("DEBUG: {test_name}: Common attributes of payables to be transacted: sender wallet: {}, contract: {:?}, chain_id: {}, gas_price: {}", + &format!("DEBUG: {test_name}: Common attributes of payables to be transacted: sender wallet: {}, contract: {:?}, chain_id: {}", consuming_wallet, chain.rec().contract, chain.rec().num_chain_id, - gas_price ) ); tlh.exists_log_containing(&format!( "INFO: {test_name}: {}", - transmission_log(chain, &accounts, gas_price) + transmission_log(chain, &accounts) )); assert_eq!(result, expected_result); } diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index ef1e8d373..a5895182d 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -16,6 +16,7 @@ use masq_lib::blockchains::chains::Chain; use web3::types::Address; use masq_lib::logger::Logger; use crate::accountant::db_access_objects::payable_dao::PayableAccount; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TransactionReceiptResult; @@ -33,10 +34,11 @@ pub trait BlockchainInterface { recipient: Address, ) -> Box>; - fn build_blockchain_agent( + fn introduce_blockchain_agent( &self, consuming_wallet: Wallet, - ) -> Box, Error = BlockchainAgentBuildError>>; + qualified_payables: QualifiedPayablesRawPack, + ) -> Box, QualifiedPayablesRipePack), Error = BlockchainAgentBuildError>>; fn process_transaction_receipts( &self, @@ -48,7 +50,7 @@ pub trait BlockchainInterface { logger: Logger, agent: Box, fingerprints_recipient: Recipient, - affordable_accounts: Vec, + affordable_accounts: QualifiedPayablesRipePack, ) -> Box, Error = PayableTransactionError>>; as_any_ref_in_trait!(); diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index ee87519a0..318d7de95 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -50,9 +50,7 @@ mod tests { use std::net::Ipv4Addr; use web3::transports::Http; - use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ - BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL, - }; + use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL}; use crate::blockchain::blockchain_interface::BlockchainInterface; use crate::test_utils::make_wallet; use masq_lib::constants::DEFAULT_CHAIN; @@ -77,16 +75,18 @@ mod tests { let (event_loop_handle, transport) = Http::with_max_parallel(server_url, REQUESTS_IN_PARALLEL).unwrap(); let subject = BlockchainInterfaceWeb3::new(transport, event_loop_handle, chain); + let payable_wallet = make_wallet("payable"); let blockchain_agent = subject - .build_blockchain_agent(wallet.clone()) + .introduce_blockchain_agent(wallet.clone(), gas_price_inputs) .wait() .unwrap(); assert_eq!(blockchain_agent.consuming_wallet(), &wallet); + let expected_gas_price = (1_000_000_000_u128 * (100 + chain.rec().gas_price_recommended_margin_percents as u128))/ 100; assert_eq!( - blockchain_agent.agreed_fee_per_computation_unit(), - 1_000_000_000 + blockchain_agent.gas_price_for_individual_txs(), + hashmap!(payable_wallet.address() => expected_gas_price) ); } diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index 4124e283a..8c4b8bd34 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -2,9 +2,8 @@ #![cfg(test)] -use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ - BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL, -}; +use std::collections::HashMap; +use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL}; use bip39::{Language, Mnemonic, Seed}; use ethabi::Hash; use ethereum_types::{BigEndianHash, H160, H256, U64}; @@ -15,8 +14,10 @@ use serde::Serialize; use serde_derive::Deserialize; use std::fmt::Debug; use std::net::Ipv4Addr; +use itertools::Itertools; use web3::transports::{EventLoopHandle, Http}; -use web3::types::{Index, Log, SignedTransaction, TransactionReceipt, H2048, U256}; +use web3::types::{Address, Index, Log, SignedTransaction, TransactionReceipt, H2048, U256}; +use crate::test_utils::make_wallet; lazy_static! { static ref BIG_MEANINGLESS_PHRASE: Vec<&'static str> = vec![ @@ -217,3 +218,7 @@ pub fn transport_error_message() -> String { "Connection refused".to_string() } } + +pub fn increase_gas_price_by_marginal(gas_price: u128, chain: Chain) -> u128 { + (gas_price * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100 +} \ No newline at end of file diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 2ec840cc9..930b9e386 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,8 +1,9 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use std::collections::HashMap; use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockchain_agent::BlockchainAgent; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::QualifiedPayablesMessage; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesMessage, QualifiedPayablesRipePack}; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; @@ -12,7 +13,7 @@ use masq_lib::blockchains::chains::Chain; use masq_lib::ui_gateway::NodeFromUiMessage; use std::fmt; use std::fmt::{Debug, Formatter}; -use web3::types::U256; +use web3::types::{Address, U256}; #[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct BlockchainBridgeConfig { @@ -41,14 +42,14 @@ impl Debug for BlockchainBridgeSubs { #[derive(Message)] pub struct OutboundPaymentsInstructions { - pub affordable_accounts: Vec, + pub affordable_accounts: QualifiedPayablesRipePack, pub agent: Box, pub response_skeleton_opt: Option, } impl OutboundPaymentsInstructions { pub fn new( - affordable_accounts: Vec, + affordable_accounts: QualifiedPayablesRipePack, agent: Box, response_skeleton_opt: Option, ) -> Self { @@ -81,6 +82,23 @@ impl ConsumingWalletBalances { } } +#[derive(Debug, PartialEq)] +pub struct QualifiedPayableGasPriceSetup { + pub gas_price_arranged_for_individual_txs_minor: HashMap, + pub gas_price_from_last_rpc_minor: u128, +} + +impl QualifiedPayableGasPriceSetup { + pub fn new(gas_price_arranged_for_individual_txs_minor: HashMap, gas_price_from_last_rpc_minor: u128) -> Self { + todo!() + // Self { + // gas_price_arranged_for_individual_txs_minor, + // gas_price_from_last_rpc_minor, + // } + } +} + + #[cfg(test)] mod tests { use crate::actor_system_factory::SubsFactory; From bfb268daab799394a3be70a6e5a84d543d28818a Mon Sep 17 00:00:00 2001 From: Bert Date: Sat, 14 Jun 2025 21:48:47 +0200 Subject: [PATCH 02/17] GH-638: interim commit; nice progress though --- node/src/accountant/mod.rs | 27 +- node/src/accountant/payment_adjuster.rs | 9 +- .../payable_scanner/agent_web3.rs | 270 ++++++++---------- .../payable_scanner/msgs.rs | 20 ++ node/src/accountant/test_utils.rs | 13 +- node/src/blockchain/blockchain_bridge.rs | 16 +- .../blockchain_interface_web3/mod.rs | 78 +++-- .../blockchain_interface_web3/utils.rs | 28 +- .../blockchain/blockchain_interface/mod.rs | 2 +- .../blockchain_interface_initializer.rs | 31 +- 10 files changed, 250 insertions(+), 244 deletions(-) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index 70da7270b..d9c982554 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1051,13 +1051,7 @@ mod tests { use crate::accountant::test_utils::DaoWithDestination::{ ForAccountantBody, ForPayableScanner, ForPendingPayableScanner, ForReceivableScanner, }; - use crate::accountant::test_utils::{ - bc_from_earning_wallet, bc_from_wallets, make_payable_account, make_payables, - BannedDaoFactoryMock, ConfigDaoFactoryMock, MessageIdGeneratorMock, NullScanner, - PayableDaoFactoryMock, PayableDaoMock, PayableScannerBuilder, PaymentAdjusterMock, - PendingPayableDaoFactoryMock, PendingPayableDaoMock, ReceivableDaoFactoryMock, - ReceivableDaoMock, ScannerMock, - }; + use crate::accountant::test_utils::{bc_from_earning_wallet, bc_from_wallets, make_payable_account, make_payables, make_ripe_qualified_payables, BannedDaoFactoryMock, ConfigDaoFactoryMock, MessageIdGeneratorMock, NullScanner, PayableDaoFactoryMock, PayableDaoMock, PayableScannerBuilder, PaymentAdjusterMock, PendingPayableDaoFactoryMock, PendingPayableDaoMock, ReceivableDaoFactoryMock, ReceivableDaoMock, ScannerMock}; use crate::accountant::test_utils::{AccountantBuilder, BannedDaoMock}; use crate::accountant::Accountant; use crate::blockchain::blockchain_bridge::BlockchainBridge; @@ -1117,6 +1111,7 @@ mod tests { use std::sync::Mutex; use std::time::Duration; use std::vec; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; impl Handler> for Accountant { @@ -1464,7 +1459,7 @@ mod tests { assert_eq!( blockchain_bridge_recording.get_record::(0), &QualifiedPayablesMessage { - qualified_payables: protect_payables_in_test(vec![payable_account]), + qualified_payables: QualifiedPayablesRawPack::from(vec![payable_account]), consuming_wallet, response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1522,7 +1517,7 @@ mod tests { #[test] fn received_balances_and_qualified_payables_under_our_money_limit_thus_all_forwarded_to_blockchain_bridge( ) { - // the numbers for balances don't do real math, they need not to match either the condition for + // The numbers for balances don't do real math, they need not match either the condition for // the payment adjustment or the actual values that come from the payable size reducing algorithm; // all that is mocked in this test init_test_logging(); @@ -1549,9 +1544,9 @@ mod tests { let system = System::new("test"); let agent_id_stamp = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp); - let accounts = vec![account_1, account_2]; + let qualified_payables = make_ripe_qualified_payables(vec![(account_1,1_000_000_001), (account_2, 1_000_000_002)]); let msg = BlockchainAgentWithContextMessage { - qualified_payables: protect_payables_in_test(accounts.clone()), + qualified_payables: qualified_payables.clone(), agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1567,7 +1562,7 @@ mod tests { is_adjustment_required_params.remove(0); assert_eq!( blockchain_agent_with_context_msg_actual.qualified_payables, - protect_payables_in_test(accounts.clone()) + qualified_payables.clone() ); assert_eq!( blockchain_agent_with_context_msg_actual.response_skeleton_opt, @@ -1586,7 +1581,7 @@ mod tests { let blockchain_bridge_recording = blockchain_bridge_recording_arc.lock().unwrap(); let payments_instructions = blockchain_bridge_recording.get_record::(0); - assert_eq!(payments_instructions.affordable_accounts, accounts); + assert_eq!(payments_instructions.affordable_accounts, qualified_payables); assert_eq!( payments_instructions.response_skeleton_opt, Some(ResponseSkeleton { @@ -1600,8 +1595,8 @@ mod tests { ); assert_eq!(blockchain_bridge_recording.len(), 1); test_use_of_the_same_logger(&logger_clone, test_name) - // adjust_payments() did not need a prepared result which means it wasn't reached - // because otherwise this test would've panicked + // adjust_payments() did not need any prepared result, which means it couldn't have been + // reached because otherwise this test would've panicked } fn test_use_of_the_same_logger(logger_clone: &Logger, test_name: &str) { @@ -1615,7 +1610,7 @@ mod tests { #[test] fn received_qualified_payables_exceeding_our_masq_balance_are_adjusted_before_forwarded_to_blockchain_bridge( ) { - // the numbers for balances don't do real math, they need not to match either the condition for + // The numbers for balances don't do real math, they need not to match either the condition for // the payment adjustment or the actual values that come from the payable size reducing algorithm; // all that is mocked in this test init_test_logging(); diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index fb474832c..205195dbe 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -74,19 +74,18 @@ mod tests { use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::BlockchainAgentWithContextMessage; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::test_utils::BlockchainAgentMock; use crate::accountant::scanners::test_utils::protect_payables_in_test; - use crate::accountant::test_utils::make_payable_account; + use crate::accountant::test_utils::{make_payable_account, make_ripe_qualified_payables}; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; #[test] fn search_for_indispensable_adjustment_always_returns_none() { init_test_logging(); - let test_name = "is_adjustment_required_always_returns_none"; - let mut payable = make_payable_account(111); - payable.balance_wei = 100_000_000; + let test_name = "search_for_indispensable_adjustment_always_returns_none"; + let mut payable = make_payable_account(123); let agent = BlockchainAgentMock::default(); let setup_msg = BlockchainAgentWithContextMessage { - qualified_payables: protect_payables_in_test(vec![payable]), + qualified_payables: make_ripe_qualified_payables(vec![(payable, 111_111_111)]), agent: Box::new(agent), response_skeleton_opt: None, }; 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 6186be236..3854cd94f 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 @@ -43,8 +43,8 @@ pub const WEB3_MAXIMAL_GAS_LIMIT_MARGIN: u128 = 3328; impl BlockchainAgentWeb3 { pub fn new( - latest_gas_price_wei: u128, qualified_payables: QualifiedPayablesRawPack, + latest_gas_price_wei: u128, gas_limit_const_part: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, @@ -84,6 +84,8 @@ mod tests { use crate::test_utils::make_wallet; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use web3::types::{U256}; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; + use crate::accountant::test_utils::make_payable_account; use crate::blockchain::test_utils::{increase_gas_price_by_marginal}; #[test] @@ -92,17 +94,93 @@ mod tests { } #[test] - fn blockchain_agent_can_return_non_computed_input_values() { + fn returns_correct_ripe_qualified_payables_for_new_payable_scan() { + let consuming_wallet = make_wallet("efg"); + let consuming_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: Default::default(), + masq_token_balance_in_minor_units: Default::default(), + }; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + let gas_price_from_rpc = 555_666_777; + let chain = TEST_DEFAULT_CHAIN; + let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( + qualified_payables, + gas_price_from_rpc, + 77_777, + consuming_wallet, + consuming_wallet_balances, + chain, + ); + + let gas_price_with_margin = increase_gas_price_by_marginal(gas_price_from_rpc, chain); + let expected_result = QualifiedPayablesRipePack{ payables: + vec![QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin)]}; + assert_eq!(ripe_qualified_payables, expected_result); + } + + #[test] + fn returns_correct_ripe_qualified_payables_for_retry_payable_scan() { + let consuming_wallet = make_wallet("efg"); + let consuming_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: Default::default(), + masq_token_balance_in_minor_units: Default::default(), + }; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let account_3 = make_payable_account(56); + let account_4 = make_payable_account(78); + let account_5 = make_payable_account(90); + let qualified_payables = QualifiedPayablesRawPack{payables: + vec![ + QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), + QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), + QualifiedPayablesBeforeGasPricePick::new(account_3, Some(444_555_667)), + QualifiedPayablesBeforeGasPricePick::new(account_4, Some(111_111_111)), + QualifiedPayablesBeforeGasPricePick::new(account_5, Some(500_000_000)) + ]}; + let gas_price_from_rpc = 444_555_666; + let chain = TEST_DEFAULT_CHAIN; + let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( + qualified_payables, + gas_price_from_rpc, + 77_777, + consuming_wallet, + consuming_wallet_balances, + chain, + ); + + let expected_result = { + let gas_price_account_1 = increase_gas_price_by_marginal(444_555_666, chain); + let gas_price_account_2 = increase_gas_price_by_marginal(444_555_666, chain); + let gas_price_account_3 = increase_gas_price_by_marginal(444_555_667, chain); + let gas_price_account_4 = increase_gas_price_by_marginal(444_555_666, chain); + let gas_price_account_5 = increase_gas_price_by_marginal(500_000_000, chain); + QualifiedPayablesRipePack{ payables: + vec![ + QualifiedPayableWithGasPrice::new(account_1, gas_price_account_1), + QualifiedPayableWithGasPrice::new(account_2, gas_price_account_2), + QualifiedPayableWithGasPrice::new(account_3, gas_price_account_3), + QualifiedPayableWithGasPrice::new(account_4, gas_price_account_4), + QualifiedPayableWithGasPrice::new(account_5, gas_price_account_5) + ]} + }; + assert_eq!(ripe_qualified_payables, expected_result); + } + + #[test] + fn returns_correct_non_computed_values() { let gas_limit_const_part = 44_000; let consuming_wallet = make_wallet("abcde"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: U256::from(456_789), masq_token_balance_in_minor_units: U256::from(123_000_000), }; - - let subject = BlockchainAgentWeb3::new( - 2222, - None, + let qualified_payables = QualifiedPayablesRawPack::from(vec![make_payable_account(123)]); + let (subject, _) = BlockchainAgentWeb3::new( + qualified_payables, + 222_333_444, gas_limit_const_part, consuming_wallet.clone(), consuming_wallet_balances, @@ -116,124 +194,7 @@ mod tests { ); assert_eq!(subject.get_chain(), TEST_DEFAULT_CHAIN); } - - // #[test] - // fn returns_correct_gas_price_for_new_payable_scan() { - // let consuming_wallet = make_wallet("efg"); - // let consuming_wallet_balances = ConsumingWalletBalances { - // transaction_fee_balance_in_minor_units: Default::default(), - // masq_token_balance_in_minor_units: Default::default(), - // }; - // let gas_price_from_rpc = 555566667777; - // let chain = TEST_DEFAULT_CHAIN; - // let gas_price_hashmap_inputs = make_populated_new_payable_gas_price_hashmap_inputs(2); - // let addresses = if let InputsForGasPriceHashmap::NewPayableMode(inputs) = &gas_price_hashmap_inputs { - // inputs.clone() - // } else { - // panic!("Expected NewPayableMode, got {:?}", gas_price_hashmap_inputs) - // }; - // let agent = BlockchainAgentWeb3::new( - // gas_price_from_rpc, - // gas_price_hashmap_inputs, - // 77_777, - // consuming_wallet, - // consuming_wallet_balances, - // chain, - // ); - // - // let result = agent.gas_price_for_individual_txs(); - // - // let expected_result = QualifiedPayableGasPriceSetup{ gas_price_arranged_for_individual_txs_minor: addresses.into_iter().map(|addr|(addr, gas_price_from_rpc)).collect(), gas_price_from_last_rpc_minor: gas_price_from_rpc }; - // assert_eq!(result, expected_result); - // } - // - // #[test] - // fn provides_gas_price_for_retry_payable_scan_if_the_latest_value_is_also_the_highest() { - // let gas_price_from_rpc = 500_500_000; - // let wallet_1 = make_wallet("abc"); - // let wallet_2 = make_wallet("def"); - // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 500_500_001, wallet_2.address() => 333_000_000}); - // let chain = TEST_DEFAULT_CHAIN; - // let increase_gas_price_by_margin = |gas_price_wei: u128| { - // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 - // }; - // - // let result = compute_gas_price_for_test( - // chain, - // gas_price_from_rpc, - // previous_attempt_gas_price_values_wei, - // ); - // - // let expected_result = - // QualifiedPayablesRipePack{ payables: vec![] } - // hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_001), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); - // assert_eq!(result, expected_result); - // } - // - // #[test] - // fn provides_gas_price_for_retry_payable_scan_if_the_latest_value_equals_the_previous_attempt() { - // let gas_price_from_rpc = 500_500_000; - // let wallet_1 = make_wallet("abc"); - // let wallet_2 = make_wallet("def"); - // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 499_999_999, wallet_2.address() => 500_500_000}); - // let chain = TEST_DEFAULT_CHAIN; - // let increase_gas_price_by_margin = |gas_price_wei: u128| { - // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 - // }; - // - // let result = compute_gas_price_for_test( - // chain, - // gas_price_from_rpc, - // previous_attempt_gas_price_values_wei, - // ); - // - // let expected_result = hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_000), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); - // assert_eq!(result, expected_result); - // } - // - // #[test] - // fn provides_gas_price_for_retry_payable_scan_if_the_prev_attempt_value_is_under_the_latest() { - // let gas_price_from_rpc = 500_500_000; - // let wallet_1 = make_wallet("abc"); - // let wallet_2 = make_wallet("def"); - // let previous_attempt_gas_price_values_wei = InputsForGasPriceHashmap::RetryPayableMode(hashmap! {wallet_1.address() => 500_499_999, wallet_2.address() => 333_000_000}); - // let chain = TEST_DEFAULT_CHAIN; - // let increase_gas_price_by_margin = |gas_price_wei: u128| { - // gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128) / 100 - // }; - // - // let result = compute_gas_price_for_test( - // chain, - // gas_price_from_rpc, - // previous_attempt_gas_price_values_wei, - // ); - // - // let expected_result = hashmap!(wallet_1.address() => increase_gas_price_by_margin(500_500_000), wallet_2.address() => increase_gas_price_by_margin(500_500_000)); - // assert_eq!(result, expected_result); - // } - // - // fn compute_gas_price_for_test( - // chain: Chain, - // gas_price_from_rpc: u128, - // gas_price_hashmap_inputs: InputsForGasPriceHashmap, - // ) -> QualifiedPayablesRipePack{ - // let consuming_wallet = make_wallet("efg"); - // let consuming_wallet_balances = ConsumingWalletBalances { - // transaction_fee_balance_in_minor_units: Default::default(), - // masq_token_balance_in_minor_units: Default::default(), - // }; - // let agent = BlockchainAgentWeb3::new( - // gas_price_from_rpc, - // gas_price_hashmap_inputs, - // 77_777, - // consuming_wallet, - // consuming_wallet_balances, - // chain, - // ); - // - // agent.finalize_gas_price_per_payable() - // } - + #[test] fn estimated_transaction_fee_works_for_new_payable() { let consuming_wallet = make_wallet("efg"); @@ -241,25 +202,24 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; - let agent = BlockchainAgentWeb3::new( - 444, - gas_price_hashmap_inputs, + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let chain = TEST_DEFAULT_CHAIN; + let qualified_payables = QualifiedPayablesRawPack::from(vec![account_1, account_2]); + let (agent, _) = BlockchainAgentWeb3::new( + qualified_payables, + 444_555_666, 77_777, consuming_wallet, consuming_wallet_balances, - TEST_DEFAULT_CHAIN, + chain, ); - let result = agent.estimated_transaction_fee_total(3); - - assert_eq!(agent.gas_limit_const_part, 77_777); - assert_eq!( - agent.maximum_added_gas_margin, - WEB3_MAXIMAL_GAS_LIMIT_MARGIN - ); + let result = agent.estimated_transaction_fee_total(); + assert_eq!( result, - (3 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) * 444 + (2 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) * increase_gas_price_by_marginal(444_555_666, chain) ); } @@ -270,12 +230,23 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; - let payable_1 = make_wallet("abc"); - let payable_2 = make_wallet("def"); + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let account_3 = make_payable_account(56); + let account_4 = make_payable_account(78); + let account_5 = make_payable_account(90); + let qualified_payables = QualifiedPayablesRawPack{payables: + vec![ + QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), + QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), + QualifiedPayablesBeforeGasPricePick::new(account_3, Some(444_555_667)), + QualifiedPayablesBeforeGasPricePick::new(account_4, Some(111_111_111)), + QualifiedPayablesBeforeGasPricePick::new(account_5, Some(500_000_000)), + ]}; let chain = TEST_DEFAULT_CHAIN; - let agent = BlockchainAgentWeb3::new( - 444, - gas_price_hashmap_inputs, + let (agent, _) = BlockchainAgentWeb3::new( + qualified_payables, + 444_555_666, 77_777, consuming_wallet, consuming_wallet_balances, @@ -283,17 +254,16 @@ mod tests { ); let result = agent.estimated_transaction_fee_total(); - - assert_eq!(agent.gas_limit_const_part, 77_777); - assert_eq!( - agent.maximum_added_gas_margin, - WEB3_MAXIMAL_GAS_LIMIT_MARGIN - ); - let first_tx_limit = increase_gas_price_by_marginal(555, chain) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); - let second_tx_limit = increase_gas_price_by_marginal(333, chain) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); + assert_eq!( result, - first_tx_limit + second_tx_limit + ( + increase_gas_price_by_marginal(444_555_666, chain) + + increase_gas_price_by_marginal(444_555_666, chain) + + increase_gas_price_by_marginal(444_555_667, chain) + + increase_gas_price_by_marginal(444_555_666, chain) + + increase_gas_price_by_marginal(500_000_000, chain) + ) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs index b53835ac8..34a9da84e 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs @@ -36,6 +36,16 @@ pub struct QualifiedPayablesBeforeGasPricePick { pub previous_attempt_gas_price_minor_opt: Option } +impl QualifiedPayablesBeforeGasPricePick { + pub fn new(payable: PayableAccount, previous_attempt_gas_price_minor_opt: Option) -> Self { + todo!(); + Self { + payable, + previous_attempt_gas_price_minor_opt + } + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub struct QualifiedPayablesRipePack { pub payables: Vec, @@ -53,6 +63,16 @@ pub struct QualifiedPayableWithGasPrice{ pub gas_price_minor: u128 } +impl QualifiedPayableWithGasPrice { + pub fn new(payable: PayableAccount, gas_price_minor: u128) -> Self { + todo!(); + Self { + payable, + gas_price_minor + } + } +} + impl QualifiedPayablesMessage { pub(in crate::accountant) fn new( qualified_payables: QualifiedPayablesRawPack, diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index e7186d2cd..94dd2d49c 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -16,9 +16,7 @@ use crate::accountant::db_access_objects::utils::{ from_unix_timestamp, to_unix_timestamp, CustomQuery, }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{ - BlockchainAgentWithContextMessage, QualifiedPayablesMessage, -}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesMessage, QualifiedPayablesRipePack}; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::{ MultistagePayableScanner, PreparedAdjustment, SolvencySensitivePaymentInstructor, }; @@ -1715,3 +1713,12 @@ impl ScanSchedulers { } } } + +pub fn make_ripe_qualified_payables(inputs: Vec<(PayableAccount, u128)>) -> QualifiedPayablesRipePack { + QualifiedPayablesRipePack{ payables: inputs.into_iter().map(|(payable, gas_price_minor)|{ + QualifiedPayableWithGasPrice{ + payable, + gas_price_minor, + } + }).collect() } +} \ No newline at end of file diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 0a878c849..2f1144c87 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -261,7 +261,7 @@ impl BlockchainBridge { let accountant_recipient = self.payable_payments_setup_subs_opt.clone(); Box::new( self.blockchain_interface - .introduce_blockchain_agent(incoming_message.consuming_wallet, incoming_message.qualified_payables) + .introduce_blockchain_agent(incoming_message.qualified_payables, incoming_message.consuming_wallet) .map_err(|e| format!("Blockchain agent build error: {:?}", e)) .and_then(move |(agent, qualified_payables_with_finalized_gas_price)| { let outgoing_message = BlockchainAgentWithContextMessage::new( @@ -728,7 +728,6 @@ mod tests { let qualified_payables_msg = QualifiedPayablesMessage { qualified_payables: qualified_payables.clone(), consuming_wallet: consuming_wallet.clone(), - previous_attempt_gas_price_values_minor_opt: None, response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, context_id: 444, @@ -742,7 +741,6 @@ mod tests { System::current().stop(); system.run(); - let accountant_received_payment = accountant_recording_arc.lock().unwrap(); let blockchain_agent_with_context_msg_actual: &BlockchainAgentWithContextMessage = accountant_received_payment.get_record(0); @@ -756,13 +754,6 @@ mod tests { .consuming_wallet(), &consuming_wallet ); - let gas_price_for_individual_txs_wei = blockchain_agent_with_context_msg_actual - .agent - .gas_price_for_individual_txs(); - assert_eq!( - gas_price_for_individual_txs_wei, - hashmap!(wallet_1.address() => 0, wallet_2.address() => 0) //TODO past right values - ); assert_eq!( blockchain_agent_with_context_msg_actual .agent @@ -777,8 +768,8 @@ mod tests { assert_eq!( blockchain_agent_with_context_msg_actual .agent - .estimated_transaction_fee_total(1), - 0 //TODO past right values + .estimated_transaction_fee_total(), + todo!() ); assert_eq!( blockchain_agent_with_context_msg_actual.response_skeleton_opt, @@ -814,7 +805,6 @@ mod tests { let qualified_payables_msg = QualifiedPayablesMessage { qualified_payables: qualified_payables, consuming_wallet: consuming_wallet.clone(), - previous_attempt_gas_price_values_minor_opt: None, response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, context_id: 444, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index dbad74757..f057c92f9 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -164,8 +164,8 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { fn introduce_blockchain_agent( &self, - consuming_wallet: Wallet, qualified_payables: QualifiedPayablesRawPack, + consuming_wallet: Wallet, ) -> Box, QualifiedPayablesRipePack), Error = BlockchainAgentBuildError>> { let wallet_address = consuming_wallet.address(); let gas_limit_const_part = self.gas_limit_const_part; @@ -200,8 +200,8 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { masq_token_balance, }; Ok(create_blockchain_agent_web3( - gas_limit_const_part, qualified_payables, + gas_limit_const_part, blockchain_agent_future_result, consuming_wallet, chain, @@ -447,7 +447,7 @@ mod tests { BlockchainAgentBuildError, BlockchainError, BlockchainInterface, RetrievedBlockchainTransactions, }; - use crate::blockchain::test_utils::{all_chains, make_blockchain_interface_web3, ReceiptResponseBuilder}; + use crate::blockchain::test_utils::{all_chains, increase_gas_price_by_marginal, make_blockchain_interface_web3, ReceiptResponseBuilder}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use crate::test_utils::make_paying_wallet; @@ -463,6 +463,8 @@ mod tests { use std::str::FromStr; use web3::transports::Http; use web3::types::{H256, U256}; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick}; + use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; #[test] @@ -835,11 +837,40 @@ mod tests { } #[test] - fn blockchain_interface_web3_can_introduce_blockchain_agent() { + fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_new_payables_mode() { + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 + let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayableWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_2, 1_000_000_000)]}; + let expected_estimated_transaction_fee = todo!("fix me"); + + blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, expected_estimated_transaction_fee); + } + + #[test] + fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_retry_payables_mode() { + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let account_3 = make_payable_account(56); + let raw_qualified_payables = QualifiedPayablesRawPack{payables: + vec![ + QualifiedPayablesBeforeGasPricePick::new(account_1, Some(999_999_999)), + QualifiedPayablesBeforeGasPricePick::new(account_2, Some(1_000_000_000)), + QualifiedPayablesBeforeGasPricePick::new(account_3, Some(1_000_000_001)) + ]}; + let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 + let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayableWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_2, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_3, 1_000_000_001)]}; + let expected_estimated_transaction_fee = todo!("fix me"); + + blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, expected_estimated_transaction_fee); + } + + fn blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables: QualifiedPayablesRawPack, gas_price_wei_from_rpc_hex: &str, expected_ripe_qualified_payables: QualifiedPayablesRipePack, expected_estimated_transaction_fee: u128) { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) // gas_price - .ok_response("0x3B9ACA00".to_string(), 0) // 1000000000 + .ok_response(gas_price_wei_from_rpc_hex.to_string(), 0) // transaction_fee_balance .ok_response("0xFFF0".to_string(), 0) // 65520 // masq_balance @@ -852,14 +883,13 @@ mod tests { let wallet = make_wallet("abc"); let subject = make_blockchain_interface_web3(port); - let result = subject - .introduce_blockchain_agent(wallet.clone(), gas_price_hashmap_inputs) + let (result, ripe_qualified_payables) = subject + .introduce_blockchain_agent(raw_qualified_payables, wallet.clone()) .wait() .unwrap(); let expected_transaction_fee_balance = U256::from(65_520); let expected_masq_balance = U256::from(65_535); - let expected_gas_price_wei = (1_000_000_000 * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100; assert_eq!(result.consuming_wallet(), &wallet); assert_eq!( result.consuming_wallet_balances(), @@ -868,17 +898,11 @@ mod tests { masq_token_balance_in_minor_units: expected_masq_balance } ); + let expected_gas_price_wei = increase_gas_price_by_marginal(u128::from_str_radix(gas_price_wei_from_rpc_hex,16).unwrap(), chain); + assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); assert_eq!( - result.gas_price_for_individual_txs(), - hashmap!() - ); - let expected_fee_estimation = (3 - * (BlockchainInterfaceWeb3::web3_gas_limit_const_part(chain) - + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) - * expected_gas_price_wei) as u128; - assert_eq!( - result.estimated_transaction_fee_total(3), - expected_fee_estimation + result.estimated_transaction_fee_total(), + expected_estimated_transaction_fee ) } @@ -889,8 +913,13 @@ mod tests { F: FnOnce(&Wallet) -> BlockchainAgentBuildError, { let wallet = make_wallet("bcd"); + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let subject = make_blockchain_interface_web3(port); - let result = subject.introduce_blockchain_agent(wallet.clone(), gas_price_hashmap_inputs).wait(); + + let result = subject.introduce_blockchain_agent(raw_qualified_payables, wallet.clone()).wait(); + let err = match result { Err(e) => e, _ => panic!("we expected Err() but got Ok()"), @@ -903,16 +932,11 @@ mod tests { fn build_of_the_blockchain_agent_fails_on_fetching_gas_price() { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port).start(); - let wallet = make_wallet("abc"); - let gas_price_hashmap_inputs = make_populated_new_payable_gas_price_hashmap_inputs(1); - let subject = make_blockchain_interface_web3(port); - - let err = subject.introduce_blockchain_agent(wallet, gas_price_hashmap_inputs).wait().err().unwrap(); - - let expected_err = BlockchainAgentBuildError::GasPrice(QueryFailed( + let expected_err_factory = |_wallet:&Wallet| BlockchainAgentBuildError::GasPrice(QueryFailed( "Transport error: Error(IncompleteMessage)".to_string(), )); - assert_eq!(err, expected_err) + + build_of_the_blockchain_agent_fails_on_blockchain_interface_error(port, expected_err_factory); } #[test] diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index b1c72415d..c6099fbb5 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -317,21 +317,22 @@ pub fn send_payables_within_batch( } pub fn create_blockchain_agent_web3( - gas_limit_const_part: u128, qualified_payables: QualifiedPayablesRawPack, + gas_limit_const_part: u128, blockchain_agent_future_result: BlockchainAgentFutureResult, wallet: Wallet, chain: Chain, ) -> (Box, QualifiedPayablesRipePack) { - let cons_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: blockchain_agent_future_result - .transaction_fee_balance, - masq_token_balance_in_minor_units: blockchain_agent_future_result.masq_token_balance, - }; - + let transaction_fee_balance_in_minor_units = blockchain_agent_future_result + .transaction_fee_balance; + let masq_token_balance_in_minor_units = blockchain_agent_future_result.masq_token_balance; + let cons_wallet_balances = ConsumingWalletBalances::new( + transaction_fee_balance_in_minor_units, + masq_token_balance_in_minor_units + ); BlockchainAgentWeb3::new( - blockchain_agent_future_result.gas_price_wei.as_u128(), qualified_payables, + blockchain_agent_future_result.gas_price_wei.as_u128(), gas_limit_const_part, wallet, cons_wallet_balances, @@ -345,9 +346,7 @@ mod tests { use crate::accountant::db_access_objects::utils::from_unix_timestamp; 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::test_utils::{ - make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, - }; + use crate::accountant::test_utils::{make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, make_ripe_qualified_payables}; use crate::blockchain::bip32::Bip32EncryptionKeyProvider; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL, @@ -448,14 +447,13 @@ mod tests { let consuming_wallet = make_paying_wallet(b"paying_wallet"); let account_1 = make_payable_account(1); let account_2 = make_payable_account(2); - let accounts = vec![account_1, account_2]; + let accounts = make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]); let result = sign_and_append_multiple_payments( &logger, chain, &web3_batch, consuming_wallet, - gwei_to_wei(gas_price_in_gwei), pending_nonce.into(), &accounts, ); @@ -505,12 +503,12 @@ mod tests { amount_3, None, ); - let accounts_to_process = vec![account_1, account_2, account_3]; + let accounts_to_process = make_ripe_qualified_payables(vec![(account_1, 123_456_789), (account_2, 234_567_890), (account_3, 345_678_901)]); info!( logger, "{}", - transmission_log(TEST_DEFAULT_CHAIN, &accounts_to_process, gas_price) + transmission_log(TEST_DEFAULT_CHAIN, &accounts_to_process) ); let log_handler = TestLogHandler::new(); diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index a5895182d..3d802d13b 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -36,8 +36,8 @@ pub trait BlockchainInterface { fn introduce_blockchain_agent( &self, - consuming_wallet: Wallet, qualified_payables: QualifiedPayablesRawPack, + consuming_wallet: Wallet, ) -> Box, QualifiedPayablesRipePack), Error = BlockchainAgentBuildError>>; fn process_transaction_receipts( diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index 318d7de95..c2f65a5cc 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -45,17 +45,16 @@ impl BlockchainInterfaceInitializer { mod tests { use crate::blockchain::blockchain_interface_initializer::BlockchainInterfaceInitializer; use masq_lib::blockchains::chains::Chain; - use futures::Future; use std::net::Ipv4Addr; - use web3::transports::Http; - - use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL}; use crate::blockchain::blockchain_interface::BlockchainInterface; use crate::test_utils::make_wallet; use masq_lib::constants::DEFAULT_CHAIN; use masq_lib::test_utils::mock_blockchain_client_server::MBCSBuilder; use masq_lib::utils::find_free_port; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; + use crate::accountant::test_utils::make_payable_account; + use crate::blockchain::test_utils::increase_gas_price_by_marginal; #[test] fn initialize_web3_interface_works() { @@ -72,21 +71,25 @@ mod tests { let wallet = make_wallet("123"); let chain = Chain::PolyMainnet; let server_url = &format!("http://{}:{}", &Ipv4Addr::LOCALHOST, port); - let (event_loop_handle, transport) = - Http::with_max_parallel(server_url, REQUESTS_IN_PARALLEL).unwrap(); - let subject = BlockchainInterfaceWeb3::new(transport, event_loop_handle, chain); - let payable_wallet = make_wallet("payable"); - let blockchain_agent = subject - .introduce_blockchain_agent(wallet.clone(), gas_price_inputs) + let result = BlockchainInterfaceInitializer{}.initialize_interface(server_url, chain); + + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + let payable_wallet = make_wallet("payable"); + let (blockchain_agent, ripe_qualified_payables) = result + .introduce_blockchain_agent(raw_qualified_payables, payable_wallet) .wait() .unwrap(); - assert_eq!(blockchain_agent.consuming_wallet(), &wallet); - let expected_gas_price = (1_000_000_000_u128 * (100 + chain.rec().gas_price_recommended_margin_percents as u128))/ 100; + let gas_price_with_margin = increase_gas_price_by_marginal(1_000_000_000, chain); + let expected_ripe_qualified_payables = QualifiedPayablesRipePack{ payables: + vec![QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin)]}; + assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); assert_eq!( - blockchain_agent.gas_price_for_individual_txs(), - hashmap!(payable_wallet.address() => expected_gas_price) + blockchain_agent.estimated_transaction_fee_total(), + todo!() ); } From e789bc8cf4769d368c928fc6131de58bae4d0b81 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 15 Jun 2025 21:25:09 +0200 Subject: [PATCH 03/17] GH-638: lots done; but the computations will be hrder to test --- node/src/accountant/mod.rs | 26 ++-- .../payable_scanner/agent_null.rs | 4 +- .../payable_scanner/agent_web3.rs | 118 ++++++++++-------- .../payable_scanner/msgs.rs | 13 +- node/src/accountant/test_utils.rs | 4 +- node/src/blockchain/blockchain_bridge.rs | 57 +++++---- .../blockchain_interface_web3/mod.rs | 27 ++-- .../blockchain_interface_web3/utils.rs | 28 +++-- .../blockchain_interface_initializer.rs | 8 +- node/src/blockchain/test_utils.rs | 4 - 10 files changed, 152 insertions(+), 137 deletions(-) diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index d9c982554..43c00a148 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1639,9 +1639,9 @@ mod tests { let agent_id_stamp_first_phase = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_first_phase); - let initial_unadjusted_accounts = protect_payables_in_test(vec![ - unadjusted_account_1.clone(), - unadjusted_account_2.clone(), + let initial_unadjusted_accounts = make_ripe_qualified_payables(vec![ + (unadjusted_account_1.clone(),111_222_333), + (unadjusted_account_2.clone(),222_333_444), ]); let msg = BlockchainAgentWithContextMessage { qualified_payables: initial_unadjusted_accounts.clone(), @@ -1653,7 +1653,7 @@ mod tests { let agent_id_stamp_second_phase = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_second_phase); - let affordable_accounts = vec![adjusted_account_1.clone(), adjusted_account_2.clone()]; + let affordable_accounts = make_ripe_qualified_payables(vec![(adjusted_account_1.clone(), 111_222_333), (adjusted_account_2.clone(),222_333_444)]); let payments_instructions = OutboundPaymentsInstructions { affordable_accounts: affordable_accounts.clone(), agent: Box::new(agent), @@ -1696,7 +1696,7 @@ mod tests { ); assert!( before <= captured_now && captured_now <= after, - "captured timestamp should have been between {:?} and {:?} but was {:?}", + "captured should be between {:?} and {:?} but was {:?}", before, after, captured_now @@ -1955,7 +1955,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - qualified_payables: protect_payables_in_test(qualified_payables), + qualified_payables: QualifiedPayablesRawPack::from(qualified_payables), consuming_wallet, response_skeleton_opt: None, } @@ -2346,7 +2346,7 @@ mod tests { .begin_scan_params(&begin_scan_params_arc) .begin_scan_result(Err(BeginScanError::NothingToProcess)) .begin_scan_result(Ok(QualifiedPayablesMessage { - qualified_payables: protect_payables_in_test(vec![make_payable_account( + qualified_payables: QualifiedPayablesRawPack::from(vec![make_payable_account( 123, )]), consuming_wallet: consuming_wallet.clone(), @@ -2355,7 +2355,7 @@ mod tests { .stop_the_system_after_last_msg(); let mut config = bc_from_earning_wallet(make_wallet("hi")); config.scan_intervals_opt = Some(ScanIntervals { - payable_scan_interval: Duration::from_millis(97), + payable_scan_interval: Duration::from_millis(25), receivable_scan_interval: Duration::from_secs(100), // We'll never run this scanner pending_payable_scan_interval: Duration::from_secs(100), // We'll never run this scanner }); @@ -2423,13 +2423,13 @@ mod tests { ScanForPayables { response_skeleton_opt: None }, - Duration::from_millis(97) + Duration::from_millis(25) ), ( ScanForPayables { response_skeleton_opt: None }, - Duration::from_millis(97) + Duration::from_millis(25) ), ] ) @@ -2590,7 +2590,7 @@ mod tests { }); let now = to_unix_timestamp(SystemTime::now()); let qualified_payables = vec![ - // slightly above minimum balance, to the right of the curve (time intersection) + // Slightly above the minimum balance, to the right of the curve (time intersection) PayableAccount { wallet: make_wallet("wallet0"), balance_wei: gwei_to_wei( @@ -2605,7 +2605,7 @@ mod tests { ), pending_payable_opt: None, }, - // slightly above the curve (balance intersection), to the right of minimum time + // Slightly above the curve (balance intersection), to the right of minimum time PayableAccount { wallet: make_wallet("wallet1"), balance_wei: gwei_to_wei(DEFAULT_PAYMENT_THRESHOLDS.debt_threshold_gwei + 1), @@ -2646,7 +2646,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - qualified_payables: protect_payables_in_test(qualified_payables), + qualified_payables: QualifiedPayablesRawPack::from(qualified_payables), consuming_wallet, response_skeleton_opt: None, } 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 e820b1acf..dc47a9360 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 @@ -10,7 +10,7 @@ use web3::types::Address; use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; #[derive(Clone)] pub struct BlockchainAgentNull { @@ -35,7 +35,7 @@ impl BlockchainAgent for BlockchainAgentNull { // fn finalize_gas_price_per_payable(&self, qualified_payables: QualifiedPayablesRawPack) -> QualifiedPayablesRipePack { // self.log_function_call("finalize_gas_price_per_payable()"); // let payables = qualified_payables.payables.into_iter().map(|preconfiguration| { - // QualifiedPayableWithGasPrice{ payable: preconfiguration.payable, gas_price_minor: 0 } + // QualifiedPayablesWithGasPrice{ payable: preconfiguration.payable, gas_price_minor: 0 } // }).collect(); // QualifiedPayablesRipePack{ payables } // } 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 3854cd94f..be4507d10 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 @@ -6,7 +6,8 @@ use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::blockch use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice}; +use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { @@ -43,34 +44,42 @@ pub const WEB3_MAXIMAL_GAS_LIMIT_MARGIN: u128 = 3328; impl BlockchainAgentWeb3 { pub fn new( - qualified_payables: QualifiedPayablesRawPack, + raw_qualified_payables: QualifiedPayablesRawPack, latest_gas_price_wei: u128, gas_limit_const_part: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, ) -> (Box, QualifiedPayablesRipePack) { - todo!() - // let increase_gas_price_by_margin = |gas_price_wei: u128| { (gas_price_wei * (100_u128 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100}; - // let gas_price_hashmap: HashMap = match &inputs_for_gas_price_hashmap { - // InputsForGasPriceHashmap::NewPayableMode(addresses) => { - // let common_gas_price_wei = increase_gas_price_by_margin(latest_gas_price_wei); - // addresses.into_iter().map(|addr|(*addr, common_gas_price_wei)).collect() - // }, - // InputsForGasPriceHashmap::RetryPayableMode(addresses_and_previous_attempt_gas_prices) => { - // addresses_and_previous_attempt_gas_prices.into_iter().map(|(addr, gas_price_wei)| (*addr, increase_gas_price_by_margin(*gas_price_wei))).collect() - // } - // }; - // - // Self { - // latest_gas_price_wei, - // gas_price_hashmap, - // gas_limit_const_part, - // consuming_wallet, - // maximum_added_gas_margin: WEB3_MAXIMAL_GAS_LIMIT_MARGIN, - // consuming_wallet_balances, - // chain, - // } + let current_gas_price_with_margin = increase_gas_price_by_margin(latest_gas_price_wei, chain); + + let (ripe_qualified_payables, gas_price_aggregated_wei) = raw_qualified_payables.payables.into_iter().fold( + ( + QualifiedPayablesRipePack{payables: vec![]}, + 0, + ), + |(mut ripe_qualified_payables, mut gas_price_aggregated_wei), raw_q_payable| { + let picked_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { + None => current_gas_price_with_margin, + Some(previous_price) if current_gas_price_with_margin < previous_price => previous_price, + Some(_) => current_gas_price_with_margin + }; + let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, picked_gas_price_wei); + ripe_qualified_payables.payables.push(ripe_qualified_payable); + gas_price_aggregated_wei += picked_gas_price_wei; + (ripe_qualified_payables, gas_price_aggregated_wei) + }); + + let estimated_gas_price_wei = gas_price_aggregated_wei * (gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); + + let agent = Self { + estimated_gas_price_wei, + consuming_wallet, + consuming_wallet_balances, + chain, + }; + + (Box::new(agent), ripe_qualified_payables) } } @@ -84,9 +93,9 @@ mod tests { use crate::test_utils::make_wallet; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use web3::types::{U256}; - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::accountant::test_utils::make_payable_account; - use crate::blockchain::test_utils::{increase_gas_price_by_marginal}; + use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; #[test] fn constants_are_correct() { @@ -113,10 +122,10 @@ mod tests { consuming_wallet_balances, chain, ); - - let gas_price_with_margin = increase_gas_price_by_marginal(gas_price_from_rpc, chain); + + let gas_price_with_margin = increase_gas_price_by_margin(gas_price_from_rpc, chain); let expected_result = QualifiedPayablesRipePack{ payables: - vec![QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin)]}; + vec![QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin)]}; assert_eq!(ripe_qualified_payables, expected_result); } @@ -134,14 +143,15 @@ mod tests { let account_5 = make_payable_account(90); let qualified_payables = QualifiedPayablesRawPack{payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), - QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), - QualifiedPayablesBeforeGasPricePick::new(account_3, Some(444_555_667)), - QualifiedPayablesBeforeGasPricePick::new(account_4, Some(111_111_111)), - QualifiedPayablesBeforeGasPricePick::new(account_5, Some(500_000_000)) + QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(444_555_665)), + QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(444_555_666)), + QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(444_555_667)), + QualifiedPayablesBeforeGasPricePick::new(account_4.clone(), Some(111_111_111)), + QualifiedPayablesBeforeGasPricePick::new(account_5.clone(), Some(500_000_000)) ]}; let gas_price_from_rpc = 444_555_666; let chain = TEST_DEFAULT_CHAIN; + let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( qualified_payables, gas_price_from_rpc, @@ -150,20 +160,20 @@ mod tests { consuming_wallet_balances, chain, ); - + let expected_result = { - let gas_price_account_1 = increase_gas_price_by_marginal(444_555_666, chain); - let gas_price_account_2 = increase_gas_price_by_marginal(444_555_666, chain); - let gas_price_account_3 = increase_gas_price_by_marginal(444_555_667, chain); - let gas_price_account_4 = increase_gas_price_by_marginal(444_555_666, chain); - let gas_price_account_5 = increase_gas_price_by_marginal(500_000_000, chain); + let gas_price_account_1 = increase_gas_price_by_margin(444_555_666, chain); + let gas_price_account_2 = increase_gas_price_by_margin(444_555_666, chain); + let gas_price_account_3 = increase_gas_price_by_margin(444_555_667, chain); + let gas_price_account_4 = increase_gas_price_by_margin(444_555_666, chain); + let gas_price_account_5 = increase_gas_price_by_margin(500_000_000, chain); QualifiedPayablesRipePack{ payables: vec![ - QualifiedPayableWithGasPrice::new(account_1, gas_price_account_1), - QualifiedPayableWithGasPrice::new(account_2, gas_price_account_2), - QualifiedPayableWithGasPrice::new(account_3, gas_price_account_3), - QualifiedPayableWithGasPrice::new(account_4, gas_price_account_4), - QualifiedPayableWithGasPrice::new(account_5, gas_price_account_5) + QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), + QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), + QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), + QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_4), + QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_5) ]} }; assert_eq!(ripe_qualified_payables, expected_result); @@ -194,7 +204,7 @@ mod tests { ); assert_eq!(subject.get_chain(), TEST_DEFAULT_CHAIN); } - + #[test] fn estimated_transaction_fee_works_for_new_payable() { let consuming_wallet = make_wallet("efg"); @@ -216,10 +226,10 @@ mod tests { ); let result = agent.estimated_transaction_fee_total(); - + assert_eq!( result, - (2 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) * increase_gas_price_by_marginal(444_555_666, chain) + (2 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) * increase_gas_price_by_margin(444_555_666, chain) ); } @@ -235,7 +245,7 @@ mod tests { let account_3 = make_payable_account(56); let account_4 = make_payable_account(78); let account_5 = make_payable_account(90); - let qualified_payables = QualifiedPayablesRawPack{payables: + let qualified_payables = QualifiedPayablesRawPack{payables: vec![ QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), @@ -254,15 +264,15 @@ mod tests { ); let result = agent.estimated_transaction_fee_total(); - + assert_eq!( result, ( - increase_gas_price_by_marginal(444_555_666, chain) + - increase_gas_price_by_marginal(444_555_666, chain) + - increase_gas_price_by_marginal(444_555_667, chain) + - increase_gas_price_by_marginal(444_555_666, chain) + - increase_gas_price_by_marginal(500_000_000, chain) + increase_gas_price_by_margin(444_555_666, chain) + + increase_gas_price_by_margin(444_555_666, chain) + + increase_gas_price_by_margin(444_555_667, chain) + + increase_gas_price_by_margin(444_555_666, chain) + + increase_gas_price_by_margin(500_000_000, chain) ) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } diff --git a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs index 34a9da84e..fa24f75ad 100644 --- a/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs +++ b/node/src/accountant/scanners/mid_scan_msg_handling/payable_scanner/msgs.rs @@ -13,9 +13,6 @@ use crate::accountant::db_access_objects::payable_dao::PayableAccount; pub struct QualifiedPayablesMessage { pub qualified_payables: QualifiedPayablesRawPack, pub consuming_wallet: Wallet, - // // None = NewPayableScanner - // // Some = RetryPayableScanner - // pub previous_attempt_gas_price_values_minor_opt: Option>, pub response_skeleton_opt: Option, } @@ -26,7 +23,7 @@ pub struct QualifiedPayablesRawPack { impl From> for QualifiedPayablesRawPack { fn from(qualified_payable: Vec) -> Self { - todo!() + QualifiedPayablesRawPack{ payables: qualified_payable.into_iter().map(|payable| QualifiedPayablesBeforeGasPricePick::new(payable, None)).collect()} } } @@ -38,7 +35,6 @@ pub struct QualifiedPayablesBeforeGasPricePick { impl QualifiedPayablesBeforeGasPricePick { pub fn new(payable: PayableAccount, previous_attempt_gas_price_minor_opt: Option) -> Self { - todo!(); Self { payable, previous_attempt_gas_price_minor_opt @@ -48,7 +44,7 @@ impl QualifiedPayablesBeforeGasPricePick { #[derive(Debug, PartialEq, Eq, Clone)] pub struct QualifiedPayablesRipePack { - pub payables: Vec, + pub payables: Vec, } impl Into> for QualifiedPayablesRipePack { @@ -58,14 +54,13 @@ impl Into> for QualifiedPayablesRipePack { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayableWithGasPrice{ +pub struct QualifiedPayablesWithGasPrice{ pub payable: PayableAccount, pub gas_price_minor: u128 } -impl QualifiedPayableWithGasPrice { +impl QualifiedPayablesWithGasPrice { pub fn new(payable: PayableAccount, gas_price_minor: u128) -> Self { - todo!(); Self { payable, gas_price_minor diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 94dd2d49c..93071b767 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -16,7 +16,7 @@ use crate::accountant::db_access_objects::utils::{ from_unix_timestamp, to_unix_timestamp, CustomQuery, }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; -use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesMessage, QualifiedPayablesRipePack}; +use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesMessage, QualifiedPayablesRipePack}; use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::{ MultistagePayableScanner, PreparedAdjustment, SolvencySensitivePaymentInstructor, }; @@ -1716,7 +1716,7 @@ impl ScanSchedulers { pub fn make_ripe_qualified_payables(inputs: Vec<(PayableAccount, u128)>) -> QualifiedPayablesRipePack { QualifiedPayablesRipePack{ payables: inputs.into_iter().map(|(payable, gas_price_minor)|{ - QualifiedPayableWithGasPrice{ + QualifiedPayablesWithGasPrice{ payable, gas_price_minor, } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 2f1144c87..1c5f535d8 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -533,6 +533,10 @@ struct PendingTxInfo { when_sent: SystemTime, } +pub fn increase_gas_price_by_margin(gas_price: u128, chain: Chain) -> u128 { + (gas_price * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100 +} + pub struct BlockchainBridgeSubsFactoryReal {} impl SubsFactory for BlockchainBridgeSubsFactoryReal { @@ -550,7 +554,7 @@ mod tests { 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::test_utils::BlockchainAgentMock; use crate::accountant::scanners::test_utils::protect_payables_in_test; - use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint}; + use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint, make_ripe_qualified_payables}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError::TransactionID; use crate::blockchain::blockchain_interface::data_structures::errors::{ @@ -596,6 +600,7 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160}; use masq_lib::constants::DEFAULT_MAX_BLOCK_COUNT; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesWithGasPrice, QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt}; impl Handler> for BlockchainBridge { @@ -685,7 +690,8 @@ mod tests { ); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) - .ok_response("0x230000000".to_string(), 1) // 9395240960 + // Fetching a recommended gas price + .ok_response("0x230000000".to_string(), 1) .ok_response("0xAAAA".to_string(), 1) .ok_response( "0x000000000000000000000000000000000000000000000000000000000000FFFF".to_string(), @@ -724,9 +730,9 @@ mod tests { false, ); subject.payable_payments_setup_subs_opt = Some(accountant_recipient); - let qualified_payables = protect_payables_in_test(qualified_payables.clone()); + let raw_qualified_payables = QualifiedPayablesRawPack{payables: qualified_payables.clone().into_iter().map(|payable|QualifiedPayablesBeforeGasPricePick{payable, previous_attempt_gas_price_minor_opt:None}).collect()}; let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: qualified_payables.clone(), + qualified_payables: raw_qualified_payables.clone(), consuming_wallet: consuming_wallet.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, @@ -744,9 +750,10 @@ mod tests { let accountant_received_payment = accountant_recording_arc.lock().unwrap(); let blockchain_agent_with_context_msg_actual: &BlockchainAgentWithContextMessage = accountant_received_payment.get_record(0); + let expected_ripe_qualified_payables = QualifiedPayablesRipePack{payables: qualified_payables.into_iter().map(|payable|QualifiedPayablesWithGasPrice{payable, gas_price_minor: 0x230000000 }).collect()}; assert_eq!( blockchain_agent_with_context_msg_actual.qualified_payables, - qualified_payables + expected_ripe_qualified_payables ); assert_eq!( blockchain_agent_with_context_msg_actual @@ -801,9 +808,9 @@ mod tests { false, ); subject.payable_payments_setup_subs_opt = Some(accountant_recipient); - let qualified_payables = protect_payables_in_test(vec![]); + let qualified_payables = QualifiedPayablesRawPack::from(vec![make_payable_account(123)]); let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: qualified_payables, + qualified_payables, consuming_wallet: consuming_wallet.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, @@ -818,7 +825,6 @@ mod tests { System::current().stop(); system.run(); - let accountant_recording = accountant_recording_arc.lock().unwrap(); assert_eq!(accountant_recording.len(), 0); let service_fee_balance_error = BlockchainAgentBuildError::ServiceFeeBalance( @@ -837,10 +843,10 @@ mod tests { } #[test] - fn handle_outbound_payments_instructions_sees_payments_happen_and_sends_payment_results_back_to_accountant( + fn handle_outbound_payments_instructions_sees_payment_happen_and_sends_payment_results_back_to_accountant( ) { let system = System::new( - "handle_outbound_payments_instructions_sees_payments_happen_and_sends_payment_results_back_to_accountant", + "handle_outbound_payments_instructions_sees_payment_happen_and_sends_payment_results_back_to_accountant", ); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) @@ -866,16 +872,15 @@ mod tests { let subject_subs = BlockchainBridge::make_subs_from(&addr); let mut peer_actors = peer_actors_builder().build(); peer_actors.accountant = make_accountant_subs_from_recorder(&accountant_addr); - let accounts = vec![PayableAccount { + let account = PayableAccount { wallet: wallet_account, balance_wei: 111_420_204, last_paid_timestamp: from_unix_timestamp(150_000_000), pending_payable_opt: None, - }]; + }; let agent_id_stamp = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default() .set_arbitrary_id_stamp(agent_id_stamp) - .gas_price_result(123) .consuming_wallet_result(consuming_wallet) .get_chain_result(Chain::PolyMainnet); @@ -883,7 +888,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - affordable_accounts: accounts.clone(), + affordable_accounts: make_ripe_qualified_payables(vec![(account.clone(), 111_222_333)]), agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -903,7 +908,7 @@ mod tests { sent_payables_msg, &SentPayables { payment_procedure_result: Ok(vec![Correct(PendingPayable { - recipient_wallet: accounts[0].wallet.clone(), + recipient_wallet: account.wallet, hash: H256::from_str( "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" ) @@ -924,7 +929,7 @@ mod tests { "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" ) .unwrap(), - amount: accounts[0].balance_wei + amount: account.balance_wei }] ); assert_eq!(accountant_recording.len(), 2); @@ -956,12 +961,12 @@ mod tests { let subject_subs = BlockchainBridge::make_subs_from(&addr); let mut peer_actors = peer_actors_builder().build(); peer_actors.accountant = make_accountant_subs_from_recorder(&accountant_addr); - let accounts = vec![PayableAccount { + let account = PayableAccount { wallet: wallet_account, balance_wei: 111_420_204, last_paid_timestamp: from_unix_timestamp(150_000_000), pending_payable_opt: None, - }]; + }; let consuming_wallet = make_paying_wallet(b"consuming_wallet"); let agent = BlockchainAgentMock::default() .consuming_wallet_result(consuming_wallet) @@ -971,7 +976,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - affordable_accounts: accounts.clone(), + affordable_accounts: make_ripe_qualified_payables(vec![(account.clone(), 111_222_333)]), agent: Box::new(agent), response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1000,7 +1005,7 @@ mod tests { "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" ) .unwrap(), - amount: accounts[0].balance_wei + amount: account.balance_wei }] ); assert_eq!( @@ -1034,13 +1039,13 @@ mod tests { let consuming_wallet = make_paying_wallet(b"consuming_wallet"); let accounts_1 = make_payable_account(1); let accounts_2 = make_payable_account(2); - let accounts = vec![accounts_1.clone(), accounts_2.clone()]; + let affordable_qualified_payables = make_ripe_qualified_payables(vec![(accounts_1.clone(), 777_777_777), (accounts_2.clone(), 999_999_999)]); let system = System::new(test_name); let agent = BlockchainAgentMock::default() .consuming_wallet_result(consuming_wallet) .gas_price_result(1) .get_chain_result(Chain::PolyMainnet); - let msg = OutboundPaymentsInstructions::new(accounts, Box::new(agent), None); + let msg = OutboundPaymentsInstructions::new(affordable_qualified_payables, Box::new(agent), None); let persistent_config = PersistentConfigurationMock::new(); let mut subject = BlockchainBridge::new( Box::new(blockchain_interface_web3), @@ -1097,7 +1102,7 @@ mod tests { .get_chain_result(TEST_DEFAULT_CHAIN) .consuming_wallet_result(consuming_wallet) .gas_price_result(123); - let msg = OutboundPaymentsInstructions::new(vec![], Box::new(agent), None); + let msg = OutboundPaymentsInstructions::new(make_ripe_qualified_payables(vec![(make_payable_account(111), 111_000_000)]), Box::new(agent), None); let persistent_config = configure_default_persistent_config(ZERO); let mut subject = BlockchainBridge::new( Box::new(blockchain_interface_web3), @@ -2218,6 +2223,12 @@ mod tests { assert_on_initialization_with_panic_on_migration(&data_dir, &act); } + + #[test] + fn increase_gas_price_by_margin_works() { + assert_eq!(increase_gas_price_by_margin(1_000_000_000, Chain::BaseMainnet), 1_300_000_000); + assert_eq!(increase_gas_price_by_margin(9_000_000_000, Chain::PolyAmoy), 11_700_000_000); + } } #[cfg(test)] diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index f057c92f9..260632740 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -447,7 +447,7 @@ mod tests { BlockchainAgentBuildError, BlockchainError, BlockchainInterface, RetrievedBlockchainTransactions, }; - use crate::blockchain::test_utils::{all_chains, increase_gas_price_by_marginal, make_blockchain_interface_web3, ReceiptResponseBuilder}; + use crate::blockchain::test_utils::{all_chains, make_blockchain_interface_web3, ReceiptResponseBuilder}; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use crate::test_utils::make_paying_wallet; @@ -463,8 +463,9 @@ mod tests { use std::str::FromStr; use web3::transports::Http; use web3::types::{H256, U256}; - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPricePick}; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesWithGasPrice, QualifiedPayablesBeforeGasPricePick}; use crate::accountant::test_utils::make_payable_account; + use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; #[test] @@ -842,9 +843,9 @@ mod tests { let account_2 = make_payable_account(34); let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 - let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayableWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_2, 1_000_000_000)]}; + let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayablesWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayablesWithGasPrice::new(account_2, 1_000_000_000)]}; let expected_estimated_transaction_fee = todo!("fix me"); - + blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, expected_estimated_transaction_fee); } @@ -855,17 +856,17 @@ mod tests { let account_3 = make_payable_account(56); let raw_qualified_payables = QualifiedPayablesRawPack{payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1, Some(999_999_999)), - QualifiedPayablesBeforeGasPricePick::new(account_2, Some(1_000_000_000)), - QualifiedPayablesBeforeGasPricePick::new(account_3, Some(1_000_000_001)) + QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(999_999_999)), + QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(1_000_000_000)), + QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(1_000_000_001)) ]}; let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 - let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayableWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_2, 1_000_000_000), QualifiedPayableWithGasPrice::new(account_3, 1_000_000_001)]}; + let expected_ripe_qualified_payables = QualifiedPayablesRipePack {payables: vec![QualifiedPayablesWithGasPrice::new(account_1, 1_000_000_000), QualifiedPayablesWithGasPrice::new(account_2, 1_000_000_000), QualifiedPayablesWithGasPrice::new(account_3, 1_000_000_001)]}; let expected_estimated_transaction_fee = todo!("fix me"); blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, expected_estimated_transaction_fee); } - + fn blockchain_interface_web3_can_introduce_blockchain_agent(raw_qualified_payables: QualifiedPayablesRawPack, gas_price_wei_from_rpc_hex: &str, expected_ripe_qualified_payables: QualifiedPayablesRipePack, expected_estimated_transaction_fee: u128) { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) @@ -898,7 +899,7 @@ mod tests { masq_token_balance_in_minor_units: expected_masq_balance } ); - let expected_gas_price_wei = increase_gas_price_by_marginal(u128::from_str_radix(gas_price_wei_from_rpc_hex,16).unwrap(), chain); + let expected_gas_price_wei = increase_gas_price_by_margin(u128::from_str_radix(gas_price_wei_from_rpc_hex,16).unwrap(), chain); assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); assert_eq!( result.estimated_transaction_fee_total(), @@ -917,9 +918,9 @@ mod tests { let account_2 = make_payable_account(34); let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let subject = make_blockchain_interface_web3(port); - + let result = subject.introduce_blockchain_agent(raw_qualified_payables, wallet.clone()).wait(); - + let err = match result { Err(e) => e, _ => panic!("we expected Err() but got Ok()"), @@ -935,7 +936,7 @@ mod tests { let expected_err_factory = |_wallet:&Wallet| BlockchainAgentBuildError::GasPrice(QueryFailed( "Transport error: Error(IncompleteMessage)".to_string(), )); - + build_of_the_blockchain_agent_fails_on_blockchain_interface_error(port, expected_err_factory); } diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index c6099fbb5..028658150 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -642,7 +642,7 @@ mod tests { #[test] fn send_payables_within_batch_works() { - let accounts = vec![make_payable_account(1), make_payable_account(2)]; + let account_1 = make_payable_account(1); let account_2 = make_payable_account(2); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .begin_batch() @@ -653,14 +653,14 @@ mod tests { .start(); let expected_result = Ok(vec![ Correct(PendingPayable { - recipient_wallet: accounts[0].wallet.clone(), + recipient_wallet: account_1.wallet.clone(), hash: H256::from_str( "35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4", ) .unwrap(), }), Correct(PendingPayable { - recipient_wallet: accounts[1].wallet.clone(), + recipient_wallet: account_2.wallet.clone(), hash: H256::from_str( "7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3", ) @@ -670,7 +670,7 @@ mod tests { execute_send_payables_test( "send_payables_within_batch_works", - accounts, + make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]), expected_result, port, ); @@ -678,7 +678,7 @@ mod tests { #[test] fn send_payables_within_batch_fails_on_submit_batch_call() { - let accounts = vec![make_payable_account(1), make_payable_account(2)]; + let accounts = make_ripe_qualified_payables(vec![(make_payable_account(1), 111_222_333), (make_payable_account(2),222_333_444)]); let os_code = transport_error_code(); let os_msg = transport_error_message(); let port = find_free_port(); @@ -700,7 +700,8 @@ mod tests { #[test] fn send_payables_within_batch_all_payments_fail() { - let accounts = vec![make_payable_account(1), make_payable_account(2)]; + let account_1 = make_payable_account(1); + let account_2 = make_payable_account(2); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .begin_batch() @@ -725,7 +726,7 @@ mod tests { message: "The requests per second (RPS) of your requests are higher than your plan allows.".to_string(), data: None, }), - recipient_wallet: accounts[0].wallet.clone(), + recipient_wallet: account_1.wallet.clone(), hash: H256::from_str("35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4").unwrap(), }), Failed(RpcPayableFailure { @@ -734,14 +735,14 @@ mod tests { message: "The requests per second (RPS) of your requests are higher than your plan allows.".to_string(), data: None, }), - recipient_wallet: accounts[1].wallet.clone(), + recipient_wallet: account_2.wallet.clone(), hash: H256::from_str("7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3").unwrap(), }), ]); execute_send_payables_test( "send_payables_within_batch_all_payments_fail", - accounts, + make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2,111_111_111)]), expected_result, port, ); @@ -749,7 +750,8 @@ mod tests { #[test] fn send_payables_within_batch_one_payment_works_the_other_fails() { - let accounts = vec![make_payable_account(1), make_payable_account(2)]; + let account_1 = make_payable_account(1); + let account_2 = make_payable_account(2); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .begin_batch() @@ -764,7 +766,7 @@ mod tests { .start(); let expected_result = Ok(vec![ Correct(PendingPayable { - recipient_wallet: accounts[0].wallet.clone(), + recipient_wallet: account_1.wallet.clone(), hash: H256::from_str("35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4").unwrap(), }), Failed(RpcPayableFailure { @@ -773,14 +775,14 @@ mod tests { message: "The requests per second (RPS) of your requests are higher than your plan allows.".to_string(), data: None, }), - recipient_wallet: accounts[1].wallet.clone(), + recipient_wallet: account_2.wallet.clone(), hash: H256::from_str("7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3").unwrap(), }), ]); execute_send_payables_test( "send_payables_within_batch_one_payment_works_the_other_fails", - accounts, + make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2,111_111_111)]), expected_result, port, ); diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index c2f65a5cc..1c93057d3 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -52,9 +52,9 @@ mod tests { use masq_lib::constants::DEFAULT_CHAIN; use masq_lib::test_utils::mock_blockchain_client_server::MBCSBuilder; use masq_lib::utils::find_free_port; - use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayableWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; + use crate::accountant::scanners::mid_scan_msg_handling::payable_scanner::msgs::{QualifiedPayablesWithGasPrice, QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::accountant::test_utils::make_payable_account; - use crate::blockchain::test_utils::increase_gas_price_by_marginal; + use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; #[test] fn initialize_web3_interface_works() { @@ -83,9 +83,9 @@ mod tests { .wait() .unwrap(); assert_eq!(blockchain_agent.consuming_wallet(), &wallet); - let gas_price_with_margin = increase_gas_price_by_marginal(1_000_000_000, chain); + let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000, chain); let expected_ripe_qualified_payables = QualifiedPayablesRipePack{ payables: - vec![QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin)]}; + vec![QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin)]}; assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); assert_eq!( blockchain_agent.estimated_transaction_fee_total(), diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index 8c4b8bd34..5ff2e5f9e 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -217,8 +217,4 @@ pub fn transport_error_message() -> String { } else { "Connection refused".to_string() } -} - -pub fn increase_gas_price_by_marginal(gas_price: u128, chain: Chain) -> u128 { - (gas_price * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100 } \ No newline at end of file From 1f512bb7688fd89ddd2dd656738c37e7a4587aef Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 15 Jun 2025 22:31:28 +0200 Subject: [PATCH 04/17] GH-638: little rearrangement in the project tree before I bring in more files --- .../accountant/scanners/payable_scanner_extension/mod.rs | 3 --- .../scanners/payable_scanner_extension/msgs.rs | 2 +- .../scanners/payable_scanner_extension/test_utils.rs | 2 +- .../blockchain_agent}/agent_null.rs | 6 +++--- .../blockchain_agent}/agent_web3.rs | 9 ++++----- .../blockchain_agent/mod.rs} | 2 ++ node/src/blockchain/blockchain_bridge.rs | 3 +-- .../blockchain_interface_web3/mod.rs | 3 +-- .../blockchain_interface_web3/utils.rs | 6 +++--- node/src/blockchain/blockchain_interface/mod.rs | 2 +- node/src/blockchain/mod.rs | 1 + node/src/sub_lib/blockchain_bridge.rs | 2 +- 12 files changed, 19 insertions(+), 22 deletions(-) rename node/src/{accountant/scanners/payable_scanner_extension => blockchain/blockchain_agent}/agent_null.rs (95%) rename node/src/{accountant/scanners/payable_scanner_extension => blockchain/blockchain_agent}/agent_web3.rs (97%) rename node/src/{accountant/scanners/payable_scanner_extension/blockchain_agent.rs => blockchain/blockchain_agent/mod.rs} (96%) diff --git a/node/src/accountant/scanners/payable_scanner_extension/mod.rs b/node/src/accountant/scanners/payable_scanner_extension/mod.rs index 649bc820f..1d1e8cb0b 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/mod.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/mod.rs @@ -1,8 +1,5 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod agent_null; -pub mod agent_web3; -pub mod blockchain_agent; pub mod msgs; pub mod test_utils; diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index 40d10d19c..5337eb5d3 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -1,8 +1,8 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::db_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::sub_lib::wallet::Wallet; use actix::Message; use std::collections::{HashMap, HashSet}; diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index 0b9bcb0f1..2027a9f6e 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -2,7 +2,7 @@ #![cfg(test)] -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; diff --git a/node/src/accountant/scanners/payable_scanner_extension/agent_null.rs b/node/src/blockchain/blockchain_agent/agent_null.rs similarity index 95% rename from node/src/accountant/scanners/payable_scanner_extension/agent_null.rs rename to node/src/blockchain/blockchain_agent/agent_null.rs index e0f45a80c..9d076bbe4 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/agent_null.rs +++ b/node/src/blockchain/blockchain_agent/agent_null.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; use ethereum_types::U256; @@ -79,8 +79,6 @@ impl Default for BlockchainAgentNull { #[cfg(test)] mod tests { - use crate::accountant::scanners::payable_scanner_extension::agent_null::BlockchainAgentNull; - use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use std::collections::HashMap; use crate::sub_lib::blockchain_bridge::{ @@ -88,6 +86,8 @@ mod tests { }; use crate::sub_lib::wallet::Wallet; + use crate::blockchain::blockchain_agent::agent_null::BlockchainAgentNull; + use crate::blockchain::blockchain_agent::BlockchainAgent; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; diff --git a/node/src/accountant/scanners/payable_scanner_extension/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs similarity index 97% rename from node/src/accountant/scanners/payable_scanner_extension/agent_web3.rs rename to node/src/blockchain/blockchain_agent/agent_web3.rs index fba5868cb..b898562e4 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -1,9 +1,9 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::accountant::scanners::payable_scanner_extension::msgs::{ QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; use crate::sub_lib::wallet::Wallet; @@ -97,15 +97,14 @@ impl BlockchainAgentWeb3 { #[cfg(test)] mod tests { - use crate::accountant::scanners::payable_scanner_extension::agent_web3::{ - BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, - }; - use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::accountant::scanners::payable_scanner_extension::msgs::{ QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; use crate::accountant::test_utils::make_payable_account; + use crate::blockchain::blockchain_agent::agent_web3::{ + BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + }; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::test_utils::make_wallet; diff --git a/node/src/accountant/scanners/payable_scanner_extension/blockchain_agent.rs b/node/src/blockchain/blockchain_agent/mod.rs similarity index 96% rename from node/src/accountant/scanners/payable_scanner_extension/blockchain_agent.rs rename to node/src/blockchain/blockchain_agent/mod.rs index 050391544..13725bf0c 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/blockchain_agent.rs +++ b/node/src/blockchain/blockchain_agent/mod.rs @@ -1,4 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +pub mod agent_null; +pub mod agent_web3; use crate::arbitrary_id_stamp_in_trait; use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index b3d53c161..ce7c5fa1e 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -44,7 +44,7 @@ use ethabi::Hash; use web3::types::H256; use masq_lib::messages::ScanType; use crate::accountant::db_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionReceiptResult, TxStatus}; pub const CRASH_KEY: &str = "BLOCKCHAINBRIDGE"; @@ -556,7 +556,6 @@ mod tests { use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; use crate::accountant::db_access_objects::utils::from_unix_timestamp; - use crate::accountant::scanners::payable_scanner_extension::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::accountant::scanners::payable_scanner_extension::test_utils::BlockchainAgentMock; use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint, make_ripe_qualified_payables}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3}; diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 07ceaaffc..9f9400499 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -5,7 +5,6 @@ mod utils; use std::cmp::PartialEq; use std::collections::HashMap; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainError, PayableTransactionError}; use crate::blockchain::blockchain_interface::data_structures::{BlockchainTransaction, ProcessedPayableFallible}; use crate::blockchain::blockchain_interface::lower_level_interface::LowBlockchainInt; @@ -24,6 +23,7 @@ use web3::transports::{EventLoopHandle, Http}; use web3::types::{Address, Log, H256, U256, FilterBuilder, TransactionReceipt, BlockNumber}; use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{LowBlockchainIntWeb3, TransactionReceiptResult, TxReceipt, TxStatus}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::utils::{create_blockchain_agent_web3, send_payables_within_batch, BlockchainAgentFutureResult}; @@ -441,7 +441,6 @@ impl BlockchainInterfaceWeb3 { #[cfg(test)] mod tests { use super::*; - use crate::accountant::scanners::payable_scanner_extension::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ BlockchainInterfaceWeb3, CONTRACT_ABI, REQUESTS_IN_PARALLEL, TRANSACTION_LITERAL, TRANSFER_METHOD_ID, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index 898c37c2d..cd7821880 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -2,11 +2,11 @@ use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; -use crate::accountant::scanners::payable_scanner_extension::agent_web3::BlockchainAgentWeb3; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::accountant::scanners::payable_scanner_extension::msgs::{ QualifiedPayablesRawPack, QualifiedPayablesRipePack, }; +use crate::blockchain::blockchain_agent::agent_web3::BlockchainAgentWeb3; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ BlockchainInterfaceWeb3, HashAndAmount, TRANSFER_METHOD_ID, @@ -342,12 +342,12 @@ mod tests { use super::*; use crate::accountant::db_access_objects::utils::from_unix_timestamp; use crate::accountant::gwei_to_wei; - use crate::accountant::scanners::payable_scanner_extension::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, make_ripe_qualified_payables, }; use crate::blockchain::bip32::Bip32EncryptionKeyProvider; + use crate::blockchain::blockchain_agent::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL, }; diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index 68b0bbe55..9c2d02e0a 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -6,7 +6,6 @@ pub mod lower_level_interface; use actix::Recipient; use ethereum_types::H256; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainAgentBuildError, BlockchainError, PayableTransactionError}; use crate::blockchain::blockchain_interface::data_structures::{ProcessedPayableFallible, RetrievedBlockchainTransactions}; use crate::blockchain::blockchain_interface::lower_level_interface::LowBlockchainInt; @@ -17,6 +16,7 @@ use web3::types::Address; use masq_lib::logger::Logger; use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TransactionReceiptResult; diff --git a/node/src/blockchain/mod.rs b/node/src/blockchain/mod.rs index 4c51e726e..48698c408 100644 --- a/node/src/blockchain/mod.rs +++ b/node/src/blockchain/mod.rs @@ -1,6 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. pub mod bip32; pub mod bip39; +pub mod blockchain_agent; pub mod blockchain_bridge; pub mod blockchain_interface; pub mod blockchain_interface_initializer; diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index c0f3ea256..4ea4e4c52 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,11 +1,11 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::db_access_objects::payable_dao::PayableAccount; -use crate::accountant::scanners::payable_scanner_extension::blockchain_agent::BlockchainAgent; use crate::accountant::scanners::payable_scanner_extension::msgs::{ QualifiedPayablesMessage, QualifiedPayablesRipePack, }; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; +use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::RetrieveTransactions; use crate::sub_lib::peer_actors::BindMessage; use actix::Message; From 4b71f33d1823e8ac6dfa7716114d64239e053a98 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 16 Jun 2025 13:38:54 +0200 Subject: [PATCH 05/17] GH-638: transmission log repair --- .../mock_blockchain_client_server.rs | 2 +- node/src/accountant/scanners/mod.rs | 6 +- .../payable_scanner_extension/msgs.rs | 8 +- node/src/accountant/test_utils.rs | 4 +- .../blockchain/blockchain_agent/agent_null.rs | 8 - .../blockchain/blockchain_agent/agent_web3.rs | 168 +++++++----- node/src/blockchain/blockchain_bridge.rs | 14 +- .../blockchain_interface_web3/mod.rs | 14 +- .../blockchain_interface_web3/utils.rs | 246 ++++++++++++------ .../blockchain_interface_initializer.rs | 18 +- 10 files changed, 311 insertions(+), 177 deletions(-) diff --git a/masq_lib/src/test_utils/mock_blockchain_client_server.rs b/masq_lib/src/test_utils/mock_blockchain_client_server.rs index 424a4433d..80df649be 100644 --- a/masq_lib/src/test_utils/mock_blockchain_client_server.rs +++ b/masq_lib/src/test_utils/mock_blockchain_client_server.rs @@ -220,7 +220,7 @@ impl MockBlockchainClientServer { Err(e) if e.kind() == ErrorKind::TimedOut => (), Err(e) => panic!("MBCS accept() failed: {:?}", e), }; - thread::sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(50)); }; drop(listener); conn.set_nonblocking(true).unwrap(); diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 519971143..92faaad76 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1395,7 +1395,7 @@ mod tests { PendingPayable, PendingPayableDaoError, TransactionHashes, }; use crate::accountant::db_access_objects::utils::{from_unix_timestamp, to_unix_timestamp}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesMessage, QualifiedPayablesRawPack}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesMessage, QualifiedPayablesRawPack}; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult, PendingPayableMetadata}; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::{handle_none_status, handle_status_with_failure, PendingPayableScanReport, PendingPayableScanResult}; use crate::accountant::scanners::{Scanner, StartScanError, StartableScanner, PayableScanner, PendingPayableScanner, ReceivableScanner, ScannerCommon, Scanners, MTError}; @@ -1645,7 +1645,7 @@ mod tests { let expected_raw_qualified_payables = QualifiedPayablesRawPack { payables: qualified_payable_accounts .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick::new(payable, None)) + .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) .collect::>(), }; assert_eq!( @@ -1739,7 +1739,7 @@ mod tests { fn retry_payable_scanner_can_initiate_a_scan() { todo!("this must be set up under the other card"); // TODO make sure the QualifiedPayableRawPack will express the difference from - // the NewPayable scanner: The QualifiedPayablesBeforeGasPricePick needs to carry + // the NewPayable scanner: The QualifiedPayablesBeforeGasPriceSelection needs to carry // `Some()` instead of None // init_test_logging(); diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index 5337eb5d3..8b5f4756c 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -17,7 +17,7 @@ pub struct QualifiedPayablesMessage { #[derive(Debug, PartialEq, Eq, Clone)] pub struct QualifiedPayablesRawPack { - pub payables: Vec, + pub payables: Vec, } impl From> for QualifiedPayablesRawPack { @@ -25,19 +25,19 @@ impl From> for QualifiedPayablesRawPack { QualifiedPayablesRawPack { payables: qualified_payable .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick::new(payable, None)) + .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) .collect(), } } } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayablesBeforeGasPricePick { +pub struct QualifiedPayablesBeforeGasPriceSelection { pub payable: PayableAccount, pub previous_attempt_gas_price_minor_opt: Option, } -impl QualifiedPayablesBeforeGasPricePick { +impl QualifiedPayablesBeforeGasPriceSelection { pub fn new( payable: PayableAccount, previous_attempt_gas_price_minor_opt: Option, diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 800d92ae5..5c2273901 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -17,7 +17,7 @@ use crate::accountant::db_access_objects::utils::{ }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - BlockchainAgentWithContextMessage, QualifiedPayablesBeforeGasPricePick, + BlockchainAgentWithContextMessage, QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; use crate::accountant::scanners::payable_scanner_extension::PreparedAdjustment; @@ -1522,7 +1522,7 @@ pub fn make_raw_qualified_payables_for_retry_mode( payables: inputs .into_iter() .map(|(payable, previous_attempt_gas_price_minor)| { - QualifiedPayablesBeforeGasPricePick { + QualifiedPayablesBeforeGasPriceSelection { payable, previous_attempt_gas_price_minor_opt: Some(previous_attempt_gas_price_minor), } diff --git a/node/src/blockchain/blockchain_agent/agent_null.rs b/node/src/blockchain/blockchain_agent/agent_null.rs index 9d076bbe4..1024febec 100644 --- a/node/src/blockchain/blockchain_agent/agent_null.rs +++ b/node/src/blockchain/blockchain_agent/agent_null.rs @@ -28,14 +28,6 @@ impl BlockchainAgent for BlockchainAgentNull { } } - // fn finalize_gas_price_per_payable(&self, qualified_payables: QualifiedPayablesRawPack) -> QualifiedPayablesRipePack { - // self.log_function_call("finalize_gas_price_per_payable()"); - // let payables = qualified_payables.payables.into_iter().map(|preconfiguration| { - // QualifiedPayablesWithGasPrice{ payable: preconfiguration.payable, gas_price_minor: 0 } - // }).collect(); - // QualifiedPayablesRipePack{ payables } - // } - fn consuming_wallet(&self) -> &Wallet { self.log_function_call("consuming_wallet()"); &self.wallet diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index b898562e4..288561c81 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -1,22 +1,18 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, + QualifiedPayablesWithGasPrice, }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; -use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; -use std::collections::HashMap; -use web3::types::Address; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { - estimated_gas_price_wei: u128, - // gas_price_hashmap: HashMap, - // gas_limit_const_part: u128, - // maximum_added_gas_margin: u128, + estimated_gas_price_for_all_txs_wei: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, @@ -24,7 +20,7 @@ pub struct BlockchainAgentWeb3 { impl BlockchainAgent for BlockchainAgentWeb3 { fn estimated_transaction_fee_total(&self) -> u128 { - todo!() // self.gas_price_hashmap.values().sum::() * (self.gas_limit_const_part + self.maximum_added_gas_margin) + self.estimated_gas_price_for_all_txs_wei } fn consuming_wallet_balances(&self) -> ConsumingWalletBalances { @@ -56,28 +52,16 @@ impl BlockchainAgentWeb3 { let current_gas_price_with_margin = increase_gas_price_by_margin(latest_gas_price_wei, chain); + let fold_init = (QualifiedPayablesRipePack { payables: vec![] }, 0); let (ripe_qualified_payables, gas_price_aggregated_wei) = raw_qualified_payables.payables.into_iter().fold( - (QualifiedPayablesRipePack { payables: vec![] }, 0), - |(mut ripe_qualified_payables, mut gas_price_aggregated_wei), raw_q_payable| { - let picked_gas_price_wei = match raw_q_payable - .previous_attempt_gas_price_minor_opt - { - None => current_gas_price_with_margin, - Some(previous_price) if current_gas_price_with_margin < previous_price => { - previous_price - } - Some(_) => current_gas_price_with_margin, - }; - let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new( - raw_q_payable.payable, - picked_gas_price_wei, - ); - ripe_qualified_payables - .payables - .push(ripe_qualified_payable); - gas_price_aggregated_wei += picked_gas_price_wei; - (ripe_qualified_payables, gas_price_aggregated_wei) + fold_init, + |(ripe_qualified_payables, gas_price_aggregated_wei), raw_q_payable| { + Self::fold_guts( + (ripe_qualified_payables, gas_price_aggregated_wei), + raw_q_payable, + current_gas_price_with_margin, + ) }, ); @@ -85,7 +69,7 @@ impl BlockchainAgentWeb3 { gas_price_aggregated_wei * (gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); let agent = Self { - estimated_gas_price_wei, + estimated_gas_price_for_all_txs_wei: estimated_gas_price_wei, consuming_wallet, consuming_wallet_balances, chain, @@ -93,13 +77,37 @@ impl BlockchainAgentWeb3 { (Box::new(agent), ripe_qualified_payables) } + + fn fold_guts( + (mut ripe_qualified_payables, mut gas_price_aggregated_wei): ( + QualifiedPayablesRipePack, + u128, + ), + raw_q_payable: QualifiedPayablesBeforeGasPriceSelection, + current_gas_price_with_margin: u128, + ) -> (QualifiedPayablesRipePack, u128) { + let selected_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { + None => current_gas_price_with_margin, + Some(previous_price) if current_gas_price_with_margin < previous_price => { + previous_price + } + Some(_) => current_gas_price_with_margin, + }; + let ripe_qualified_payable = + QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, selected_gas_price_wei); + ripe_qualified_payables + .payables + .push(ripe_qualified_payable); + gas_price_aggregated_wei += selected_gas_price_wei; + (ripe_qualified_payables, gas_price_aggregated_wei) + } } #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack, - QualifiedPayablesWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, + QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_agent::agent_web3::{ @@ -155,6 +163,9 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; + let rpc_gas_price_wei = 444_555_666; + let chain = TEST_DEFAULT_CHAIN; + let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -162,11 +173,26 @@ mod tests { let account_5 = make_payable_account(90); let qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(444_555_665)), - QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(444_555_666)), - QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(444_555_667)), - QualifiedPayablesBeforeGasPricePick::new(account_4.clone(), Some(111_111_111)), - QualifiedPayablesBeforeGasPricePick::new(account_5.clone(), Some(500_000_000)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_1.clone(), + Some(rpc_gas_price_with_margin_wei - 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(rpc_gas_price_with_margin_wei), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(rpc_gas_price_with_margin_wei + 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_4.clone(), + Some(rpc_gas_price_with_margin_wei - 123_456), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_5.clone(), + Some(rpc_gas_price_with_margin_wei + 456_789), + ), ], }; let gas_price_from_rpc = 444_555_666; @@ -181,21 +207,17 @@ mod tests { chain, ); - let expected_result = { - let gas_price_account_1 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_2 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_3 = increase_gas_price_by_margin(444_555_667, chain); - let gas_price_account_4 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_5 = increase_gas_price_by_margin(500_000_000, chain); - QualifiedPayablesRipePack { - payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), - QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), - QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_4), - QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_5), - ], - } + let expected_result = QualifiedPayablesRipePack { + payables: vec![ + QualifiedPayablesWithGasPrice::new(account_1, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new(account_2, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new(account_3, rpc_gas_price_with_margin_wei + 1), + QualifiedPayablesWithGasPrice::new(account_4, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new( + account_5, + rpc_gas_price_with_margin_wei + 456_789, + ), + ], }; assert_eq!(ripe_qualified_payables, expected_result); } @@ -262,6 +284,9 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; + let rpc_gas_price_wei = 444_555_666; + let chain = TEST_DEFAULT_CHAIN; + let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -269,17 +294,32 @@ mod tests { let account_5 = make_payable_account(90); let qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), - QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), - QualifiedPayablesBeforeGasPricePick::new(account_3, Some(444_555_667)), - QualifiedPayablesBeforeGasPricePick::new(account_4, Some(111_111_111)), - QualifiedPayablesBeforeGasPricePick::new(account_5, Some(500_000_000)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_1.clone(), + Some(rpc_gas_price_with_margin_wei - 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(rpc_gas_price_with_margin_wei), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(rpc_gas_price_with_margin_wei + 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_4.clone(), + Some(rpc_gas_price_with_margin_wei - 123_456), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_5.clone(), + Some(rpc_gas_price_with_margin_wei + 456_789), + ), ], }; let chain = TEST_DEFAULT_CHAIN; let (agent, _) = BlockchainAgentWeb3::new( qualified_payables, - 444_555_666, + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, @@ -290,11 +330,13 @@ mod tests { assert_eq!( result, - (increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(444_555_667, chain) - + increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(500_000_000, chain)) + (rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + 1 + + rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + 456_789) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index ce7c5fa1e..fc3ec1f87 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -601,7 +601,7 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160}; use masq_lib::constants::DEFAULT_MAX_BLOCK_COUNT; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesWithGasPrice}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt}; impl Handler> for BlockchainBridge { @@ -685,9 +685,7 @@ mod tests { #[test] fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant() { let system = System::new( - " fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant( -", - ); + "handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant"); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) // Fetching a recommended gas price @@ -734,7 +732,7 @@ mod tests { payables: qualified_payables .clone() .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick { + .map(|payable| QualifiedPayablesBeforeGasPriceSelection { payable, previous_attempt_gas_price_minor_opt: None, }) @@ -764,7 +762,7 @@ mod tests { .into_iter() .map(|payable| QualifiedPayablesWithGasPrice { payable, - gas_price_minor: 0x230000000, + gas_price_minor: increase_gas_price_by_margin(0x230000000, chain), }) .collect(), }; @@ -784,13 +782,11 @@ mod tests { .consuming_wallet_balances(), ConsumingWalletBalances::new(0xAAAA.into(), 0xFFFF.into()) ); - let gas_limit_const_part = - BlockchainInterfaceWeb3::web3_gas_limit_const_part(Chain::PolyMainnet); assert_eq!( blockchain_agent_with_context_msg_actual .agent .estimated_transaction_fee_total(), - todo!() + 1_791_228_995_698_688 ); assert_eq!( blockchain_agent_with_context_msg_actual.response_skeleton_opt, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 9f9400499..ad593448e 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -467,7 +467,7 @@ mod tests { use std::str::FromStr; use web3::transports::Http; use web3::types::{H256, U256}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesWithGasPrice}; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; @@ -871,9 +871,15 @@ mod tests { let account_3 = make_payable_account(56); let raw_qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(999_999_999)), - QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(1_000_000_000)), - QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(1_000_000_001)), + QualifiedPayablesBeforeGasPriceSelection::new(account_1.clone(), Some(999_999_999)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(1_000_000_000), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(1_000_000_001), + ), ], }; let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index cd7821880..f1b2d10a2 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -18,12 +18,15 @@ use crate::blockchain::blockchain_interface::data_structures::{ use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use actix::Recipient; +use bytes::Buf; use futures::Future; use masq_lib::blockchains::chains::Chain; +use masq_lib::constants::WALLET_ADDRESS_LENGTH; use masq_lib::logger::Logger; use secp256k1secrets::SecretKey; use serde_json::Value; use std::fmt::Display; +use std::iter::once; use std::time::SystemTime; use thousands::Separable; use web3::transports::{Batch, Http}; @@ -86,46 +89,62 @@ pub fn merged_output_data( .collect() } -pub fn transmission_log(chain: Chain, accounts: &QualifiedPayablesRipePack) -> String { - todo!() - // let chain_name = chain - // .rec() - // .literal_identifier - // .chars() - // .skip_while(|char| char != &'-') - // .skip(1) - // .collect::(); - // const PAYMENT_VALUE_MAX_LENGTH_INCLUDING_COMMAS: usize = 24; - // let introduction = once(format!( - // "\ - // Paying to creditors...\n\ - // Transactions in the batch:\n\ - // \n\ - // chain: {}\n\ - // \n\ - // {:wallet_address_length$} {: value, - // None => &"NA" - // }; - // format!( - // "{:wallet_address_length$} {: String { + let chain_name = chain.rec().literal_identifier; + let account_count = qualified_payables_pack.payables.len(); + let last_nonce_used = lowest_nonce_used + U256::from(account_count - 1); + let biggest_payable = qualified_payables_pack + .payables + .iter() + .map(|payable_with_gas_price| payable_with_gas_price.payable.balance_wei) + .max() + .unwrap(); + let max_length_as_str = biggest_payable.separate_with_commas().len(); + let payment_wei_label = "[payment wei]"; + let payment_column_width = payment_wei_label.len().max(max_length_as_str); + + let introduction = once(format!( + "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + {:first_column_width$} {}\n\ + {:first_column_width$} {}...{}\n\ + \n\ + {:first_column_width$} {: [u8; 68] { @@ -155,7 +174,8 @@ pub fn sign_transaction( ) -> SignedTransaction { let data = sign_transaction_data(amount, recipient_wallet); let gas_limit = gas_limit(data, chain); - // Warning: If you set gas_price or nonce to None in transaction_parameters, sign_transaction will start making RPC calls which we don't want (Do it at your own risk). + // Warning: If you set gas_price or nonce to None in transaction_parameters, sign_transaction + // will start making RPC calls which we don't want (Do it at your own risk). let transaction_parameters = TransactionParameters { nonce: Some(nonce), to: Some(chain.rec().contract), @@ -288,7 +308,6 @@ pub fn send_payables_within_batch( let hashes_and_paid_amounts_error = hashes_and_paid_amounts.clone(); let hashes_and_paid_amounts_ok = hashes_and_paid_amounts.clone(); - // TODO: We are sending hashes_and_paid_amounts to the Accountant even if the payments fail. new_fingerprints_recipient .try_send(PendingPayableFingerprintSeeds { batch_wide_timestamp: timestamp, @@ -296,7 +315,11 @@ pub fn send_payables_within_batch( }) .expect("Accountant is dead"); - info!(logger, "{}", transmission_log(chain, &accounts)); + info!( + logger, + "{}", + transmission_log(chain, &accounts, pending_nonce) + ); Box::new( web3_batch @@ -481,27 +504,108 @@ mod tests { } #[test] - fn transmission_log_just_works() { - init_test_logging(); - let test_name = "transmission_log_just_works"; - let gas_price = 120; - let logger = Logger::new(test_name); - let amount_1 = gwei_to_wei(900_000_000_u64); + fn transmission_log_is_well_formatted() { + // This test only focuses on the formatting, but there are other tests asserting printing + // this in the logs + + // Case 1 + let payments = [ + gwei_to_wei(900_000_000_u64), + 123_456_789_u128, + gwei_to_wei(33_355_666_u64), + ]; + let pending_nonce = 123456789.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: base-sepolia\n\ + nonces: 123,456,789...123,456,791\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 900,000,000,000,000,000 123,456,789\n\ + 0x0000000000000000000000000000000077353535 123,456,789 234,567,890\n\ + 0x0000000000000000000000000000000077393837 33,355,666,000,000,000 345,678,901\n"; + + test_transmission_log( + 1, + payments, + Chain::BaseSepolia, + pending_nonce, + expected_format, + ); + + // Case 2 + let payments = [ + gwei_to_wei(5_400_u64), + gwei_to_wei(10_000_u64), + 44_444_555_u128, + ]; + let pending_nonce = 100.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: eth-mainnet\n\ + nonces: 100...102\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 5,400,000,000,000 123,456,789\n\ + 0x0000000000000000000000000000000077353535 10,000,000,000,000 234,567,890\n\ + 0x0000000000000000000000000000000077393837 44,444,555 345,678,901\n"; + + test_transmission_log( + 2, + payments, + Chain::EthMainnet, + pending_nonce, + expected_format, + ); + + // Case 3 + let payments = [45_000_888, 1_999_999, 444_444_555]; + let pending_nonce = 1.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: polygon-mainnet\n\ + nonces: 1...3\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 45,000,888 123,456,789\n\ + 0x0000000000000000000000000000000077353535 1,999,999 234,567,890\n\ + 0x0000000000000000000000000000000077393837 444,444,555 345,678,901\n"; + + test_transmission_log( + 3, + payments, + Chain::PolyMainnet, + pending_nonce, + expected_format, + ); + } + + fn test_transmission_log( + case: usize, + payments: [u128; 3], + chain: Chain, + pending_nonce: U256, + expected_result: &str, + ) { let account_1 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w123"), - amount_1, + payments[0], None, ); - let amount_2 = 123_456_789_u128; let account_2 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w555"), - amount_2, + payments[1], None, ); - let amount_3 = gwei_to_wei(33_355_666_u64); let account_3 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w987"), - amount_3, + payments[2], None, ); let accounts_to_process = make_ripe_qualified_payables(vec![ @@ -510,24 +614,12 @@ mod tests { (account_3, 345_678_901), ]); - info!( - logger, - "{}", - transmission_log(TEST_DEFAULT_CHAIN, &accounts_to_process) - ); + let result = transmission_log(chain, &accounts_to_process, pending_nonce); - let log_handler = TestLogHandler::new(); - log_handler.exists_log_containing( - "INFO: transmission_log_just_works: Paying to creditors...\n\ - Transactions in the batch:\n\ - \n\ - gas price: 120 wei\n\ - chain: sepolia\n\ - \n\ - [wallet address] [payment in wei]\n\ - 0x0000000000000000000000000000000077313233 900,000,000,000,000,000\n\ - 0x0000000000000000000000000000000077353535 123,456,789\n\ - 0x0000000000000000000000000000000077393837 33,355,666,000,000,000\n", + assert_eq!( + result, expected_result, + "Test case {}: we expected this format: \"{}\", but it was: \"{}\"", + case, expected_result, result ); } @@ -588,7 +680,7 @@ mod tests { ) } - fn execute_send_payables_test( + fn test_send_payables_within_batch( test_name: &str, accounts: QualifiedPayablesRipePack, expected_result: Result, PayableTransactionError>, @@ -640,7 +732,7 @@ mod tests { ); tlh.exists_log_containing(&format!( "INFO: {test_name}: {}", - transmission_log(chain, &accounts) + transmission_log(chain, &accounts, pending_nonce) )); assert_eq!(result, expected_result); } @@ -674,7 +766,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_works", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]), expected_result, @@ -699,7 +791,7 @@ mod tests { ], }); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_fails_on_submit_batch_call", accounts, expected_result, @@ -749,7 +841,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_all_payments_fail", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), expected_result, @@ -789,7 +881,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_one_payment_works_the_other_fails", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), expected_result, diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index da5377d6b..3b8214f98 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -10,8 +10,9 @@ use web3::transports::Http; pub(in crate::blockchain) struct BlockchainInterfaceInitializer {} impl BlockchainInterfaceInitializer { - // TODO when we have multiple chains of fundamentally different architectures and are able to switch them, - // this should probably be replaced by a HashMap of distinct interfaces for each chain + // TODO if we ever have multiple chains of fundamentally different architectures and are able + // to switch them, this should probably be replaced by a HashMap of distinct interfaces for + // each chain pub fn initialize_interface( &self, blockchain_service_url: &str, @@ -60,6 +61,9 @@ mod tests { #[test] fn initialize_web3_interface_works() { + // TODO this test should definitely assert on the web3 requests sent to the server, + // that's the best way to verify that this interface belongs to the web3 architecture + // (GH-543) let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .ok_response("0x3B9ACA00".to_string(), 0) // gas_price = 10000000000 @@ -70,7 +74,6 @@ mod tests { ) .ok_response("0x23".to_string(), 1) .start(); - let wallet = make_wallet("123"); let chain = Chain::PolyMainnet; let server_url = &format!("http://{}:{}", &Ipv4Addr::LOCALHOST, port); @@ -82,10 +85,10 @@ mod tests { QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let payable_wallet = make_wallet("payable"); let (blockchain_agent, ripe_qualified_payables) = result - .introduce_blockchain_agent(raw_qualified_payables, payable_wallet) + .introduce_blockchain_agent(raw_qualified_payables, payable_wallet.clone()) .wait() .unwrap(); - assert_eq!(blockchain_agent.consuming_wallet(), &wallet); + assert_eq!(blockchain_agent.consuming_wallet(), &payable_wallet); let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000, chain); let expected_ripe_qualified_payables = QualifiedPayablesRipePack { payables: vec![ @@ -94,7 +97,10 @@ mod tests { ], }; assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); - assert_eq!(blockchain_agent.estimated_transaction_fee_total(), todo!()); + assert_eq!( + blockchain_agent.estimated_transaction_fee_total(), + 190_652_800_000_000 + ); } #[test] From 5a67588b8b10694425d8dfe6bb1406d64f099613 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 16 Jun 2025 13:38:54 +0200 Subject: [PATCH 06/17] GH-638: transmission log repair and some other tests --- .../mock_blockchain_client_server.rs | 2 +- node/src/accountant/scanners/mod.rs | 6 +- .../payable_scanner_extension/msgs.rs | 8 +- node/src/accountant/test_utils.rs | 4 +- .../blockchain/blockchain_agent/agent_null.rs | 8 - .../blockchain/blockchain_agent/agent_web3.rs | 168 +++++++----- node/src/blockchain/blockchain_bridge.rs | 14 +- .../blockchain_interface_web3/mod.rs | 14 +- .../blockchain_interface_web3/utils.rs | 246 ++++++++++++------ .../blockchain_interface_initializer.rs | 18 +- 10 files changed, 311 insertions(+), 177 deletions(-) diff --git a/masq_lib/src/test_utils/mock_blockchain_client_server.rs b/masq_lib/src/test_utils/mock_blockchain_client_server.rs index 424a4433d..80df649be 100644 --- a/masq_lib/src/test_utils/mock_blockchain_client_server.rs +++ b/masq_lib/src/test_utils/mock_blockchain_client_server.rs @@ -220,7 +220,7 @@ impl MockBlockchainClientServer { Err(e) if e.kind() == ErrorKind::TimedOut => (), Err(e) => panic!("MBCS accept() failed: {:?}", e), }; - thread::sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(50)); }; drop(listener); conn.set_nonblocking(true).unwrap(); diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 519971143..92faaad76 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1395,7 +1395,7 @@ mod tests { PendingPayable, PendingPayableDaoError, TransactionHashes, }; use crate::accountant::db_access_objects::utils::{from_unix_timestamp, to_unix_timestamp}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesMessage, QualifiedPayablesRawPack}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesMessage, QualifiedPayablesRawPack}; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult, PendingPayableMetadata}; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::{handle_none_status, handle_status_with_failure, PendingPayableScanReport, PendingPayableScanResult}; use crate::accountant::scanners::{Scanner, StartScanError, StartableScanner, PayableScanner, PendingPayableScanner, ReceivableScanner, ScannerCommon, Scanners, MTError}; @@ -1645,7 +1645,7 @@ mod tests { let expected_raw_qualified_payables = QualifiedPayablesRawPack { payables: qualified_payable_accounts .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick::new(payable, None)) + .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) .collect::>(), }; assert_eq!( @@ -1739,7 +1739,7 @@ mod tests { fn retry_payable_scanner_can_initiate_a_scan() { todo!("this must be set up under the other card"); // TODO make sure the QualifiedPayableRawPack will express the difference from - // the NewPayable scanner: The QualifiedPayablesBeforeGasPricePick needs to carry + // the NewPayable scanner: The QualifiedPayablesBeforeGasPriceSelection needs to carry // `Some()` instead of None // init_test_logging(); diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index 5337eb5d3..8b5f4756c 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -17,7 +17,7 @@ pub struct QualifiedPayablesMessage { #[derive(Debug, PartialEq, Eq, Clone)] pub struct QualifiedPayablesRawPack { - pub payables: Vec, + pub payables: Vec, } impl From> for QualifiedPayablesRawPack { @@ -25,19 +25,19 @@ impl From> for QualifiedPayablesRawPack { QualifiedPayablesRawPack { payables: qualified_payable .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick::new(payable, None)) + .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) .collect(), } } } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayablesBeforeGasPricePick { +pub struct QualifiedPayablesBeforeGasPriceSelection { pub payable: PayableAccount, pub previous_attempt_gas_price_minor_opt: Option, } -impl QualifiedPayablesBeforeGasPricePick { +impl QualifiedPayablesBeforeGasPriceSelection { pub fn new( payable: PayableAccount, previous_attempt_gas_price_minor_opt: Option, diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 800d92ae5..5c2273901 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -17,7 +17,7 @@ use crate::accountant::db_access_objects::utils::{ }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - BlockchainAgentWithContextMessage, QualifiedPayablesBeforeGasPricePick, + BlockchainAgentWithContextMessage, QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; use crate::accountant::scanners::payable_scanner_extension::PreparedAdjustment; @@ -1522,7 +1522,7 @@ pub fn make_raw_qualified_payables_for_retry_mode( payables: inputs .into_iter() .map(|(payable, previous_attempt_gas_price_minor)| { - QualifiedPayablesBeforeGasPricePick { + QualifiedPayablesBeforeGasPriceSelection { payable, previous_attempt_gas_price_minor_opt: Some(previous_attempt_gas_price_minor), } diff --git a/node/src/blockchain/blockchain_agent/agent_null.rs b/node/src/blockchain/blockchain_agent/agent_null.rs index 9d076bbe4..1024febec 100644 --- a/node/src/blockchain/blockchain_agent/agent_null.rs +++ b/node/src/blockchain/blockchain_agent/agent_null.rs @@ -28,14 +28,6 @@ impl BlockchainAgent for BlockchainAgentNull { } } - // fn finalize_gas_price_per_payable(&self, qualified_payables: QualifiedPayablesRawPack) -> QualifiedPayablesRipePack { - // self.log_function_call("finalize_gas_price_per_payable()"); - // let payables = qualified_payables.payables.into_iter().map(|preconfiguration| { - // QualifiedPayablesWithGasPrice{ payable: preconfiguration.payable, gas_price_minor: 0 } - // }).collect(); - // QualifiedPayablesRipePack{ payables } - // } - fn consuming_wallet(&self) -> &Wallet { self.log_function_call("consuming_wallet()"); &self.wallet diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index b898562e4..288561c81 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -1,22 +1,18 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, + QualifiedPayablesWithGasPrice, }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; -use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; -use std::collections::HashMap; -use web3::types::Address; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { - estimated_gas_price_wei: u128, - // gas_price_hashmap: HashMap, - // gas_limit_const_part: u128, - // maximum_added_gas_margin: u128, + estimated_gas_price_for_all_txs_wei: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, @@ -24,7 +20,7 @@ pub struct BlockchainAgentWeb3 { impl BlockchainAgent for BlockchainAgentWeb3 { fn estimated_transaction_fee_total(&self) -> u128 { - todo!() // self.gas_price_hashmap.values().sum::() * (self.gas_limit_const_part + self.maximum_added_gas_margin) + self.estimated_gas_price_for_all_txs_wei } fn consuming_wallet_balances(&self) -> ConsumingWalletBalances { @@ -56,28 +52,16 @@ impl BlockchainAgentWeb3 { let current_gas_price_with_margin = increase_gas_price_by_margin(latest_gas_price_wei, chain); + let fold_init = (QualifiedPayablesRipePack { payables: vec![] }, 0); let (ripe_qualified_payables, gas_price_aggregated_wei) = raw_qualified_payables.payables.into_iter().fold( - (QualifiedPayablesRipePack { payables: vec![] }, 0), - |(mut ripe_qualified_payables, mut gas_price_aggregated_wei), raw_q_payable| { - let picked_gas_price_wei = match raw_q_payable - .previous_attempt_gas_price_minor_opt - { - None => current_gas_price_with_margin, - Some(previous_price) if current_gas_price_with_margin < previous_price => { - previous_price - } - Some(_) => current_gas_price_with_margin, - }; - let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new( - raw_q_payable.payable, - picked_gas_price_wei, - ); - ripe_qualified_payables - .payables - .push(ripe_qualified_payable); - gas_price_aggregated_wei += picked_gas_price_wei; - (ripe_qualified_payables, gas_price_aggregated_wei) + fold_init, + |(ripe_qualified_payables, gas_price_aggregated_wei), raw_q_payable| { + Self::fold_guts( + (ripe_qualified_payables, gas_price_aggregated_wei), + raw_q_payable, + current_gas_price_with_margin, + ) }, ); @@ -85,7 +69,7 @@ impl BlockchainAgentWeb3 { gas_price_aggregated_wei * (gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); let agent = Self { - estimated_gas_price_wei, + estimated_gas_price_for_all_txs_wei: estimated_gas_price_wei, consuming_wallet, consuming_wallet_balances, chain, @@ -93,13 +77,37 @@ impl BlockchainAgentWeb3 { (Box::new(agent), ripe_qualified_payables) } + + fn fold_guts( + (mut ripe_qualified_payables, mut gas_price_aggregated_wei): ( + QualifiedPayablesRipePack, + u128, + ), + raw_q_payable: QualifiedPayablesBeforeGasPriceSelection, + current_gas_price_with_margin: u128, + ) -> (QualifiedPayablesRipePack, u128) { + let selected_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { + None => current_gas_price_with_margin, + Some(previous_price) if current_gas_price_with_margin < previous_price => { + previous_price + } + Some(_) => current_gas_price_with_margin, + }; + let ripe_qualified_payable = + QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, selected_gas_price_wei); + ripe_qualified_payables + .payables + .push(ripe_qualified_payable); + gas_price_aggregated_wei += selected_gas_price_wei; + (ripe_qualified_payables, gas_price_aggregated_wei) + } } #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesRipePack, - QualifiedPayablesWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, + QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_agent::agent_web3::{ @@ -155,6 +163,9 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; + let rpc_gas_price_wei = 444_555_666; + let chain = TEST_DEFAULT_CHAIN; + let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -162,11 +173,26 @@ mod tests { let account_5 = make_payable_account(90); let qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(444_555_665)), - QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(444_555_666)), - QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(444_555_667)), - QualifiedPayablesBeforeGasPricePick::new(account_4.clone(), Some(111_111_111)), - QualifiedPayablesBeforeGasPricePick::new(account_5.clone(), Some(500_000_000)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_1.clone(), + Some(rpc_gas_price_with_margin_wei - 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(rpc_gas_price_with_margin_wei), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(rpc_gas_price_with_margin_wei + 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_4.clone(), + Some(rpc_gas_price_with_margin_wei - 123_456), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_5.clone(), + Some(rpc_gas_price_with_margin_wei + 456_789), + ), ], }; let gas_price_from_rpc = 444_555_666; @@ -181,21 +207,17 @@ mod tests { chain, ); - let expected_result = { - let gas_price_account_1 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_2 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_3 = increase_gas_price_by_margin(444_555_667, chain); - let gas_price_account_4 = increase_gas_price_by_margin(444_555_666, chain); - let gas_price_account_5 = increase_gas_price_by_margin(500_000_000, chain); - QualifiedPayablesRipePack { - payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), - QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), - QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_4), - QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_5), - ], - } + let expected_result = QualifiedPayablesRipePack { + payables: vec![ + QualifiedPayablesWithGasPrice::new(account_1, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new(account_2, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new(account_3, rpc_gas_price_with_margin_wei + 1), + QualifiedPayablesWithGasPrice::new(account_4, rpc_gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new( + account_5, + rpc_gas_price_with_margin_wei + 456_789, + ), + ], }; assert_eq!(ripe_qualified_payables, expected_result); } @@ -262,6 +284,9 @@ mod tests { transaction_fee_balance_in_minor_units: Default::default(), masq_token_balance_in_minor_units: Default::default(), }; + let rpc_gas_price_wei = 444_555_666; + let chain = TEST_DEFAULT_CHAIN; + let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -269,17 +294,32 @@ mod tests { let account_5 = make_payable_account(90); let qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1, Some(444_555_665)), - QualifiedPayablesBeforeGasPricePick::new(account_2, Some(444_555_666)), - QualifiedPayablesBeforeGasPricePick::new(account_3, Some(444_555_667)), - QualifiedPayablesBeforeGasPricePick::new(account_4, Some(111_111_111)), - QualifiedPayablesBeforeGasPricePick::new(account_5, Some(500_000_000)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_1.clone(), + Some(rpc_gas_price_with_margin_wei - 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(rpc_gas_price_with_margin_wei), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(rpc_gas_price_with_margin_wei + 1), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_4.clone(), + Some(rpc_gas_price_with_margin_wei - 123_456), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_5.clone(), + Some(rpc_gas_price_with_margin_wei + 456_789), + ), ], }; let chain = TEST_DEFAULT_CHAIN; let (agent, _) = BlockchainAgentWeb3::new( qualified_payables, - 444_555_666, + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, @@ -290,11 +330,13 @@ mod tests { assert_eq!( result, - (increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(444_555_667, chain) - + increase_gas_price_by_margin(444_555_666, chain) - + increase_gas_price_by_margin(500_000_000, chain)) + (rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + 1 + + rpc_gas_price_with_margin_wei + + rpc_gas_price_with_margin_wei + + 456_789) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index ce7c5fa1e..fc3ec1f87 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -601,7 +601,7 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160}; use masq_lib::constants::DEFAULT_MAX_BLOCK_COUNT; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesRawPack, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesWithGasPrice}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt}; impl Handler> for BlockchainBridge { @@ -685,9 +685,7 @@ mod tests { #[test] fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant() { let system = System::new( - " fn handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant( -", - ); + "handles_qualified_payables_msg_in_new_payables_mode_and_sends_response_back_to_accountant"); let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) // Fetching a recommended gas price @@ -734,7 +732,7 @@ mod tests { payables: qualified_payables .clone() .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPricePick { + .map(|payable| QualifiedPayablesBeforeGasPriceSelection { payable, previous_attempt_gas_price_minor_opt: None, }) @@ -764,7 +762,7 @@ mod tests { .into_iter() .map(|payable| QualifiedPayablesWithGasPrice { payable, - gas_price_minor: 0x230000000, + gas_price_minor: increase_gas_price_by_margin(0x230000000, chain), }) .collect(), }; @@ -784,13 +782,11 @@ mod tests { .consuming_wallet_balances(), ConsumingWalletBalances::new(0xAAAA.into(), 0xFFFF.into()) ); - let gas_limit_const_part = - BlockchainInterfaceWeb3::web3_gas_limit_const_part(Chain::PolyMainnet); assert_eq!( blockchain_agent_with_context_msg_actual .agent .estimated_transaction_fee_total(), - todo!() + 1_791_228_995_698_688 ); assert_eq!( blockchain_agent_with_context_msg_actual.response_skeleton_opt, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 9f9400499..ad593448e 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -467,7 +467,7 @@ mod tests { use std::str::FromStr; use web3::transports::Http; use web3::types::{H256, U256}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPricePick, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesWithGasPrice}; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; @@ -871,9 +871,15 @@ mod tests { let account_3 = make_payable_account(56); let raw_qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPricePick::new(account_1.clone(), Some(999_999_999)), - QualifiedPayablesBeforeGasPricePick::new(account_2.clone(), Some(1_000_000_000)), - QualifiedPayablesBeforeGasPricePick::new(account_3.clone(), Some(1_000_000_001)), + QualifiedPayablesBeforeGasPriceSelection::new(account_1.clone(), Some(999_999_999)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_2.clone(), + Some(1_000_000_000), + ), + QualifiedPayablesBeforeGasPriceSelection::new( + account_3.clone(), + Some(1_000_000_001), + ), ], }; let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index cd7821880..f1b2d10a2 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -18,12 +18,15 @@ use crate::blockchain::blockchain_interface::data_structures::{ use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use actix::Recipient; +use bytes::Buf; use futures::Future; use masq_lib::blockchains::chains::Chain; +use masq_lib::constants::WALLET_ADDRESS_LENGTH; use masq_lib::logger::Logger; use secp256k1secrets::SecretKey; use serde_json::Value; use std::fmt::Display; +use std::iter::once; use std::time::SystemTime; use thousands::Separable; use web3::transports::{Batch, Http}; @@ -86,46 +89,62 @@ pub fn merged_output_data( .collect() } -pub fn transmission_log(chain: Chain, accounts: &QualifiedPayablesRipePack) -> String { - todo!() - // let chain_name = chain - // .rec() - // .literal_identifier - // .chars() - // .skip_while(|char| char != &'-') - // .skip(1) - // .collect::(); - // const PAYMENT_VALUE_MAX_LENGTH_INCLUDING_COMMAS: usize = 24; - // let introduction = once(format!( - // "\ - // Paying to creditors...\n\ - // Transactions in the batch:\n\ - // \n\ - // chain: {}\n\ - // \n\ - // {:wallet_address_length$} {: value, - // None => &"NA" - // }; - // format!( - // "{:wallet_address_length$} {: String { + let chain_name = chain.rec().literal_identifier; + let account_count = qualified_payables_pack.payables.len(); + let last_nonce_used = lowest_nonce_used + U256::from(account_count - 1); + let biggest_payable = qualified_payables_pack + .payables + .iter() + .map(|payable_with_gas_price| payable_with_gas_price.payable.balance_wei) + .max() + .unwrap(); + let max_length_as_str = biggest_payable.separate_with_commas().len(); + let payment_wei_label = "[payment wei]"; + let payment_column_width = payment_wei_label.len().max(max_length_as_str); + + let introduction = once(format!( + "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + {:first_column_width$} {}\n\ + {:first_column_width$} {}...{}\n\ + \n\ + {:first_column_width$} {: [u8; 68] { @@ -155,7 +174,8 @@ pub fn sign_transaction( ) -> SignedTransaction { let data = sign_transaction_data(amount, recipient_wallet); let gas_limit = gas_limit(data, chain); - // Warning: If you set gas_price or nonce to None in transaction_parameters, sign_transaction will start making RPC calls which we don't want (Do it at your own risk). + // Warning: If you set gas_price or nonce to None in transaction_parameters, sign_transaction + // will start making RPC calls which we don't want (Do it at your own risk). let transaction_parameters = TransactionParameters { nonce: Some(nonce), to: Some(chain.rec().contract), @@ -288,7 +308,6 @@ pub fn send_payables_within_batch( let hashes_and_paid_amounts_error = hashes_and_paid_amounts.clone(); let hashes_and_paid_amounts_ok = hashes_and_paid_amounts.clone(); - // TODO: We are sending hashes_and_paid_amounts to the Accountant even if the payments fail. new_fingerprints_recipient .try_send(PendingPayableFingerprintSeeds { batch_wide_timestamp: timestamp, @@ -296,7 +315,11 @@ pub fn send_payables_within_batch( }) .expect("Accountant is dead"); - info!(logger, "{}", transmission_log(chain, &accounts)); + info!( + logger, + "{}", + transmission_log(chain, &accounts, pending_nonce) + ); Box::new( web3_batch @@ -481,27 +504,108 @@ mod tests { } #[test] - fn transmission_log_just_works() { - init_test_logging(); - let test_name = "transmission_log_just_works"; - let gas_price = 120; - let logger = Logger::new(test_name); - let amount_1 = gwei_to_wei(900_000_000_u64); + fn transmission_log_is_well_formatted() { + // This test only focuses on the formatting, but there are other tests asserting printing + // this in the logs + + // Case 1 + let payments = [ + gwei_to_wei(900_000_000_u64), + 123_456_789_u128, + gwei_to_wei(33_355_666_u64), + ]; + let pending_nonce = 123456789.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: base-sepolia\n\ + nonces: 123,456,789...123,456,791\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 900,000,000,000,000,000 123,456,789\n\ + 0x0000000000000000000000000000000077353535 123,456,789 234,567,890\n\ + 0x0000000000000000000000000000000077393837 33,355,666,000,000,000 345,678,901\n"; + + test_transmission_log( + 1, + payments, + Chain::BaseSepolia, + pending_nonce, + expected_format, + ); + + // Case 2 + let payments = [ + gwei_to_wei(5_400_u64), + gwei_to_wei(10_000_u64), + 44_444_555_u128, + ]; + let pending_nonce = 100.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: eth-mainnet\n\ + nonces: 100...102\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 5,400,000,000,000 123,456,789\n\ + 0x0000000000000000000000000000000077353535 10,000,000,000,000 234,567,890\n\ + 0x0000000000000000000000000000000077393837 44,444,555 345,678,901\n"; + + test_transmission_log( + 2, + payments, + Chain::EthMainnet, + pending_nonce, + expected_format, + ); + + // Case 3 + let payments = [45_000_888, 1_999_999, 444_444_555]; + let pending_nonce = 1.into(); + let expected_format = "\n\ + Paying creditors\n\ + Transactions:\n\ + \n\ + chain: polygon-mainnet\n\ + nonces: 1...3\n\ + \n\ + [wallet address] [payment wei] [gas price wei]\n\ + 0x0000000000000000000000000000000077313233 45,000,888 123,456,789\n\ + 0x0000000000000000000000000000000077353535 1,999,999 234,567,890\n\ + 0x0000000000000000000000000000000077393837 444,444,555 345,678,901\n"; + + test_transmission_log( + 3, + payments, + Chain::PolyMainnet, + pending_nonce, + expected_format, + ); + } + + fn test_transmission_log( + case: usize, + payments: [u128; 3], + chain: Chain, + pending_nonce: U256, + expected_result: &str, + ) { let account_1 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w123"), - amount_1, + payments[0], None, ); - let amount_2 = 123_456_789_u128; let account_2 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w555"), - amount_2, + payments[1], None, ); - let amount_3 = gwei_to_wei(33_355_666_u64); let account_3 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( make_wallet("w987"), - amount_3, + payments[2], None, ); let accounts_to_process = make_ripe_qualified_payables(vec![ @@ -510,24 +614,12 @@ mod tests { (account_3, 345_678_901), ]); - info!( - logger, - "{}", - transmission_log(TEST_DEFAULT_CHAIN, &accounts_to_process) - ); + let result = transmission_log(chain, &accounts_to_process, pending_nonce); - let log_handler = TestLogHandler::new(); - log_handler.exists_log_containing( - "INFO: transmission_log_just_works: Paying to creditors...\n\ - Transactions in the batch:\n\ - \n\ - gas price: 120 wei\n\ - chain: sepolia\n\ - \n\ - [wallet address] [payment in wei]\n\ - 0x0000000000000000000000000000000077313233 900,000,000,000,000,000\n\ - 0x0000000000000000000000000000000077353535 123,456,789\n\ - 0x0000000000000000000000000000000077393837 33,355,666,000,000,000\n", + assert_eq!( + result, expected_result, + "Test case {}: we expected this format: \"{}\", but it was: \"{}\"", + case, expected_result, result ); } @@ -588,7 +680,7 @@ mod tests { ) } - fn execute_send_payables_test( + fn test_send_payables_within_batch( test_name: &str, accounts: QualifiedPayablesRipePack, expected_result: Result, PayableTransactionError>, @@ -640,7 +732,7 @@ mod tests { ); tlh.exists_log_containing(&format!( "INFO: {test_name}: {}", - transmission_log(chain, &accounts) + transmission_log(chain, &accounts, pending_nonce) )); assert_eq!(result, expected_result); } @@ -674,7 +766,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_works", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]), expected_result, @@ -699,7 +791,7 @@ mod tests { ], }); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_fails_on_submit_batch_call", accounts, expected_result, @@ -749,7 +841,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_all_payments_fail", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), expected_result, @@ -789,7 +881,7 @@ mod tests { }), ]); - execute_send_payables_test( + test_send_payables_within_batch( "send_payables_within_batch_one_payment_works_the_other_fails", make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), expected_result, diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index da5377d6b..3b8214f98 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -10,8 +10,9 @@ use web3::transports::Http; pub(in crate::blockchain) struct BlockchainInterfaceInitializer {} impl BlockchainInterfaceInitializer { - // TODO when we have multiple chains of fundamentally different architectures and are able to switch them, - // this should probably be replaced by a HashMap of distinct interfaces for each chain + // TODO if we ever have multiple chains of fundamentally different architectures and are able + // to switch them, this should probably be replaced by a HashMap of distinct interfaces for + // each chain pub fn initialize_interface( &self, blockchain_service_url: &str, @@ -60,6 +61,9 @@ mod tests { #[test] fn initialize_web3_interface_works() { + // TODO this test should definitely assert on the web3 requests sent to the server, + // that's the best way to verify that this interface belongs to the web3 architecture + // (GH-543) let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .ok_response("0x3B9ACA00".to_string(), 0) // gas_price = 10000000000 @@ -70,7 +74,6 @@ mod tests { ) .ok_response("0x23".to_string(), 1) .start(); - let wallet = make_wallet("123"); let chain = Chain::PolyMainnet; let server_url = &format!("http://{}:{}", &Ipv4Addr::LOCALHOST, port); @@ -82,10 +85,10 @@ mod tests { QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let payable_wallet = make_wallet("payable"); let (blockchain_agent, ripe_qualified_payables) = result - .introduce_blockchain_agent(raw_qualified_payables, payable_wallet) + .introduce_blockchain_agent(raw_qualified_payables, payable_wallet.clone()) .wait() .unwrap(); - assert_eq!(blockchain_agent.consuming_wallet(), &wallet); + assert_eq!(blockchain_agent.consuming_wallet(), &payable_wallet); let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000, chain); let expected_ripe_qualified_payables = QualifiedPayablesRipePack { payables: vec![ @@ -94,7 +97,10 @@ mod tests { ], }; assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); - assert_eq!(blockchain_agent.estimated_transaction_fee_total(), todo!()); + assert_eq!( + blockchain_agent.estimated_transaction_fee_total(), + 190_652_800_000_000 + ); } #[test] From 162a231a78b032f3709bf0b312779fde965a15f3 Mon Sep 17 00:00:00 2001 From: Bert Date: Mon, 16 Jun 2025 22:12:15 +0200 Subject: [PATCH 07/17] GH-638: tests for gas price ceiling confrontations written --- .../src/blockchains/blockchain_records.rs | 48 ++-- masq_lib/src/blockchains/chains.rs | 3 +- .../payable_scanner_extension/msgs.rs | 5 +- .../blockchain/blockchain_agent/agent_web3.rs | 270 ++++++++++++++++-- node/src/blockchain/blockchain_bridge.rs | 2 +- .../blockchain_interface_web3/mod.rs | 55 +++- .../blockchain_interface_web3/utils.rs | 20 +- 7 files changed, 346 insertions(+), 57 deletions(-) diff --git a/masq_lib/src/blockchains/blockchain_records.rs b/masq_lib/src/blockchains/blockchain_records.rs index d45a12da9..56d0092c8 100644 --- a/masq_lib/src/blockchains/blockchain_records.rs +++ b/masq_lib/src/blockchains/blockchain_records.rs @@ -12,12 +12,14 @@ use crate::constants::{ }; use ethereum_types::{Address, H160}; +// TODO these should probably be a static, and dynamic initialization should then also be allowed pub const CHAINS: [BlockchainRecord; 7] = [ BlockchainRecord { self_id: Chain::PolyMainnet, num_chain_id: 137, literal_identifier: POLYGON_MAINNET_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200_000_000_000, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -25,7 +27,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthMainnet, num_chain_id: 1, literal_identifier: ETH_MAINNET_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 100_000_000_000, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -33,7 +36,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::BaseMainnet, num_chain_id: 8453, literal_identifier: BASE_MAINNET_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 50_000_000_000, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -41,7 +45,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::BaseSepolia, num_chain_id: 84532, literal_identifier: BASE_SEPOLIA_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 50_000_000_000, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, }, @@ -49,7 +54,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::PolyAmoy, num_chain_id: 80002, literal_identifier: POLYGON_AMOY_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200_000_000_000, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, }, @@ -57,7 +63,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthRopsten, num_chain_id: 3, literal_identifier: ETH_ROPSTEN_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 100_000_000_000, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, }, @@ -65,7 +72,8 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::Dev, num_chain_id: 2, literal_identifier: DEV_CHAIN_FULL_IDENTIFIER, - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200_000_000_000, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, }, @@ -76,7 +84,8 @@ pub struct BlockchainRecord { pub self_id: Chain, pub num_chain_id: u64, pub literal_identifier: &'static str, - pub gas_price_recommended_margin_percents: u8, + pub gas_price_default_margin_percents: u8, + pub gas_price_safe_ceiling_minor: u128, pub contract: Address, pub contract_creation_block: u64, } @@ -123,7 +132,7 @@ const POLYGON_MAINNET_CONTRACT_ADDRESS: Address = H160([ mod tests { use super::*; use crate::blockchains::chains::chain_from_chain_identifier_opt; - use crate::constants::BASE_MAINNET_CONTRACT_CREATION_BLOCK; + use crate::constants::{BASE_MAINNET_CONTRACT_CREATION_BLOCK, WEIS_IN_GWEI}; use std::collections::HashSet; use std::iter::FromIterator; @@ -203,7 +212,8 @@ mod tests { num_chain_id: 1, self_id: examined_chain, literal_identifier: "eth-mainnet", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 100 * WEIS_IN_GWEI as u128, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -220,7 +230,8 @@ mod tests { num_chain_id: 3, self_id: examined_chain, literal_identifier: "eth-ropsten", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 100 * WEIS_IN_GWEI as u128, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, } @@ -237,7 +248,8 @@ mod tests { num_chain_id: 137, self_id: examined_chain, literal_identifier: "polygon-mainnet", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -254,7 +266,8 @@ mod tests { num_chain_id: 80002, self_id: examined_chain, literal_identifier: "polygon-amoy", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, } @@ -271,7 +284,8 @@ mod tests { num_chain_id: 8453, self_id: examined_chain, literal_identifier: "base-mainnet", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 50 * WEIS_IN_GWEI as u128, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, } @@ -288,7 +302,8 @@ mod tests { num_chain_id: 84532, self_id: examined_chain, literal_identifier: "base-sepolia", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 50 * WEIS_IN_GWEI as u128, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, } @@ -305,7 +320,8 @@ mod tests { num_chain_id: 2, self_id: examined_chain, literal_identifier: "dev", - gas_price_recommended_margin_percents: 30, + gas_price_default_margin_percents: 30, + gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, } diff --git a/masq_lib/src/blockchains/chains.rs b/masq_lib/src/blockchains/chains.rs index 2ac9db03f..e43f58edd 100644 --- a/masq_lib/src/blockchains/chains.rs +++ b/masq_lib/src/blockchains/chains.rs @@ -141,7 +141,8 @@ mod tests { num_chain_id: 0, self_id: Chain::PolyMainnet, literal_identifier: "", - gas_price_recommended_margin_percents: 0, + gas_price_default_margin_percents: 0, + gas_price_safe_ceiling_minor: 0, contract: Default::default(), contract_creation_block: 0, } diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index 8b5f4756c..d077a7cf6 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -56,7 +56,10 @@ pub struct QualifiedPayablesRipePack { impl Into> for QualifiedPayablesRipePack { fn into(self) -> Vec { - todo!() + self.payables + .into_iter() + .map(|qualified_payable| qualified_payable.payable) + .collect() } } diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 288561c81..9fc108857 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -109,13 +109,17 @@ mod tests { QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, }; - use crate::accountant::test_utils::make_payable_account; + use crate::accountant::test_utils::{ + make_payable_account, make_raw_qualified_payables_for_retry_mode, + make_ripe_qualified_payables, + }; use crate::blockchain::blockchain_agent::agent_web3::{ BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::test_utils::make_wallet; + use masq_lib::blockchains::chains::Chain; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use web3::types::U256; @@ -207,21 +211,246 @@ mod tests { chain, ); + let expected_result = { + let gas_price_account_1 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_2 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_3 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 1, chain); + let gas_price_account_4 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_5 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 456_789, chain); + QualifiedPayablesRipePack { + payables: vec![ + QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), + QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), + QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), + QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_4), + QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_5), + ], + } + }; + assert_eq!(ripe_qualified_payables, expected_result); + } + + #[test] + fn new_payables_gas_price_ceiling_test_if_latest_price_is_a_border_value() { + let chain = TEST_DEFAULT_CHAIN; + let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + // This should be the value that would surplus the ceiling just slightly if the margin is applied + let fetched_lastest_gas_price = + ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); + let check_value_wei = increase_gas_price_by_margin(fetched_lastest_gas_price, chain); + + test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + chain, + fetched_lastest_gas_price, + ); + + assert!(check_value_wei > ceiling_gas_price_wei); + } + + #[test] + fn new_payables_gas_price_ceiling_test_if_latest_price_is_a_bit_bigger_even_with_no_margin() { + let chain = TEST_DEFAULT_CHAIN; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + + test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + chain, + ceiling_gas_price_wei + 1, + ); + } + + #[test] + fn new_payables_gas_price_ceiling_test_if_latest_price_is_just_gigantic() { + let chain = TEST_DEFAULT_CHAIN; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + + test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + chain, + 10 * ceiling_gas_price_wei, + ); + } + + fn test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + chain: Chain, + fetched_lastest_gas_price_wei: u128, + ) { + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + let consuming_wallet = make_wallet("efg"); + let consuming_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: Default::default(), + masq_token_balance_in_minor_units: Default::default(), + }; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let qualified_payables = + QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( + qualified_payables, + fetched_lastest_gas_price_wei, + 77_777, + consuming_wallet, + consuming_wallet_balances, + chain, + ); + let expected_result = QualifiedPayablesRipePack { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, rpc_gas_price_with_margin_wei), - QualifiedPayablesWithGasPrice::new(account_2, rpc_gas_price_with_margin_wei), - QualifiedPayablesWithGasPrice::new(account_3, rpc_gas_price_with_margin_wei + 1), - QualifiedPayablesWithGasPrice::new(account_4, rpc_gas_price_with_margin_wei), - QualifiedPayablesWithGasPrice::new( - account_5, - rpc_gas_price_with_margin_wei + 456_789, - ), + QualifiedPayablesWithGasPrice::new(account_1, ceiling_gas_price_wei), + QualifiedPayablesWithGasPrice::new(account_2, ceiling_gas_price_wei), ], }; assert_eq!(ripe_qualified_payables, expected_result); } + #[test] + fn retry_payables_gas_price_ceiling_test_of_border_value_if_the_latest_fetch_being_bigger() { + let chain = TEST_DEFAULT_CHAIN; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + // This should be the value that would surplus the ceiling just slightly if the margin is applied + let fetched_lastest_gas_price = + ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); + let check_value_wei = increase_gas_price_by_margin(fetched_lastest_gas_price, chain); + let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), fetched_lastest_gas_price - 1), + (account_2.clone(), fetched_lastest_gas_price - 2), + ]); + + test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain, + fetched_lastest_gas_price, + raw_qualified_payables, + ); + + assert!(check_value_wei > ceiling_gas_price_wei); + } + + #[test] + fn retry_payables_gas_price_ceiling_test_of_border_value_if_the_previous_attempt_being_bigger() + { + let chain = TEST_DEFAULT_CHAIN; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + // This should be the value that would surplus the ceiling just slightly if the margin is applied + let border_gas_price_wei = + ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); + let fetched_gas_price_wei = border_gas_price_wei - 1; + let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei, chain); + let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), border_gas_price_wei), + (account_2.clone(), border_gas_price_wei), + ]); + + test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain, + fetched_gas_price_wei, + raw_qualified_payables, + ); + + assert!(check_value_wei > ceiling_gas_price_wei); + } + + #[test] + fn retry_payables_gas_price_ceiling_test_of_big_value_if_the_latest_fetch_being_bigger() { + let chain = TEST_DEFAULT_CHAIN; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + let fetched_gas_price_wei = ceiling_gas_price_wei - 1; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), fetched_gas_price_wei - 1), + (account_2.clone(), fetched_gas_price_wei - 2), + ]); + + test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain, + fetched_gas_price_wei, + raw_qualified_payables, + ); + } + + #[test] + fn retry_payables_gas_price_ceiling_test_of_big_value_if_the_previous_attempt_being_bigger() { + let chain = TEST_DEFAULT_CHAIN; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), ceiling_gas_price_wei - 1), + (account_2.clone(), ceiling_gas_price_wei - 2), + ]); + + test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain, + ceiling_gas_price_wei - 3, + raw_qualified_payables, + ); + } + + #[test] + fn retry_payables_gas_price_ceiling_test_of_giant_value_for_the_latest_fetch() { + let chain = TEST_DEFAULT_CHAIN; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + let fetched_gas_price_wei = 10 * ceiling_gas_price_wei; + let account_1 = make_payable_account(12); + let account_2 = make_payable_account(34); + // The values can never go above the ceiling, therefore, we can assume only values even or + // smaller than that in the previous attempts + let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), ceiling_gas_price_wei), + (account_2.clone(), ceiling_gas_price_wei), + ]); + + test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain, + fetched_gas_price_wei, + raw_qualified_payables, + ); + } + + fn test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + chain: Chain, + fetched_lastest_gas_price_wei: u128, + qualified_payables: QualifiedPayablesRawPack, + ) { + let consuming_wallet = make_wallet("efg"); + let consuming_wallet_balances = ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: Default::default(), + masq_token_balance_in_minor_units: Default::default(), + }; + let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; + let expected_ripe_payable = QualifiedPayablesRipePack { + payables: qualified_payables + .payables + .clone() + .into_iter() + .map(|payable| { + QualifiedPayablesWithGasPrice::new(payable.payable, ceiling_gas_price_wei) + }) + .collect(), + }; + + let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( + qualified_payables, + fetched_lastest_gas_price_wei, + 77_777, + consuming_wallet, + consuming_wallet_balances, + chain, + ); + + assert_eq!(ripe_qualified_payables, expected_ripe_payable); + } + #[test] fn returns_correct_non_computed_values() { let gas_limit_const_part = 44_000; @@ -328,15 +557,24 @@ mod tests { let result = agent.estimated_transaction_fee_total(); + let gas_price_account_1 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_2 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_3 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 1, chain); + let gas_price_account_4 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_5 = + increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 456_789, chain); assert_eq!( result, - (rpc_gas_price_with_margin_wei - + rpc_gas_price_with_margin_wei - + rpc_gas_price_with_margin_wei - + 1 - + rpc_gas_price_with_margin_wei - + rpc_gas_price_with_margin_wei - + 456_789) + (gas_price_account_1 + + gas_price_account_2 + + gas_price_account_3 + + gas_price_account_3 + + gas_price_account_4 + + gas_price_account_5) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index fc3ec1f87..b6e260aad 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -539,7 +539,7 @@ struct PendingTxInfo { } pub fn increase_gas_price_by_margin(gas_price: u128, chain: Chain) -> u128 { - (gas_price * (100 + chain.rec().gas_price_recommended_margin_percents as u128)) / 100 + (gas_price * (100 + chain.rec().gas_price_default_margin_percents as u128)) / 100 } pub struct BlockchainBridgeSubsFactoryReal {} diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index ad593448e..4a8c0e3ae 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -843,20 +843,32 @@ mod tests { #[test] fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_new_payables_mode() { + let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 + let gas_price_wei_from_rpc_u128_wei = + u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); + let gas_price_wei_from_rpc_u128_wei_with_margin = + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); let expected_ripe_qualified_payables = QualifiedPayablesRipePack { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, 1_000_000_000), - QualifiedPayablesWithGasPrice::new(account_2, 1_000_000_000), + QualifiedPayablesWithGasPrice::new( + account_1, + gas_price_wei_from_rpc_u128_wei_with_margin, + ), + QualifiedPayablesWithGasPrice::new( + account_2, + gas_price_wei_from_rpc_u128_wei_with_margin, + ), ], }; - let expected_estimated_transaction_fee = todo!("fix me"); + let expected_estimated_transaction_fee = 190_652_800_000_000; blockchain_interface_web3_can_introduce_blockchain_agent( + chain, raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, @@ -866,33 +878,52 @@ mod tests { #[test] fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_retry_payables_mode() { + let chain = TEST_DEFAULT_CHAIN; + let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 + let gas_price_wei_from_rpc_u128_wei = + u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); + let gas_price_wei_from_rpc_u128_wei_with_margin = + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); let raw_qualified_payables = QualifiedPayablesRawPack { payables: vec![ - QualifiedPayablesBeforeGasPriceSelection::new(account_1.clone(), Some(999_999_999)), + QualifiedPayablesBeforeGasPriceSelection::new( + account_1.clone(), + Some(gas_price_wei_from_rpc_u128_wei_with_margin - 1), + ), QualifiedPayablesBeforeGasPriceSelection::new( account_2.clone(), - Some(1_000_000_000), + Some(gas_price_wei_from_rpc_u128_wei_with_margin), ), QualifiedPayablesBeforeGasPriceSelection::new( account_3.clone(), - Some(1_000_000_001), + Some(gas_price_wei_from_rpc_u128_wei_with_margin + 1), ), ], }; - let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 + let expected_ripe_qualified_payables = QualifiedPayablesRipePack { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, 1_000_000_000), - QualifiedPayablesWithGasPrice::new(account_2, 1_000_000_000), - QualifiedPayablesWithGasPrice::new(account_3, 1_000_000_001), + QualifiedPayablesWithGasPrice::new( + account_1, + gas_price_wei_from_rpc_u128_wei_with_margin, + ), + QualifiedPayablesWithGasPrice::new( + account_2, + gas_price_wei_from_rpc_u128_wei_with_margin, + ), + QualifiedPayablesWithGasPrice::new( + account_3, + gas_price_wei_from_rpc_u128_wei_with_margin + 1, + ), ], }; - let expected_estimated_transaction_fee = todo!("fix me"); + let expected_estimated_transaction_fee = 285_979_200_073_328; blockchain_interface_web3_can_introduce_blockchain_agent( + chain, raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, @@ -901,6 +932,7 @@ mod tests { } fn blockchain_interface_web3_can_introduce_blockchain_agent( + chain: Chain, raw_qualified_payables: QualifiedPayablesRawPack, gas_price_wei_from_rpc_hex: &str, expected_ripe_qualified_payables: QualifiedPayablesRipePack, @@ -918,7 +950,6 @@ mod tests { 0, ) .start(); - let chain = Chain::PolyMainnet; let wallet = make_wallet("abc"); let subject = make_blockchain_interface_web3(port); diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index f1b2d10a2..6c25239f6 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -487,14 +487,14 @@ mod tests { vec![ HashAndAmount { hash: H256::from_str( - "94881436a9c89f48b01651ff491c69e97089daf71ab8cfb240243d7ecf9b38b2" + "374b7d023f4ac7d99e612d82beda494b0747116e9b9dc975b33b865f331ee934" ) .unwrap(), amount: 1000000000 }, HashAndAmount { hash: H256::from_str( - "3811874d2b73cecd51234c94af46bcce918d0cb4de7d946c01d7da606fe761b5" + "5708afd876bc2573f9db984ec6d0e7f8ef222dd9f115643c9b9056d8bef8bbd9" ) .unwrap(), amount: 2000000000 @@ -753,14 +753,14 @@ mod tests { Correct(PendingPayable { recipient_wallet: account_1.wallet.clone(), hash: H256::from_str( - "35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4", + "6e7fa351eef640186f76c629cb74106b3082c8f8a1a9df75ff02fe5bfd4dd1a2", ) .unwrap(), }), Correct(PendingPayable { recipient_wallet: account_2.wallet.clone(), hash: H256::from_str( - "7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3", + "b67a61b29c0c48d8b63a64fda73b3247e8e2af68082c710325675d4911e113d4", ) .unwrap(), }), @@ -786,8 +786,8 @@ mod tests { let expected_result = Err(Sending { msg: format!("Transport error: Error(Connect, Os {{ code: {}, kind: ConnectionRefused, message: {:?} }})", os_code, os_msg).to_string(), hashes: vec![ - H256::from_str("35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4").unwrap(), - H256::from_str("7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3").unwrap() + H256::from_str("ec7ac48060b75889f949f5e8d301b386198218e60e2635c95cb6b0934a0887ea").unwrap(), + H256::from_str("c2d5059db0ec2fbf15f83d9157eeb0d793d6242de5e73a607935fb5660e7e925").unwrap() ], }); @@ -828,7 +828,7 @@ mod tests { data: None, }), recipient_wallet: account_1.wallet.clone(), - hash: H256::from_str("35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4").unwrap(), + hash: H256::from_str("6e7fa351eef640186f76c629cb74106b3082c8f8a1a9df75ff02fe5bfd4dd1a2").unwrap(), }), Failed(RpcPayableFailure { rpc_error: Rpc(Error { @@ -837,7 +837,7 @@ mod tests { data: None, }), recipient_wallet: account_2.wallet.clone(), - hash: H256::from_str("7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3").unwrap(), + hash: H256::from_str("ca6ad0a60daeaf31cbca7ce6e499c0f4ff5870564c5e845de11834f1fc05bd4e").unwrap(), }), ]); @@ -868,7 +868,7 @@ mod tests { let expected_result = Ok(vec![ Correct(PendingPayable { recipient_wallet: account_1.wallet.clone(), - hash: H256::from_str("35f42b260f090a559e8b456718d9c91a9da0f234ed0a129b9d5c4813b6615af4").unwrap(), + hash: H256::from_str("6e7fa351eef640186f76c629cb74106b3082c8f8a1a9df75ff02fe5bfd4dd1a2").unwrap(), }), Failed(RpcPayableFailure { rpc_error: Rpc(Error { @@ -877,7 +877,7 @@ mod tests { data: None, }), recipient_wallet: account_2.wallet.clone(), - hash: H256::from_str("7f3221109e4f1de8ba1f7cd358aab340ecca872a1456cb1b4f59ca33d3e22ee3").unwrap(), + hash: H256::from_str("ca6ad0a60daeaf31cbca7ce6e499c0f4ff5870564c5e845de11834f1fc05bd4e").unwrap(), }), ]); From ba08ac0be9bd714db4efc7778eeb299be6add85a Mon Sep 17 00:00:00 2001 From: Bert Date: Wed, 18 Jun 2025 13:44:46 +0200 Subject: [PATCH 08/17] GH-638: single test fixed --- .../blockchain/blockchain_agent/agent_web3.rs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 9fc108857..eeb5e7781 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -49,9 +49,6 @@ impl BlockchainAgentWeb3 { consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, ) -> (Box, QualifiedPayablesRipePack) { - let current_gas_price_with_margin = - increase_gas_price_by_margin(latest_gas_price_wei, chain); - let fold_init = (QualifiedPayablesRipePack { payables: vec![] }, 0); let (ripe_qualified_payables, gas_price_aggregated_wei) = raw_qualified_payables.payables.into_iter().fold( @@ -59,8 +56,9 @@ impl BlockchainAgentWeb3 { |(ripe_qualified_payables, gas_price_aggregated_wei), raw_q_payable| { Self::fold_guts( (ripe_qualified_payables, gas_price_aggregated_wei), + chain, raw_q_payable, - current_gas_price_with_margin, + latest_gas_price_wei, ) }, ); @@ -83,6 +81,7 @@ impl BlockchainAgentWeb3 { QualifiedPayablesRipePack, u128, ), + chain: Chain, raw_q_payable: QualifiedPayablesBeforeGasPriceSelection, current_gas_price_with_margin: u128, ) -> (QualifiedPayablesRipePack, u128) { @@ -93,12 +92,16 @@ impl BlockchainAgentWeb3 { } Some(_) => current_gas_price_with_margin, }; - let ripe_qualified_payable = - QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, selected_gas_price_wei); + let increased_by_margin_gas_price_wei = + increase_gas_price_by_margin(selected_gas_price_wei, chain); + let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new( + raw_q_payable.payable, + increased_by_margin_gas_price_wei, + ); ripe_qualified_payables .payables .push(ripe_qualified_payable); - gas_price_aggregated_wei += selected_gas_price_wei; + gas_price_aggregated_wei += increased_by_margin_gas_price_wei; (ripe_qualified_payables, gas_price_aggregated_wei) } } @@ -169,7 +172,6 @@ mod tests { }; let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; - let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -179,23 +181,23 @@ mod tests { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), - Some(rpc_gas_price_with_margin_wei - 1), + Some(rpc_gas_price_wei - 1), ), QualifiedPayablesBeforeGasPriceSelection::new( account_2.clone(), - Some(rpc_gas_price_with_margin_wei), + Some(rpc_gas_price_wei), ), QualifiedPayablesBeforeGasPriceSelection::new( account_3.clone(), - Some(rpc_gas_price_with_margin_wei + 1), + Some(rpc_gas_price_wei + 1), ), QualifiedPayablesBeforeGasPriceSelection::new( account_4.clone(), - Some(rpc_gas_price_with_margin_wei - 123_456), + Some(rpc_gas_price_wei - 123_456), ), QualifiedPayablesBeforeGasPriceSelection::new( account_5.clone(), - Some(rpc_gas_price_with_margin_wei + 456_789), + Some(rpc_gas_price_wei + 456_789), ), ], }; @@ -212,16 +214,12 @@ mod tests { ); let expected_result = { - let gas_price_account_1 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); - let gas_price_account_2 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); - let gas_price_account_3 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 1, chain); - let gas_price_account_4 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + let gas_price_account_1 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); + let gas_price_account_2 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); + let gas_price_account_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); + let gas_price_account_4 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let gas_price_account_5 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 456_789, chain); + increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); QualifiedPayablesRipePack { payables: vec![ QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), From 49619ed647617fe3c90a2a1f266ef316a3a63692 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Fri, 20 Jun 2025 07:08:21 +0200 Subject: [PATCH 09/17] GH-638: tests full - all and fixed --- node/src/accountant/scanners/mod.rs | 3 +- .../blockchain/blockchain_agent/agent_web3.rs | 75 +++++++++++-------- node/src/blockchain/blockchain_bridge.rs | 12 +-- .../blockchain_interface_web3/mod.rs | 43 ++++++----- 4 files changed, 74 insertions(+), 59 deletions(-) diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 92faaad76..8f46a01a5 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -1737,11 +1737,10 @@ mod tests { #[test] fn retry_payable_scanner_can_initiate_a_scan() { - todo!("this must be set up under the other card"); + todo!("this must be set up under GH-605"); // TODO make sure the QualifiedPayableRawPack will express the difference from // the NewPayable scanner: The QualifiedPayablesBeforeGasPriceSelection needs to carry // `Some()` instead of None - // init_test_logging(); // let test_name = "retry_payable_scanner_can_initiate_a_scan"; // let consuming_wallet = make_paying_wallet(b"consuming wallet"); diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index eeb5e7781..e23f89d47 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -83,25 +83,36 @@ impl BlockchainAgentWeb3 { ), chain: Chain, raw_q_payable: QualifiedPayablesBeforeGasPriceSelection, - current_gas_price_with_margin: u128, + latest_gas_price: u128, ) -> (QualifiedPayablesRipePack, u128) { let selected_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { - None => current_gas_price_with_margin, - Some(previous_price) if current_gas_price_with_margin < previous_price => { + None => latest_gas_price, + Some(previous_price) if latest_gas_price < previous_price => { previous_price } - Some(_) => current_gas_price_with_margin, + Some(_) => latest_gas_price, }; - let increased_by_margin_gas_price_wei = + + let gas_price_increased_by_margin_wei = increase_gas_price_by_margin(selected_gas_price_wei, chain); + + let price_ceiling = chain.rec().gas_price_safe_ceiling_minor; + let checked_gas_price_wei = if gas_price_increased_by_margin_wei > price_ceiling { + price_ceiling + } else { + gas_price_increased_by_margin_wei + }; + let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new( raw_q_payable.payable, - increased_by_margin_gas_price_wei, + checked_gas_price_wei, ); + ripe_qualified_payables .payables .push(ripe_qualified_payable); - gas_price_aggregated_wei += increased_by_margin_gas_price_wei; + gas_price_aggregated_wei += checked_gas_price_wei; + (ripe_qualified_payables, gas_price_aggregated_wei) } } @@ -238,17 +249,19 @@ mod tests { let chain = TEST_DEFAULT_CHAIN; let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; - // This should be the value that would surplus the ceiling just slightly if the margin is applied - let fetched_lastest_gas_price = - ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); - let check_value_wei = increase_gas_price_by_margin(fetched_lastest_gas_price, chain); + // This should be the value that would surplus the ceiling just slightly if the margin is + // applied. + // Adding just 1 didn't work, therefore 2 + let fetched_latest_gas_price_wei = + ((ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100)) + 2; + let check_value_wei = increase_gas_price_by_margin(fetched_latest_gas_price_wei, chain); test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( chain, - fetched_lastest_gas_price, + fetched_latest_gas_price_wei, ); - assert!(check_value_wei > ceiling_gas_price_wei); + assert!(check_value_wei > ceiling_gas_price_wei, "should be {} > {} but isn't", check_value_wei, ceiling_gas_price_wei); } #[test] @@ -275,7 +288,7 @@ mod tests { fn test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( chain: Chain, - fetched_lastest_gas_price_wei: u128, + fetched_latest_gas_price_wei: u128, ) { let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let consuming_wallet = make_wallet("efg"); @@ -289,7 +302,7 @@ mod tests { QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( qualified_payables, - fetched_lastest_gas_price_wei, + fetched_latest_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, @@ -312,9 +325,11 @@ mod tests { let account_2 = make_payable_account(34); let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; - // This should be the value that would surplus the ceiling just slightly if the margin is applied + // This should be the value that would surplus the ceiling just slightly if the margin is + // applied. + // Adding just 1 didn't work, therefore 2 let fetched_lastest_gas_price = - ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); + (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; let check_value_wei = increase_gas_price_by_margin(fetched_lastest_gas_price, chain); let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ (account_1.clone(), fetched_lastest_gas_price - 1), @@ -327,7 +342,7 @@ mod tests { raw_qualified_payables, ); - assert!(check_value_wei > ceiling_gas_price_wei); + assert!(check_value_wei > ceiling_gas_price_wei, "should be {} > {} but isn't", check_value_wei, ceiling_gas_price_wei); } #[test] @@ -340,7 +355,7 @@ mod tests { let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; // This should be the value that would surplus the ceiling just slightly if the margin is applied let border_gas_price_wei = - ((ceiling_gas_price_wei + 1) * 100) / (default_gas_price_margin_percents as u128 + 100); + (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; let fetched_gas_price_wei = border_gas_price_wei - 1; let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei, chain); let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ @@ -513,7 +528,6 @@ mod tests { }; let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; - let rpc_gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -523,23 +537,23 @@ mod tests { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), - Some(rpc_gas_price_with_margin_wei - 1), + Some(rpc_gas_price_wei - 1), ), QualifiedPayablesBeforeGasPriceSelection::new( account_2.clone(), - Some(rpc_gas_price_with_margin_wei), + Some(rpc_gas_price_wei), ), QualifiedPayablesBeforeGasPriceSelection::new( account_3.clone(), - Some(rpc_gas_price_with_margin_wei + 1), + Some(rpc_gas_price_wei + 1), ), QualifiedPayablesBeforeGasPriceSelection::new( account_4.clone(), - Some(rpc_gas_price_with_margin_wei - 123_456), + Some(rpc_gas_price_wei - 123_456), ), QualifiedPayablesBeforeGasPriceSelection::new( account_5.clone(), - Some(rpc_gas_price_with_margin_wei + 456_789), + Some(rpc_gas_price_wei + 456_789), ), ], }; @@ -556,21 +570,20 @@ mod tests { let result = agent.estimated_transaction_fee_total(); let gas_price_account_1 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + increase_gas_price_by_margin(rpc_gas_price_wei, chain); let gas_price_account_2 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + increase_gas_price_by_margin(rpc_gas_price_wei, chain); let gas_price_account_3 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 1, chain); + increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); let gas_price_account_4 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei, chain); + increase_gas_price_by_margin(rpc_gas_price_wei, chain); let gas_price_account_5 = - increase_gas_price_by_margin(rpc_gas_price_with_margin_wei + 456_789, chain); + increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); assert_eq!( result, (gas_price_account_1 + gas_price_account_2 + gas_price_account_3 - + gas_price_account_3 + gas_price_account_4 + gas_price_account_5) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index b6e260aad..eb1f0bad0 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -924,7 +924,7 @@ mod tests { payment_procedure_result: Ok(vec![Correct(PendingPayable { recipient_wallet: account.wallet, hash: H256::from_str( - "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" + "81d20df32920161727cd20e375e53c2f9df40fd80256a236fb39e444c999fb6c" ) .unwrap() })]), @@ -940,7 +940,7 @@ mod tests { pending_payable_fingerprint_seeds_msg.hashes_and_balances, vec![HashAndAmount { hash: H256::from_str( - "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" + "81d20df32920161727cd20e375e53c2f9df40fd80256a236fb39e444c999fb6c" ) .unwrap(), amount: account.balance_wei @@ -1019,7 +1019,7 @@ mod tests { pending_payable_fingerprint_seeds_msg.hashes_and_balances, vec![HashAndAmount { hash: H256::from_str( - "36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" + "81d20df32920161727cd20e375e53c2f9df40fd80256a236fb39e444c999fb6c" ) .unwrap(), amount: account.balance_wei @@ -1034,7 +1034,7 @@ mod tests { context_id: 4321 }), msg: format!( - "ReportAccountsPayable: Sending phase: \"Transport error: Error(IncompleteMessage)\". Signed and hashed transactions: 0x36e9d7cdd657181317dd461192d537d9944c57a51ee950607de5a618b00e57a1" + "ReportAccountsPayable: Sending phase: \"Transport error: Error(IncompleteMessage)\". Signed and hashed transactions: 0x81d20df32920161727cd20e375e53c2f9df40fd80256a236fb39e444c999fb6c" ) } ); @@ -1090,7 +1090,7 @@ mod tests { Correct(PendingPayable { recipient_wallet: accounts_1.wallet, hash: H256::from_str( - "cc73f3d5fe9fc3dac28b510ddeb157b0f8030b201e809014967396cdf365488a" + "c0756e8da662cee896ed979456c77931668b7f8456b9f978fc3305671f8f82ad" ) .unwrap() }) @@ -1100,7 +1100,7 @@ mod tests { Correct(PendingPayable { recipient_wallet: accounts_2.wallet, hash: H256::from_str( - "891d9ffa838aedc0bb2f6f7e9737128ce98bb33d07b4c8aa5645871e20d6cd13" + "9ba19f88ce43297d700b1f57ed8bc6274d01a5c366b78dd05167f9874c867ba0" ) .unwrap() }) diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 4a8c0e3ae..860577619 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -882,8 +882,6 @@ mod tests { let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 let gas_price_wei_from_rpc_u128_wei = u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); - let gas_price_wei_from_rpc_u128_wei_with_margin = - increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); @@ -891,34 +889,39 @@ mod tests { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), - Some(gas_price_wei_from_rpc_u128_wei_with_margin - 1), + Some(gas_price_wei_from_rpc_u128_wei - 1), ), QualifiedPayablesBeforeGasPriceSelection::new( account_2.clone(), - Some(gas_price_wei_from_rpc_u128_wei_with_margin), + Some(gas_price_wei_from_rpc_u128_wei), ), QualifiedPayablesBeforeGasPriceSelection::new( account_3.clone(), - Some(gas_price_wei_from_rpc_u128_wei_with_margin + 1), + Some(gas_price_wei_from_rpc_u128_wei + 1), ), ], }; - let expected_ripe_qualified_payables = QualifiedPayablesRipePack { - payables: vec![ - QualifiedPayablesWithGasPrice::new( - account_1, - gas_price_wei_from_rpc_u128_wei_with_margin, - ), - QualifiedPayablesWithGasPrice::new( - account_2, - gas_price_wei_from_rpc_u128_wei_with_margin, - ), - QualifiedPayablesWithGasPrice::new( - account_3, - gas_price_wei_from_rpc_u128_wei_with_margin + 1, - ), - ], + let expected_ripe_qualified_payables = { + let gas_price_account_1 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); + let gas_price_account_2 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); + let gas_price_account_3 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1, chain); + QualifiedPayablesRipePack { + payables: vec![ + QualifiedPayablesWithGasPrice::new( + account_1, + gas_price_account_1, + ), + QualifiedPayablesWithGasPrice::new( + account_2, + gas_price_account_2, + ), + QualifiedPayablesWithGasPrice::new( + account_3, + gas_price_account_3, + ), + ], + } }; let expected_estimated_transaction_fee = 285_979_200_073_328; From eb88d7baf81f4f8d1f67d658d615e88d409ad354 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Fri, 20 Jun 2025 07:57:53 +0200 Subject: [PATCH 10/17] GH-638: lint and formatting --- .../payable_scanner_extension/msgs.rs | 1 - .../payable_scanner_extension/test_utils.rs | 4 +- .../blockchain/blockchain_agent/agent_null.rs | 8 +--- .../blockchain/blockchain_agent/agent_web3.rs | 42 +++++++++---------- node/src/blockchain/blockchain_agent/mod.rs | 4 +- node/src/blockchain/blockchain_bridge.rs | 2 - .../blockchain_interface_web3/mod.rs | 37 ++++++---------- .../blockchain_interface_web3/utils.rs | 4 -- .../blockchain/blockchain_interface/mod.rs | 1 - .../blockchain_interface_initializer.rs | 1 - node/src/blockchain/test_utils.rs | 5 +-- node/src/sub_lib/blockchain_bridge.rs | 23 +--------- 12 files changed, 39 insertions(+), 93 deletions(-) diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index d077a7cf6..9aeaecd0a 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -5,7 +5,6 @@ use crate::accountant::{ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::sub_lib::wallet::Wallet; use actix::Message; -use std::collections::{HashMap, HashSet}; use std::fmt::Debug; #[derive(Debug, Message, PartialEq, Eq, Clone)] diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index 2027a9f6e..c28753c28 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -3,14 +3,12 @@ #![cfg(test)] use crate::blockchain::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use crate::test_utils::unshared_test_utils::arbitrary_id_stamp::ArbitraryIdStamp; use crate::{arbitrary_id_stamp_in_trait_impl, set_arbitrary_id_stamp_in_mock_impl}; use masq_lib::blockchains::chains::Chain; use std::cell::RefCell; -use std::collections::HashMap; -use web3::types::Address; pub struct BlockchainAgentMock { consuming_wallet_balances_results: RefCell>, diff --git a/node/src/blockchain/blockchain_agent/agent_null.rs b/node/src/blockchain/blockchain_agent/agent_null.rs index 1024febec..b1fdf1bb8 100644 --- a/node/src/blockchain/blockchain_agent/agent_null.rs +++ b/node/src/blockchain/blockchain_agent/agent_null.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::blockchain::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use ethereum_types::U256; use masq_lib::blockchains::chains::Chain; @@ -71,11 +71,7 @@ impl Default for BlockchainAgentNull { #[cfg(test)] mod tests { - use std::collections::HashMap; - - use crate::sub_lib::blockchain_bridge::{ - ConsumingWalletBalances, QualifiedPayableGasPriceSetup, - }; + use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use crate::blockchain::blockchain_agent::agent_null::BlockchainAgentNull; diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index e23f89d47..a6ed9ce79 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -87,9 +87,7 @@ impl BlockchainAgentWeb3 { ) -> (QualifiedPayablesRipePack, u128) { let selected_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { None => latest_gas_price, - Some(previous_price) if latest_gas_price < previous_price => { - previous_price - } + Some(previous_price) if latest_gas_price < previous_price => previous_price, Some(_) => latest_gas_price, }; @@ -103,10 +101,8 @@ impl BlockchainAgentWeb3 { gas_price_increased_by_margin_wei }; - let ripe_qualified_payable = QualifiedPayablesWithGasPrice::new( - raw_q_payable.payable, - checked_gas_price_wei, - ); + let ripe_qualified_payable = + QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, checked_gas_price_wei); ripe_qualified_payables .payables @@ -125,7 +121,6 @@ mod tests { }; use crate::accountant::test_utils::{ make_payable_account, make_raw_qualified_payables_for_retry_mode, - make_ripe_qualified_payables, }; use crate::blockchain::blockchain_agent::agent_web3::{ BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, @@ -213,7 +208,6 @@ mod tests { ], }; let gas_price_from_rpc = 444_555_666; - let chain = TEST_DEFAULT_CHAIN; let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( qualified_payables, @@ -261,7 +255,12 @@ mod tests { fetched_latest_gas_price_wei, ); - assert!(check_value_wei > ceiling_gas_price_wei, "should be {} > {} but isn't", check_value_wei, ceiling_gas_price_wei); + assert!( + check_value_wei > ceiling_gas_price_wei, + "should be {} > {} but isn't", + check_value_wei, + ceiling_gas_price_wei + ); } #[test] @@ -342,7 +341,12 @@ mod tests { raw_qualified_payables, ); - assert!(check_value_wei > ceiling_gas_price_wei, "should be {} > {} but isn't", check_value_wei, ceiling_gas_price_wei); + assert!( + check_value_wei > ceiling_gas_price_wei, + "should be {} > {} but isn't", + check_value_wei, + ceiling_gas_price_wei + ); } #[test] @@ -557,7 +561,6 @@ mod tests { ), ], }; - let chain = TEST_DEFAULT_CHAIN; let (agent, _) = BlockchainAgentWeb3::new( qualified_payables, rpc_gas_price_wei, @@ -569,16 +572,11 @@ mod tests { let result = agent.estimated_transaction_fee_total(); - let gas_price_account_1 = - increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_2 = - increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_3 = - increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); - let gas_price_account_4 = - increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_5 = - increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); + let gas_price_account_1 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); + let gas_price_account_2 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); + let gas_price_account_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); + let gas_price_account_4 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); + let gas_price_account_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); assert_eq!( result, (gas_price_account_1 diff --git a/node/src/blockchain/blockchain_agent/mod.rs b/node/src/blockchain/blockchain_agent/mod.rs index 13725bf0c..d6c3b46db 100644 --- a/node/src/blockchain/blockchain_agent/mod.rs +++ b/node/src/blockchain/blockchain_agent/mod.rs @@ -3,11 +3,9 @@ pub mod agent_null; pub mod agent_web3; use crate::arbitrary_id_stamp_in_trait; -use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, QualifiedPayableGasPriceSetup}; +use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use masq_lib::blockchains::chains::Chain; -use std::collections::HashMap; -use web3::types::Address; // Table of chains by // // a) adoption of the fee market (variations on "gas price") diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index eb1f0bad0..11eebe1e3 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -43,7 +43,6 @@ use std::time::SystemTime; use ethabi::Hash; use web3::types::H256; use masq_lib::messages::ScanType; -use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionReceiptResult, TxStatus}; @@ -558,7 +557,6 @@ mod tests { use crate::accountant::db_access_objects::utils::from_unix_timestamp; use crate::accountant::scanners::payable_scanner_extension::test_utils::BlockchainAgentMock; use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint, make_ripe_qualified_payables}; - use crate::blockchain::blockchain_interface::blockchain_interface_web3::{BlockchainInterfaceWeb3}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError::TransactionID; use crate::blockchain::blockchain_interface::data_structures::errors::{ BlockchainAgentBuildError, PayableTransactionError, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 860577619..134fc1807 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -4,7 +4,6 @@ pub mod lower_level_interface_web3; mod utils; use std::cmp::PartialEq; -use std::collections::HashMap; use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainError, PayableTransactionError}; use crate::blockchain::blockchain_interface::data_structures::{BlockchainTransaction, ProcessedPayableFallible}; use crate::blockchain::blockchain_interface::lower_level_interface::LowBlockchainInt; @@ -21,7 +20,6 @@ use actix::Recipient; use ethereum_types::U64; use web3::transports::{EventLoopHandle, Http}; use web3::types::{Address, Log, H256, U256, FilterBuilder, TransactionReceipt, BlockNumber}; -use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; @@ -867,8 +865,7 @@ mod tests { }; let expected_estimated_transaction_fee = 190_652_800_000_000; - blockchain_interface_web3_can_introduce_blockchain_agent( - chain, + test_blockchain_interface_web3_can_introduce_blockchain_agent( raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, @@ -903,30 +900,23 @@ mod tests { }; let expected_ripe_qualified_payables = { - let gas_price_account_1 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); - let gas_price_account_2 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); - let gas_price_account_3 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1, chain); - QualifiedPayablesRipePack { + let gas_price_account_1 = + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); + let gas_price_account_2 = + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); + let gas_price_account_3 = + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1, chain); + QualifiedPayablesRipePack { payables: vec![ - QualifiedPayablesWithGasPrice::new( - account_1, - gas_price_account_1, - ), - QualifiedPayablesWithGasPrice::new( - account_2, - gas_price_account_2, - ), - QualifiedPayablesWithGasPrice::new( - account_3, - gas_price_account_3, - ), + QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), + QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), + QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), ], } }; let expected_estimated_transaction_fee = 285_979_200_073_328; - blockchain_interface_web3_can_introduce_blockchain_agent( - chain, + test_blockchain_interface_web3_can_introduce_blockchain_agent( raw_qualified_payables, gas_price_wei_from_rpc_hex, expected_ripe_qualified_payables, @@ -934,8 +924,7 @@ mod tests { ); } - fn blockchain_interface_web3_can_introduce_blockchain_agent( - chain: Chain, + fn test_blockchain_interface_web3_can_introduce_blockchain_agent( raw_qualified_payables: QualifiedPayablesRawPack, gas_price_wei_from_rpc_hex: &str, expected_ripe_qualified_payables: QualifiedPayablesRipePack, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index 6c25239f6..ac0447ee1 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -18,14 +18,12 @@ use crate::blockchain::blockchain_interface::data_structures::{ use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; use actix::Recipient; -use bytes::Buf; use futures::Future; use masq_lib::blockchains::chains::Chain; use masq_lib::constants::WALLET_ADDRESS_LENGTH; use masq_lib::logger::Logger; use secp256k1secrets::SecretKey; use serde_json::Value; -use std::fmt::Display; use std::iter::once; use std::time::SystemTime; use thousands::Separable; @@ -394,7 +392,6 @@ mod tests { use masq_lib::constants::{DEFAULT_CHAIN, DEFAULT_GAS_PRICE}; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::mock_blockchain_client_server::MBCSBuilder; - use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use masq_lib::utils::find_free_port; use serde_json::Value; use std::net::Ipv4Addr; @@ -465,7 +462,6 @@ mod tests { .unwrap(); let web3_batch = Web3::new(Batch::new(transport)); let chain = DEFAULT_CHAIN; - let gas_price_in_gwei = DEFAULT_GAS_PRICE; let pending_nonce = 1; let consuming_wallet = make_paying_wallet(b"paying_wallet"); let account_1 = make_payable_account(1); diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index 9c2d02e0a..6a4762673 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -14,7 +14,6 @@ use futures::Future; use masq_lib::blockchains::chains::Chain; use web3::types::Address; use masq_lib::logger::Logger; -use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index 3b8214f98..a52ef9590 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -49,7 +49,6 @@ mod tests { }; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; - use crate::blockchain::blockchain_interface::BlockchainInterface; use crate::blockchain::blockchain_interface_initializer::BlockchainInterfaceInitializer; use crate::test_utils::make_wallet; use futures::Future; diff --git a/node/src/blockchain/test_utils.rs b/node/src/blockchain/test_utils.rs index 42f1dc5e1..4124e283a 100644 --- a/node/src/blockchain/test_utils.rs +++ b/node/src/blockchain/test_utils.rs @@ -5,21 +5,18 @@ use crate::blockchain::blockchain_interface::blockchain_interface_web3::{ BlockchainInterfaceWeb3, REQUESTS_IN_PARALLEL, }; -use crate::test_utils::make_wallet; use bip39::{Language, Mnemonic, Seed}; use ethabi::Hash; use ethereum_types::{BigEndianHash, H160, H256, U64}; -use itertools::Itertools; use lazy_static::lazy_static; use masq_lib::blockchains::chains::Chain; use masq_lib::utils::to_string; use serde::Serialize; use serde_derive::Deserialize; -use std::collections::HashMap; use std::fmt::Debug; use std::net::Ipv4Addr; use web3::transports::{EventLoopHandle, Http}; -use web3::types::{Address, Index, Log, SignedTransaction, TransactionReceipt, H2048, U256}; +use web3::types::{Index, Log, SignedTransaction, TransactionReceipt, H2048, U256}; lazy_static! { static ref BIG_MEANINGLESS_PHRASE: Vec<&'static str> = vec![ diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 4ea4e4c52..24c88ac9a 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,6 +1,5 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::scanners::payable_scanner_extension::msgs::{ QualifiedPayablesMessage, QualifiedPayablesRipePack, }; @@ -12,10 +11,9 @@ use actix::Message; use actix::Recipient; use masq_lib::blockchains::chains::Chain; use masq_lib::ui_gateway::NodeFromUiMessage; -use std::collections::HashMap; use std::fmt; use std::fmt::{Debug, Formatter}; -use web3::types::{Address, U256}; +use web3::types::U256; #[derive(Clone, PartialEq, Eq, Debug, Default)] pub struct BlockchainBridgeConfig { @@ -84,25 +82,6 @@ impl ConsumingWalletBalances { } } -#[derive(Debug, PartialEq)] -pub struct QualifiedPayableGasPriceSetup { - pub gas_price_arranged_for_individual_txs_minor: HashMap, - pub gas_price_from_last_rpc_minor: u128, -} - -impl QualifiedPayableGasPriceSetup { - pub fn new( - gas_price_arranged_for_individual_txs_minor: HashMap, - gas_price_from_last_rpc_minor: u128, - ) -> Self { - todo!() - // Self { - // gas_price_arranged_for_individual_txs_minor, - // gas_price_from_last_rpc_minor, - // } - } -} - #[cfg(test)] mod tests { use crate::actor_system_factory::SubsFactory; From bdb9f3e1eb0fd7fa036f6e31ecd392f0cee47684 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Fri, 20 Jun 2025 08:21:45 +0200 Subject: [PATCH 11/17] GH-638: self-review --- masq_lib/src/blockchains/blockchain_records.rs | 3 ++- .../scanners/payable_scanner_extension/test_utils.rs | 9 --------- .../blockchain_interface_web3/mod.rs | 8 +++++--- node/src/blockchain/blockchain_interface_initializer.rs | 2 +- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/masq_lib/src/blockchains/blockchain_records.rs b/masq_lib/src/blockchains/blockchain_records.rs index 56d0092c8..3b592f597 100644 --- a/masq_lib/src/blockchains/blockchain_records.rs +++ b/masq_lib/src/blockchains/blockchain_records.rs @@ -12,7 +12,8 @@ use crate::constants::{ }; use ethereum_types::{Address, H160}; -// TODO these should probably be a static, and dynamic initialization should then also be allowed +// TODO these should probably be a static (it's a shame that we construct the data every time anew +// when we ask for the chain specs), and dynamic initialization should be allowed as well pub const CHAINS: [BlockchainRecord; 7] = [ BlockchainRecord { self_id: Chain::PolyMainnet, diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index c28753c28..3cf5d6574 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -39,15 +39,6 @@ impl BlockchainAgent for BlockchainAgentMock { todo!("to be implemented by GH-711") } - // fn gas_price_for_individual_txs(&self) -> QualifiedPayableGasPriceSetup { - // todo!() - // // (&self) -> u128 { - // // self.gas_price_results - // // .borrow_mut() - // // .remove(0) - // // } - // } - fn consuming_wallet(&self) -> &Wallet { self.consuming_wallet_result_opt.as_ref().unwrap() } diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 134fc1807..9911cbe80 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -26,9 +26,11 @@ use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingP use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{LowBlockchainIntWeb3, TransactionReceiptResult, TxReceipt, TxStatus}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::utils::{create_blockchain_agent_web3, send_payables_within_batch, BlockchainAgentFutureResult}; -// TODO We probably should begin to attach these constants more tightly to the interface, so that we aren't baffled -// which constant belongs to which interface. I suggest to declare them inside the inherent impl block. They will then -// need to be preceded by the class name if you want to use them. That could be the distinction we desire, though. +// TODO We should probably begin to attach these constants to the interfaces more tightly, so that +// we aren't baffled by which interface they belong with. I suggest to declare them inside +// their inherent impl blocks. They will then need to be preceded by the class name +// of the respective interface if you want to use them. This could be a distinction we desire, +// despite the increased wordiness. const CONTRACT_ABI: &str = indoc!( r#"[{ diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index a52ef9590..d9b54a39d 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -62,7 +62,7 @@ mod tests { fn initialize_web3_interface_works() { // TODO this test should definitely assert on the web3 requests sent to the server, // that's the best way to verify that this interface belongs to the web3 architecture - // (GH-543) + // (This test amplifies the importance of GH-543) let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) .ok_response("0x3B9ACA00".to_string(), 0) // gas_price = 10000000000 From f39928d3d96b91942a96ac55d9529b15457e076c Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Wed, 25 Jun 2025 12:17:53 +0200 Subject: [PATCH 12/17] mend --- masq_lib/src/constants.rs | 2 + node/src/accountant/mod.rs | 39 +-- node/src/accountant/payment_adjuster.rs | 4 +- node/src/accountant/scanners/mod.rs | 10 +- .../payable_scanner_extension/msgs.rs | 18 +- .../payable_scanner_extension/test_utils.rs | 15 +- node/src/accountant/test_utils.rs | 17 +- .../blockchain/blockchain_agent/agent_null.rs | 175 ---------- .../blockchain/blockchain_agent/agent_web3.rs | 299 +++++++++--------- node/src/blockchain/blockchain_agent/mod.rs | 12 +- node/src/blockchain/blockchain_bridge.rs | 93 +++--- .../blockchain_interface_web3/mod.rs | 56 ++-- .../blockchain_interface_web3/utils.rs | 102 +++--- .../blockchain/blockchain_interface/mod.rs | 12 +- .../blockchain_interface_initializer.rs | 23 +- node/src/sub_lib/blockchain_bridge.rs | 6 +- 16 files changed, 348 insertions(+), 535 deletions(-) delete mode 100644 node/src/blockchain/blockchain_agent/agent_null.rs diff --git a/masq_lib/src/constants.rs b/masq_lib/src/constants.rs index 6beea5748..3d09904ad 100644 --- a/masq_lib/src/constants.rs +++ b/masq_lib/src/constants.rs @@ -19,6 +19,7 @@ pub const CURRENT_LOGFILE_NAME: &str = "MASQNode_rCURRENT.log"; pub const MASQ_PROMPT: &str = "masq> "; pub const DEFAULT_GAS_PRICE: u64 = 1; //TODO ?? Really +pub const DEFAULT_GAS_PRICE_MARGIN: u64 = 30; pub const WALLET_ADDRESS_LENGTH: usize = 42; pub const MASQ_TOTAL_SUPPLY: u64 = 37_500_000; @@ -124,6 +125,7 @@ mod tests { assert_eq!(CURRENT_LOGFILE_NAME, "MASQNode_rCURRENT.log"); assert_eq!(MASQ_PROMPT, "masq> "); assert_eq!(DEFAULT_GAS_PRICE, 1); + assert_eq!(DEFAULT_GAS_PRICE_MARGIN, 30); assert_eq!(WALLET_ADDRESS_LENGTH, 42); assert_eq!(MASQ_TOTAL_SUPPLY, 37_500_000); assert_eq!(WEIS_IN_GWEI, 1_000_000_000); diff --git a/node/src/accountant/mod.rs b/node/src/accountant/mod.rs index d8cc2a9cc..7237110a8 100644 --- a/node/src/accountant/mod.rs +++ b/node/src/accountant/mod.rs @@ -1231,7 +1231,7 @@ mod tests { use crate::accountant::test_utils::DaoWithDestination::{ ForAccountantBody, ForPayableScanner, ForPendingPayableScanner, ForReceivableScanner, }; - use crate::accountant::test_utils::{bc_from_earning_wallet, bc_from_wallets, make_payable_account, make_pending_payable_fingerprint, make_qualified_and_unqualified_payables, make_raw_qualified_payables_for_retry_mode, make_ripe_qualified_payables, BannedDaoFactoryMock, ConfigDaoFactoryMock, MessageIdGeneratorMock, PayableDaoFactoryMock, PayableDaoMock, PayableScannerBuilder, PaymentAdjusterMock, PendingPayableDaoFactoryMock, PendingPayableDaoMock, ReceivableDaoFactoryMock, ReceivableDaoMock}; + use crate::accountant::test_utils::{bc_from_earning_wallet, bc_from_wallets, make_payable_account, make_pending_payable_fingerprint, make_qualified_and_unqualified_payables, make_unpriced_qualified_payables_for_retry_mode, make_priced_qualified_payables, BannedDaoFactoryMock, ConfigDaoFactoryMock, MessageIdGeneratorMock, PayableDaoFactoryMock, PayableDaoMock, PayableScannerBuilder, PaymentAdjusterMock, PendingPayableDaoFactoryMock, PendingPayableDaoMock, ReceivableDaoFactoryMock, ReceivableDaoMock}; use crate::accountant::test_utils::{AccountantBuilder, BannedDaoMock}; use crate::accountant::Accountant; use crate::blockchain::blockchain_interface::blockchain_interface_web3::HashAndAmount; @@ -1286,7 +1286,7 @@ mod tests { use std::sync::Mutex; use std::time::{Duration, UNIX_EPOCH}; use std::vec; - use crate::accountant::scanners::payable_scanner_extension::msgs::QualifiedPayablesRawPack; + use crate::accountant::scanners::payable_scanner_extension::msgs::UnpricedQualifiedPayables; use crate::accountant::scanners::scan_schedulers::{NewPayableScanDynIntervalComputer, NewPayableScanDynIntervalComputerReal}; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; @@ -1542,7 +1542,7 @@ mod tests { assert_eq!( blockchain_bridge_recording.get_record::(0), &QualifiedPayablesMessage { - qualified_payables: QualifiedPayablesRawPack::from(vec![payable_account]), + qualified_payables: UnpricedQualifiedPayables::from(vec![payable_account]), consuming_wallet, response_skeleton_opt: Some(ResponseSkeleton { client_id: 1234, @@ -1632,7 +1632,7 @@ mod tests { let system = System::new("test"); let agent_id_stamp = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp); - let qualified_payables = make_ripe_qualified_payables(vec![ + let qualified_payables = make_priced_qualified_payables(vec![ (account_1, 1_000_000_001), (account_2, 1_000_000_002), ]); @@ -1689,8 +1689,8 @@ mod tests { ); assert_eq!(blockchain_bridge_recording.len(), 1); assert_using_the_same_logger(&logger_clone, test_name, None) - // adjust_payments() did not need any prepared result, which means it couldn't have been - // reached because otherwise this test would've panicked + // The adjust_payments() function doesn't require prepared results, indicating it shouldn't + // have been reached during the test, or it would have caused a panic. } fn assert_using_the_same_logger( @@ -1739,7 +1739,7 @@ mod tests { let agent_id_stamp_first_phase = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_first_phase); - let initial_unadjusted_accounts = make_ripe_qualified_payables(vec![ + let initial_unadjusted_accounts = make_priced_qualified_payables(vec![ (unadjusted_account_1.clone(), 111_222_333), (unadjusted_account_2.clone(), 222_333_444), ]); @@ -1753,7 +1753,7 @@ mod tests { let agent_id_stamp_second_phase = ArbitraryIdStamp::new(); let agent = BlockchainAgentMock::default().set_arbitrary_id_stamp(agent_id_stamp_second_phase); - let affordable_accounts = make_ripe_qualified_payables(vec![ + let affordable_accounts = make_priced_qualified_payables(vec![ (adjusted_account_1.clone(), 111_222_333), (adjusted_account_2.clone(), 222_333_444), ]); @@ -1803,7 +1803,7 @@ mod tests { ); assert!( before <= captured_now && captured_now <= after, - "captured should be between {:?} and {:?} but was {:?}", + "timestamp should be between {:?} and {:?} but was {:?}", before, after, captured_now @@ -2235,7 +2235,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - qualified_payables: QualifiedPayablesRawPack::from(qualified_payables), + qualified_payables: UnpricedQualifiedPayables::from(qualified_payables), consuming_wallet, response_skeleton_opt: None, } @@ -2311,7 +2311,7 @@ mod tests { let consuming_wallet = make_wallet("abc"); subject.consuming_wallet_opt = Some(consuming_wallet.clone()); let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: make_raw_qualified_payables_for_retry_mode(vec![ + qualified_payables: make_unpriced_qualified_payables_for_retry_mode(vec![ (make_payable_account(789), 111_222_333), (make_payable_account(888), 222_333_444), ]), @@ -2724,7 +2724,7 @@ mod tests { // These values belong to the RetryPayableScanner .start_scan_params(&scan_params.payable_start_scan) .start_scan_result(Ok(QualifiedPayablesMessage { - qualified_payables: make_raw_qualified_payables_for_retry_mode(vec![( + qualified_payables: make_unpriced_qualified_payables_for_retry_mode(vec![( make_payable_account(123), 555_666_777, )]), @@ -3482,12 +3482,13 @@ mod tests { let (blockchain_bridge, _, blockchain_bridge_recording_arc) = make_recorder(); let blockchain_bridge_addr = blockchain_bridge.start(); let payable_account = make_payable_account(123); - let raw_qualified_payables = QualifiedPayablesRawPack::from(vec![payable_account.clone()]); - let ripe_qualified_payables = - make_ripe_qualified_payables(vec![(payable_account, 123_456_789)]); + let unpriced_qualified_payables = + UnpricedQualifiedPayables::from(vec![payable_account.clone()]); + let priced_qualified_payables = + make_priced_qualified_payables(vec![(payable_account, 123_456_789)]); let consuming_wallet = make_paying_wallet(b"consuming"); let counter_msg_1 = BlockchainAgentWithContextMessage { - qualified_payables: ripe_qualified_payables.clone(), + qualified_payables: priced_qualified_payables.clone(), agent: Box::new(BlockchainAgentMock::default()), response_skeleton_opt: None, }; @@ -3519,7 +3520,7 @@ mod tests { response_skeleton_opt: None, }; let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: raw_qualified_payables, + qualified_payables: unpriced_qualified_payables, consuming_wallet: consuming_wallet.clone(), response_skeleton_opt: None, }; @@ -3590,7 +3591,7 @@ mod tests { blockchain_bridge_recording.get_record::(1); assert_eq!( actual_outbound_payment_instructions_msg.affordable_accounts, - ripe_qualified_payables + priced_qualified_payables ); let actual_requested_receipts_1 = blockchain_bridge_recording.get_record::(2); @@ -3926,7 +3927,7 @@ mod tests { assert_eq!( message, &QualifiedPayablesMessage { - qualified_payables: QualifiedPayablesRawPack::from(qualified_payables), + qualified_payables: UnpricedQualifiedPayables::from(qualified_payables), consuming_wallet, response_skeleton_opt: None, } diff --git a/node/src/accountant/payment_adjuster.rs b/node/src/accountant/payment_adjuster.rs index 0c7385fc9..5062fc1ab 100644 --- a/node/src/accountant/payment_adjuster.rs +++ b/node/src/accountant/payment_adjuster.rs @@ -73,7 +73,7 @@ mod tests { use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal}; use crate::accountant::scanners::payable_scanner_extension::msgs::BlockchainAgentWithContextMessage; use crate::accountant::scanners::payable_scanner_extension::test_utils::BlockchainAgentMock; - use crate::accountant::test_utils::{make_payable_account, make_ripe_qualified_payables}; + use crate::accountant::test_utils::{make_payable_account, make_priced_qualified_payables}; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; @@ -84,7 +84,7 @@ mod tests { let payable = make_payable_account(123); let agent = BlockchainAgentMock::default(); let setup_msg = BlockchainAgentWithContextMessage { - qualified_payables: make_ripe_qualified_payables(vec![(payable, 111_111_111)]), + qualified_payables: make_priced_qualified_payables(vec![(payable, 111_111_111)]), agent: Box::new(agent), response_skeleton_opt: None, }; diff --git a/node/src/accountant/scanners/mod.rs b/node/src/accountant/scanners/mod.rs index 5683ee211..cbd844bc4 100644 --- a/node/src/accountant/scanners/mod.rs +++ b/node/src/accountant/scanners/mod.rs @@ -45,7 +45,7 @@ use time::OffsetDateTime; use variant_count::VariantCount; use web3::types::H256; use crate::accountant::scanners::payable_scanner_extension::{MultistageDualPayableScanner, PreparedAdjustment, SolvencySensitivePaymentInstructor}; -use crate::accountant::scanners::payable_scanner_extension::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, QualifiedPayablesRawPack}; +use crate::accountant::scanners::payable_scanner_extension::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, UnpricedQualifiedPayables}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionReceiptResult, TxStatus}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError; use crate::db_config::persistent_configuration::{PersistentConfiguration, PersistentConfigurationReal}; @@ -499,7 +499,7 @@ impl StartableScanner for PayableS "Chose {} qualified debts to pay", qualified_payables.len() ); - let qualified_payables = QualifiedPayablesRawPack::from(qualified_payables); + let qualified_payables = UnpricedQualifiedPayables::from(qualified_payables); let outgoing_msg = QualifiedPayablesMessage::new( qualified_payables, consuming_wallet.clone(), @@ -1395,7 +1395,7 @@ mod tests { PendingPayable, PendingPayableDaoError, TransactionHashes, }; use crate::accountant::db_access_objects::utils::{from_unix_timestamp, to_unix_timestamp}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesMessage, QualifiedPayablesRawPack}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesMessage, UnpricedQualifiedPayables}; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult, PendingPayableMetadata}; use crate::accountant::scanners::scanners_utils::pending_payable_scanner_utils::{handle_none_status, handle_status_with_failure, PendingPayableScanReport, PendingPayableScanResult}; use crate::accountant::scanners::{Scanner, StartScanError, StartableScanner, PayableScanner, PendingPayableScanner, ReceivableScanner, ScannerCommon, Scanners, MTError}; @@ -1642,7 +1642,7 @@ mod tests { let timestamp = subject.payable.scan_started_at(); assert_eq!(timestamp, Some(now)); let qualified_payables_count = qualified_payable_accounts.len(); - let expected_raw_qualified_payables = QualifiedPayablesRawPack { + let expected_unpriced_qualified_payables = UnpricedQualifiedPayables { payables: qualified_payable_accounts .into_iter() .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) @@ -1651,7 +1651,7 @@ mod tests { assert_eq!( result, Ok(QualifiedPayablesMessage { - qualified_payables: expected_raw_qualified_payables, + qualified_payables: expected_unpriced_qualified_payables, consuming_wallet, response_skeleton_opt: None, }) diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index 9aeaecd0a..a89a1e73d 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -9,19 +9,19 @@ use std::fmt::Debug; #[derive(Debug, Message, PartialEq, Eq, Clone)] pub struct QualifiedPayablesMessage { - pub qualified_payables: QualifiedPayablesRawPack, + pub qualified_payables: UnpricedQualifiedPayables, pub consuming_wallet: Wallet, pub response_skeleton_opt: Option, } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayablesRawPack { +pub struct UnpricedQualifiedPayables { pub payables: Vec, } -impl From> for QualifiedPayablesRawPack { +impl From> for UnpricedQualifiedPayables { fn from(qualified_payable: Vec) -> Self { - QualifiedPayablesRawPack { + UnpricedQualifiedPayables { payables: qualified_payable .into_iter() .map(|payable| QualifiedPayablesBeforeGasPriceSelection::new(payable, None)) @@ -49,11 +49,11 @@ impl QualifiedPayablesBeforeGasPriceSelection { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayablesRipePack { +pub struct PricedQualifiedPayables { pub payables: Vec, } -impl Into> for QualifiedPayablesRipePack { +impl Into> for PricedQualifiedPayables { fn into(self) -> Vec { self.payables .into_iter() @@ -79,7 +79,7 @@ impl QualifiedPayablesWithGasPrice { impl QualifiedPayablesMessage { pub(in crate::accountant) fn new( - qualified_payables: QualifiedPayablesRawPack, + qualified_payables: UnpricedQualifiedPayables, consuming_wallet: Wallet, response_skeleton_opt: Option, ) -> Self { @@ -99,14 +99,14 @@ impl SkeletonOptHolder for QualifiedPayablesMessage { #[derive(Message)] pub struct BlockchainAgentWithContextMessage { - pub qualified_payables: QualifiedPayablesRipePack, + pub qualified_payables: PricedQualifiedPayables, pub agent: Box, pub response_skeleton_opt: Option, } impl BlockchainAgentWithContextMessage { pub fn new( - qualified_payables: QualifiedPayablesRipePack, + qualified_payables: PricedQualifiedPayables, agent: Box, response_skeleton_opt: Option, ) -> Self { diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index 3cf5d6574..e27bad120 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -2,6 +2,9 @@ #![cfg(test)] +use crate::accountant::scanners::payable_scanner_extension::msgs::{ + PricedQualifiedPayables, UnpricedQualifiedPayables, +}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; @@ -31,7 +34,17 @@ impl Default for BlockchainAgentMock { } impl BlockchainAgent for BlockchainAgentMock { - fn estimated_transaction_fee_total(&self) -> u128 { + fn price_qualified_payables( + &self, + qualified_payables: UnpricedQualifiedPayables, + ) -> PricedQualifiedPayables { + todo!() + } + + fn estimated_transaction_fee_total( + &self, + _qualified_payables: &PricedQualifiedPayables, + ) -> u128 { todo!("to be implemented by GH-711") } diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index 5c2273901..dd02a2cdf 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -17,8 +17,9 @@ use crate::accountant::db_access_objects::utils::{ }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - BlockchainAgentWithContextMessage, QualifiedPayablesBeforeGasPriceSelection, - QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, + BlockchainAgentWithContextMessage, PricedQualifiedPayables, + QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesWithGasPrice, + UnpricedQualifiedPayables, }; use crate::accountant::scanners::payable_scanner_extension::PreparedAdjustment; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableThresholdsGauge; @@ -1501,10 +1502,10 @@ impl PaymentAdjusterMock { } } -pub fn make_ripe_qualified_payables( +pub fn make_priced_qualified_payables( inputs: Vec<(PayableAccount, u128)>, -) -> QualifiedPayablesRipePack { - QualifiedPayablesRipePack { +) -> PricedQualifiedPayables { + PricedQualifiedPayables { payables: inputs .into_iter() .map(|(payable, gas_price_minor)| QualifiedPayablesWithGasPrice { @@ -1515,10 +1516,10 @@ pub fn make_ripe_qualified_payables( } } -pub fn make_raw_qualified_payables_for_retry_mode( +pub fn make_unpriced_qualified_payables_for_retry_mode( inputs: Vec<(PayableAccount, u128)>, -) -> QualifiedPayablesRawPack { - QualifiedPayablesRawPack { +) -> UnpricedQualifiedPayables { + UnpricedQualifiedPayables { payables: inputs .into_iter() .map(|(payable, previous_attempt_gas_price_minor)| { diff --git a/node/src/blockchain/blockchain_agent/agent_null.rs b/node/src/blockchain/blockchain_agent/agent_null.rs deleted file mode 100644 index b1fdf1bb8..000000000 --- a/node/src/blockchain/blockchain_agent/agent_null.rs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. - -use crate::blockchain::blockchain_agent::BlockchainAgent; -use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; -use crate::sub_lib::wallet::Wallet; -use ethereum_types::U256; -use masq_lib::blockchains::chains::Chain; -use masq_lib::logger::Logger; -use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; - -#[derive(Clone)] -pub struct BlockchainAgentNull { - wallet: Wallet, - logger: Logger, -} - -impl BlockchainAgent for BlockchainAgentNull { - fn estimated_transaction_fee_total(&self) -> u128 { - self.log_function_call("estimated_transaction_fee_total()"); - 0 - } - - fn consuming_wallet_balances(&self) -> ConsumingWalletBalances { - self.log_function_call("consuming_wallet_balances()"); - ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::zero(), - masq_token_balance_in_minor_units: U256::zero(), - } - } - - fn consuming_wallet(&self) -> &Wallet { - self.log_function_call("consuming_wallet()"); - &self.wallet - } - - fn get_chain(&self) -> Chain { - self.log_function_call("get_chain()"); - TEST_DEFAULT_CHAIN - } - - #[cfg(test)] - fn dup(&self) -> Box { - intentionally_blank!() - } - - #[cfg(test)] - as_any_ref_in_trait_impl!(); -} - -impl BlockchainAgentNull { - pub fn new() -> Self { - Self { - wallet: Wallet::null(), - logger: Logger::new("BlockchainAgentNull"), - } - } - - fn log_function_call(&self, function_call: &str) { - error!( - self.logger, - "calling null version of {function_call} for BlockchainAgentNull will be without effect", - ); - } -} - -impl Default for BlockchainAgentNull { - fn default() -> Self { - Self::new() - } -} - -#[cfg(test)] -mod tests { - use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; - use crate::sub_lib::wallet::Wallet; - - use crate::blockchain::blockchain_agent::agent_null::BlockchainAgentNull; - use crate::blockchain::blockchain_agent::BlockchainAgent; - use masq_lib::logger::Logger; - use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; - use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; - use web3::types::U256; - - fn blockchain_agent_null_constructor_works(constructor: C) - where - C: Fn() -> BlockchainAgentNull, - { - init_test_logging(); - - let result = constructor(); - - assert_eq!(result.wallet, Wallet::null()); - warning!(result.logger, "blockchain_agent_null_constructor_works"); - TestLogHandler::default().exists_log_containing( - "WARN: BlockchainAgentNull: \ - blockchain_agent_null_constructor_works", - ); - } - - #[test] - fn blockchain_agent_null_constructor_works_for_new() { - blockchain_agent_null_constructor_works(BlockchainAgentNull::new) - } - - #[test] - fn blockchain_agent_null_constructor_works_for_default() { - blockchain_agent_null_constructor_works(BlockchainAgentNull::default) - } - - fn assert_error_log(test_name: &str, expected_operation: &str) { - TestLogHandler::default().exists_log_containing(&format!( - "ERROR: {test_name}: calling \ - null version of {expected_operation}() for BlockchainAgentNull \ - 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 = BlockchainAgentNull::new(); - subject.logger = Logger::new(test_name); - - let result = subject.estimated_transaction_fee_total(); - - assert_eq!(result, 0); - assert_error_log(test_name, "estimated_transaction_fee_total"); - } - - #[test] - fn null_agent_consuming_wallet_balances() { - init_test_logging(); - let test_name = "null_agent_consuming_wallet_balances"; - let mut subject = BlockchainAgentNull::new(); - subject.logger = Logger::new(test_name); - - let result = subject.consuming_wallet_balances(); - - assert_eq!( - result, - ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::zero(), - masq_token_balance_in_minor_units: U256::zero() - } - ); - assert_error_log(test_name, "consuming_wallet_balances") - } - - #[test] - fn null_agent_consuming_wallet() { - init_test_logging(); - let test_name = "null_agent_consuming_wallet"; - let mut subject = BlockchainAgentNull::new(); - subject.logger = Logger::new(test_name); - - let result = subject.consuming_wallet(); - - assert_eq!(result, &Wallet::null()); - assert_error_log(test_name, "consuming_wallet") - } - - #[test] - fn null_agent_get_chain() { - init_test_logging(); - let test_name = "null_agent_get_chain"; - let mut subject = BlockchainAgentNull::new(); - subject.logger = Logger::new(test_name); - - let result = subject.get_chain(); - - assert_eq!(result, TEST_DEFAULT_CHAIN); - assert_error_log(test_name, "get_chain") - } -} diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index a6ed9ce79..b4a25c1e8 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -1,8 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesRipePack, - QualifiedPayablesWithGasPrice, + PricedQualifiedPayables, QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; @@ -12,15 +11,62 @@ use masq_lib::blockchains::chains::Chain; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { - estimated_gas_price_for_all_txs_wei: u128, + latest_gas_price_wei: u128, + gas_limit_const_part: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, } impl BlockchainAgent for BlockchainAgentWeb3 { - fn estimated_transaction_fee_total(&self) -> u128 { - self.estimated_gas_price_for_all_txs_wei + fn price_qualified_payables( + &self, + qualified_payables: UnpricedQualifiedPayables, + ) -> PricedQualifiedPayables { + let priced_qualified_payables = qualified_payables + .payables + .into_iter() + .map(|payable_without_gas_price| { + let selected_gas_price_wei = + match payable_without_gas_price.previous_attempt_gas_price_minor_opt { + None => self.latest_gas_price_wei, + Some(previous_price) if self.latest_gas_price_wei < previous_price => { + previous_price + } + Some(_) => self.latest_gas_price_wei, + }; + + let gas_price_increased_by_margin_wei = + increase_gas_price_by_margin(selected_gas_price_wei); + + let price_ceiling = self.chain.rec().gas_price_safe_ceiling_minor; + let checked_gas_price_wei = if gas_price_increased_by_margin_wei > price_ceiling { + price_ceiling + } else { + gas_price_increased_by_margin_wei + }; + + QualifiedPayablesWithGasPrice::new( + payable_without_gas_price.payable, + checked_gas_price_wei, + ) + }) + .collect(); + PricedQualifiedPayables { + payables: priced_qualified_payables, + } + } + + fn estimated_transaction_fee_total( + &self, + qualified_payables: &PricedQualifiedPayables, + ) -> u128 { + let prices_sum: u128 = qualified_payables + .payables + .iter() + .map(|priced_payable| priced_payable.gas_price_minor) + .sum(); + (self.gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) * prices_sum } fn consuming_wallet_balances(&self) -> ConsumingWalletBalances { @@ -42,89 +88,35 @@ pub const WEB3_MAXIMAL_GAS_LIMIT_MARGIN: u128 = 3328; impl BlockchainAgentWeb3 { pub fn new( - raw_qualified_payables: QualifiedPayablesRawPack, latest_gas_price_wei: u128, gas_limit_const_part: u128, consuming_wallet: Wallet, consuming_wallet_balances: ConsumingWalletBalances, chain: Chain, - ) -> (Box, QualifiedPayablesRipePack) { - let fold_init = (QualifiedPayablesRipePack { payables: vec![] }, 0); - let (ripe_qualified_payables, gas_price_aggregated_wei) = - raw_qualified_payables.payables.into_iter().fold( - fold_init, - |(ripe_qualified_payables, gas_price_aggregated_wei), raw_q_payable| { - Self::fold_guts( - (ripe_qualified_payables, gas_price_aggregated_wei), - chain, - raw_q_payable, - latest_gas_price_wei, - ) - }, - ); - - let estimated_gas_price_wei = - gas_price_aggregated_wei * (gas_limit_const_part + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); - - let agent = Self { - estimated_gas_price_for_all_txs_wei: estimated_gas_price_wei, + ) -> BlockchainAgentWeb3 { + Self { + latest_gas_price_wei, + gas_limit_const_part, consuming_wallet, consuming_wallet_balances, chain, - }; - - (Box::new(agent), ripe_qualified_payables) - } - - fn fold_guts( - (mut ripe_qualified_payables, mut gas_price_aggregated_wei): ( - QualifiedPayablesRipePack, - u128, - ), - chain: Chain, - raw_q_payable: QualifiedPayablesBeforeGasPriceSelection, - latest_gas_price: u128, - ) -> (QualifiedPayablesRipePack, u128) { - let selected_gas_price_wei = match raw_q_payable.previous_attempt_gas_price_minor_opt { - None => latest_gas_price, - Some(previous_price) if latest_gas_price < previous_price => previous_price, - Some(_) => latest_gas_price, - }; - - let gas_price_increased_by_margin_wei = - increase_gas_price_by_margin(selected_gas_price_wei, chain); - - let price_ceiling = chain.rec().gas_price_safe_ceiling_minor; - let checked_gas_price_wei = if gas_price_increased_by_margin_wei > price_ceiling { - price_ceiling - } else { - gas_price_increased_by_margin_wei - }; - - let ripe_qualified_payable = - QualifiedPayablesWithGasPrice::new(raw_q_payable.payable, checked_gas_price_wei); - - ripe_qualified_payables - .payables - .push(ripe_qualified_payable); - gas_price_aggregated_wei += checked_gas_price_wei; - - (ripe_qualified_payables, gas_price_aggregated_wei) + } } } #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, - QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, + PricedQualifiedPayables, QualifiedPayablesBeforeGasPriceSelection, + QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, }; use crate::accountant::test_utils::{ - make_payable_account, make_raw_qualified_payables_for_retry_mode, + make_payable_account, make_unpriced_qualified_payables_for_retry_mode, }; use crate::blockchain::blockchain_agent::agent_web3::{ BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; + use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::test_utils::make_wallet; @@ -138,7 +130,7 @@ mod tests { } #[test] - fn returns_correct_ripe_qualified_payables_for_new_payable_scan() { + fn returns_correct_priced_qualified_payables_for_new_payable_scan() { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -146,31 +138,33 @@ mod tests { }; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let qualified_payables = - QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); - let gas_price_from_rpc = 555_666_777; + let qualified_payables_without_price = + UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); + let rpc_gas_price_wei = 555_666_777; let chain = TEST_DEFAULT_CHAIN; - let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( - qualified_payables, - gas_price_from_rpc, + let subject = BlockchainAgentWeb3::new( + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); - let gas_price_with_margin = increase_gas_price_by_margin(gas_price_from_rpc, chain); - let expected_result = QualifiedPayablesRipePack { + let priced_qualified_payables = + subject.price_qualified_payables(qualified_payables_without_price); + + let gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei); + let expected_result = PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin), + QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin_wei), + QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin_wei), ], }; - assert_eq!(ripe_qualified_payables, expected_result); + assert_eq!(priced_qualified_payables, expected_result); } #[test] - fn returns_correct_ripe_qualified_payables_for_retry_payable_scan() { + fn returns_correct_priced_qualified_payables_for_retry_payable_scan() { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -183,7 +177,7 @@ mod tests { let account_3 = make_payable_account(56); let account_4 = make_payable_account(78); let account_5 = make_payable_account(90); - let qualified_payables = QualifiedPayablesRawPack { + let qualified_payables_without_price = UnpricedQualifiedPayables { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), @@ -207,35 +201,34 @@ mod tests { ), ], }; - let gas_price_from_rpc = 444_555_666; - - let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( - qualified_payables, - gas_price_from_rpc, + let subject = BlockchainAgentWeb3::new( + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + let priced_qualified_payables = + subject.price_qualified_payables(qualified_payables_without_price); + let expected_result = { - let gas_price_account_1 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_2 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); - let gas_price_account_4 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_5 = - increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); - QualifiedPayablesRipePack { + let gas_price_account_wei_1 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_2 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1); + let gas_price_account_wei_4 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789); + PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), - QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), - QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_4), - QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_5), + QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_wei_1), + QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_wei_2), + QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_wei_3), + QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_wei_4), + QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_wei_5), ], } }; - assert_eq!(ripe_qualified_payables, expected_result); + assert_eq!(priced_qualified_payables, expected_result); } #[test] @@ -246,13 +239,13 @@ mod tests { // This should be the value that would surplus the ceiling just slightly if the margin is // applied. // Adding just 1 didn't work, therefore 2 - let fetched_latest_gas_price_wei = + let rpc_gas_price_wei = ((ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100)) + 2; - let check_value_wei = increase_gas_price_by_margin(fetched_latest_gas_price_wei, chain); + let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( chain, - fetched_latest_gas_price_wei, + rpc_gas_price_wei, ); assert!( @@ -287,7 +280,7 @@ mod tests { fn test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( chain: Chain, - fetched_latest_gas_price_wei: u128, + rpc_gas_price_wei: u128, ) { let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let consuming_wallet = make_wallet("efg"); @@ -298,23 +291,24 @@ mod tests { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let qualified_payables = - QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); - let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( - qualified_payables, - fetched_latest_gas_price_wei, + UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); + let subject = BlockchainAgentWeb3::new( + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); - let expected_result = QualifiedPayablesRipePack { + let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); + + let expected_result = PricedQualifiedPayables { payables: vec![ QualifiedPayablesWithGasPrice::new(account_1, ceiling_gas_price_wei), QualifiedPayablesWithGasPrice::new(account_2, ceiling_gas_price_wei), ], }; - assert_eq!(ripe_qualified_payables, expected_result); + assert_eq!(priced_qualified_payables, expected_result); } #[test] @@ -327,17 +321,17 @@ mod tests { // This should be the value that would surplus the ceiling just slightly if the margin is // applied. // Adding just 1 didn't work, therefore 2 - let fetched_lastest_gas_price = + let rpc_gas_price_wei = (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; - let check_value_wei = increase_gas_price_by_margin(fetched_lastest_gas_price, chain); - let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ - (account_1.clone(), fetched_lastest_gas_price - 1), - (account_2.clone(), fetched_lastest_gas_price - 2), + let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); + let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + (account_1.clone(), rpc_gas_price_wei - 1), + (account_2.clone(), rpc_gas_price_wei - 2), ]); test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( chain, - fetched_lastest_gas_price, + rpc_gas_price_wei, raw_qualified_payables, ); @@ -360,16 +354,16 @@ mod tests { // This should be the value that would surplus the ceiling just slightly if the margin is applied let border_gas_price_wei = (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; - let fetched_gas_price_wei = border_gas_price_wei - 1; - let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei, chain); - let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + let rpc_gas_price_wei = border_gas_price_wei - 1; + let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei); + let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), border_gas_price_wei), (account_2.clone(), border_gas_price_wei), ]); test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( chain, - fetched_gas_price_wei, + rpc_gas_price_wei, raw_qualified_payables, ); @@ -383,7 +377,7 @@ mod tests { let fetched_gas_price_wei = ceiling_gas_price_wei - 1; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), fetched_gas_price_wei - 1), (account_2.clone(), fetched_gas_price_wei - 2), ]); @@ -401,7 +395,7 @@ mod tests { let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), ceiling_gas_price_wei - 1), (account_2.clone(), ceiling_gas_price_wei - 2), ]); @@ -422,7 +416,7 @@ mod tests { let account_2 = make_payable_account(34); // The values can never go above the ceiling, therefore, we can assume only values even or // smaller than that in the previous attempts - let raw_qualified_payables = make_raw_qualified_payables_for_retry_mode(vec![ + let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), ceiling_gas_price_wei), (account_2.clone(), ceiling_gas_price_wei), ]); @@ -436,8 +430,8 @@ mod tests { fn test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( chain: Chain, - fetched_lastest_gas_price_wei: u128, - qualified_payables: QualifiedPayablesRawPack, + rpc_gas_price_wei: u128, + qualified_payables: UnpricedQualifiedPayables, ) { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { @@ -445,7 +439,7 @@ mod tests { masq_token_balance_in_minor_units: Default::default(), }; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; - let expected_ripe_payable = QualifiedPayablesRipePack { + let expected_priced_payables = PricedQualifiedPayables { payables: qualified_payables .payables .clone() @@ -455,17 +449,17 @@ mod tests { }) .collect(), }; - - let (_, ripe_qualified_payables) = BlockchainAgentWeb3::new( - qualified_payables, - fetched_lastest_gas_price_wei, + let subject = BlockchainAgentWeb3::new( + rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); - assert_eq!(ripe_qualified_payables, expected_ripe_payable); + let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); + + assert_eq!(priced_qualified_payables, expected_priced_payables); } #[test] @@ -476,9 +470,8 @@ mod tests { transaction_fee_balance_in_minor_units: U256::from(456_789), masq_token_balance_in_minor_units: U256::from(123_000_000), }; - let qualified_payables = QualifiedPayablesRawPack::from(vec![make_payable_account(123)]); - let (subject, _) = BlockchainAgentWeb3::new( - qualified_payables, + + let subject = BlockchainAgentWeb3::new( 222_333_444, gas_limit_const_part, consuming_wallet.clone(), @@ -504,22 +497,22 @@ mod tests { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let chain = TEST_DEFAULT_CHAIN; - let qualified_payables = QualifiedPayablesRawPack::from(vec![account_1, account_2]); - let (agent, _) = BlockchainAgentWeb3::new( - qualified_payables, + let qualified_payables = UnpricedQualifiedPayables::from(vec![account_1, account_2]); + let subject = BlockchainAgentWeb3::new( 444_555_666, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); - let result = agent.estimated_transaction_fee_total(); + let result = subject.estimated_transaction_fee_total(&priced_qualified_payables); assert_eq!( result, (2 * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN)) - * increase_gas_price_by_margin(444_555_666, chain) + * increase_gas_price_by_margin(444_555_666) ); } @@ -537,7 +530,7 @@ mod tests { let account_3 = make_payable_account(56); let account_4 = make_payable_account(78); let account_5 = make_payable_account(90); - let qualified_payables = QualifiedPayablesRawPack { + let qualified_payables = UnpricedQualifiedPayables { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), @@ -561,29 +554,29 @@ mod tests { ), ], }; - let (agent, _) = BlockchainAgentWeb3::new( - qualified_payables, + let subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); - let result = agent.estimated_transaction_fee_total(); + let result = subject.estimated_transaction_fee_total(&priced_qualified_payables); - let gas_price_account_1 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_2 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1, chain); - let gas_price_account_4 = increase_gas_price_by_margin(rpc_gas_price_wei, chain); - let gas_price_account_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789, chain); + let gas_price_account_wei_1 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_2 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1); + let gas_price_account_wei_4 = increase_gas_price_by_margin(rpc_gas_price_wei); + let gas_price_account_wei_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789); assert_eq!( result, - (gas_price_account_1 - + gas_price_account_2 - + gas_price_account_3 - + gas_price_account_4 - + gas_price_account_5) + (gas_price_account_wei_1 + + gas_price_account_wei_2 + + gas_price_account_wei_3 + + gas_price_account_wei_4 + + gas_price_account_wei_5) * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } diff --git a/node/src/blockchain/blockchain_agent/mod.rs b/node/src/blockchain/blockchain_agent/mod.rs index d6c3b46db..b8538d97e 100644 --- a/node/src/blockchain/blockchain_agent/mod.rs +++ b/node/src/blockchain/blockchain_agent/mod.rs @@ -1,7 +1,10 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -pub mod agent_null; + pub mod agent_web3; +use crate::accountant::scanners::payable_scanner_extension::msgs::{ + PricedQualifiedPayables, UnpricedQualifiedPayables, +}; use crate::arbitrary_id_stamp_in_trait; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; @@ -23,7 +26,12 @@ use masq_lib::blockchains::chains::Chain; //* defaulted limit pub trait BlockchainAgent: Send { - fn estimated_transaction_fee_total(&self) -> u128; + fn price_qualified_payables( + &self, + qualified_payables: UnpricedQualifiedPayables, + ) -> PricedQualifiedPayables; + fn estimated_transaction_fee_total(&self, qualified_payables: &PricedQualifiedPayables) + -> u128; fn consuming_wallet_balances(&self) -> ConsumingWalletBalances; fn consuming_wallet(&self) -> &Wallet; fn get_chain(&self) -> Chain; diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 11eebe1e3..005c2b866 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -1,6 +1,6 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. -use crate::accountant::scanners::payable_scanner_extension::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, QualifiedPayablesRipePack}; +use crate::accountant::scanners::payable_scanner_extension::msgs::{BlockchainAgentWithContextMessage, QualifiedPayablesMessage, PricedQualifiedPayables}; use crate::accountant::{ ReceivedPayments, ResponseSkeleton, ScanError, SentPayables, SkeletonOptHolder, @@ -42,6 +42,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use ethabi::Hash; use web3::types::H256; +use masq_lib::constants::DEFAULT_GAS_PRICE_MARGIN; use masq_lib::messages::ScanType; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionReceiptResult, TxStatus}; @@ -260,25 +261,22 @@ impl BlockchainBridge { let accountant_recipient = self.payable_payments_setup_subs_opt.clone(); Box::new( self.blockchain_interface - .introduce_blockchain_agent( - incoming_message.qualified_payables, - incoming_message.consuming_wallet, - ) + .introduce_blockchain_agent(incoming_message.consuming_wallet) .map_err(|e| format!("Blockchain agent build error: {:?}", e)) - .and_then( - move |(agent, qualified_payables_with_gas_price_finalized)| { - let outgoing_message = BlockchainAgentWithContextMessage::new( - qualified_payables_with_gas_price_finalized, - agent, - incoming_message.response_skeleton_opt, - ); - accountant_recipient - .expect("Accountant is unbound") - .try_send(outgoing_message) - .expect("Accountant is dead"); - Ok(()) - }, - ), + .and_then(move |agent| { + let priced_qualified_payables = + agent.price_qualified_payables(incoming_message.qualified_payables); + let outgoing_message = BlockchainAgentWithContextMessage::new( + priced_qualified_payables, + agent, + incoming_message.response_skeleton_opt, + ); + accountant_recipient + .expect("Accountant is unbound") + .try_send(outgoing_message) + .expect("Accountant is dead"); + Ok(()) + }), ) } @@ -487,7 +485,7 @@ impl BlockchainBridge { fn process_payments( &self, agent: Box, - affordable_accounts: QualifiedPayablesRipePack, + affordable_accounts: PricedQualifiedPayables, ) -> Box, Error = PayableTransactionError>> { let new_fingerprints_recipient = self.new_fingerprints_recipient(); @@ -537,8 +535,8 @@ struct PendingTxInfo { when_sent: SystemTime, } -pub fn increase_gas_price_by_margin(gas_price: u128, chain: Chain) -> u128 { - (gas_price * (100 + chain.rec().gas_price_default_margin_percents as u128)) / 100 +pub fn increase_gas_price_by_margin(gas_price: u128) -> u128 { + (gas_price * (100 + DEFAULT_GAS_PRICE_MARGIN as u128)) / 100 } pub struct BlockchainBridgeSubsFactoryReal {} @@ -556,7 +554,7 @@ mod tests { use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; use crate::accountant::db_access_objects::utils::from_unix_timestamp; use crate::accountant::scanners::payable_scanner_extension::test_utils::BlockchainAgentMock; - use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint, make_ripe_qualified_payables}; + use crate::accountant::test_utils::{make_payable_account, make_pending_payable_fingerprint, make_priced_qualified_payables}; use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError::TransactionID; use crate::blockchain::blockchain_interface::data_structures::errors::{ BlockchainAgentBuildError, PayableTransactionError, @@ -599,7 +597,7 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160}; use masq_lib::constants::DEFAULT_MAX_BLOCK_COUNT; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesRawPack, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, UnpricedQualifiedPayables, QualifiedPayablesWithGasPrice}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt}; impl Handler> for BlockchainBridge { @@ -697,7 +695,6 @@ mod tests { let (accountant, _, accountant_recording_arc) = make_recorder(); let accountant_recipient = accountant.start().recipient(); let blockchain_interface = make_blockchain_interface_web3(port); - let chain = blockchain_interface.get_chain(); let consuming_wallet = make_paying_wallet(b"somewallet"); let persistent_configuration = PersistentConfigurationMock::default(); let wallet_1 = make_wallet("booga"); @@ -726,7 +723,7 @@ mod tests { false, ); subject.payable_payments_setup_subs_opt = Some(accountant_recipient); - let raw_qualified_payables = QualifiedPayablesRawPack { + let qualified_payables_without_price = UnpricedQualifiedPayables { payables: qualified_payables .clone() .into_iter() @@ -737,7 +734,7 @@ mod tests { .collect(), }; let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: raw_qualified_payables.clone(), + qualified_payables: qualified_payables_without_price.clone(), consuming_wallet: consuming_wallet.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, @@ -755,12 +752,12 @@ mod tests { let accountant_received_payment = accountant_recording_arc.lock().unwrap(); let blockchain_agent_with_context_msg_actual: &BlockchainAgentWithContextMessage = accountant_received_payment.get_record(0); - let expected_ripe_qualified_payables = QualifiedPayablesRipePack { + let expected_ripe_qualified_payables = PricedQualifiedPayables { payables: qualified_payables .into_iter() .map(|payable| QualifiedPayablesWithGasPrice { payable, - gas_price_minor: increase_gas_price_by_margin(0x230000000, chain), + gas_price_minor: increase_gas_price_by_margin(0x230000000), }) .collect(), }; @@ -768,22 +765,16 @@ mod tests { blockchain_agent_with_context_msg_actual.qualified_payables, expected_ripe_qualified_payables ); + let actual_agent = blockchain_agent_with_context_msg_actual.agent.as_ref(); + assert_eq!(actual_agent.consuming_wallet(), &consuming_wallet); assert_eq!( - blockchain_agent_with_context_msg_actual - .agent - .consuming_wallet(), - &consuming_wallet - ); - assert_eq!( - blockchain_agent_with_context_msg_actual - .agent - .consuming_wallet_balances(), + actual_agent.consuming_wallet_balances(), ConsumingWalletBalances::new(0xAAAA.into(), 0xFFFF.into()) ); assert_eq!( - blockchain_agent_with_context_msg_actual - .agent - .estimated_transaction_fee_total(), + actual_agent.estimated_transaction_fee_total( + &actual_agent.price_qualified_payables(qualified_payables_without_price) + ), 1_791_228_995_698_688 ); assert_eq!( @@ -817,7 +808,7 @@ mod tests { false, ); subject.payable_payments_setup_subs_opt = Some(accountant_recipient); - let qualified_payables = QualifiedPayablesRawPack::from(vec![make_payable_account(123)]); + let qualified_payables = UnpricedQualifiedPayables::from(vec![make_payable_account(123)]); let qualified_payables_msg = QualifiedPayablesMessage { qualified_payables, consuming_wallet: consuming_wallet.clone(), @@ -897,7 +888,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - affordable_accounts: make_ripe_qualified_payables(vec![( + affordable_accounts: make_priced_qualified_payables(vec![( account.clone(), 111_222_333, )]), @@ -988,7 +979,7 @@ mod tests { let _ = addr .try_send(OutboundPaymentsInstructions { - affordable_accounts: make_ripe_qualified_payables(vec![( + affordable_accounts: make_priced_qualified_payables(vec![( account.clone(), 111_222_333, )]), @@ -1054,7 +1045,7 @@ mod tests { let consuming_wallet = make_paying_wallet(b"consuming_wallet"); let accounts_1 = make_payable_account(1); let accounts_2 = make_payable_account(2); - let affordable_qualified_payables = make_ripe_qualified_payables(vec![ + let affordable_qualified_payables = make_priced_qualified_payables(vec![ (accounts_1.clone(), 777_777_777), (accounts_2.clone(), 999_999_999), ]); @@ -1122,7 +1113,7 @@ mod tests { .consuming_wallet_result(consuming_wallet) .gas_price_result(123); let msg = OutboundPaymentsInstructions::new( - make_ripe_qualified_payables(vec![(make_payable_account(111), 111_000_000)]), + make_priced_qualified_payables(vec![(make_payable_account(111), 111_000_000)]), Box::new(agent), None, ); @@ -2253,14 +2244,8 @@ mod tests { #[test] fn increase_gas_price_by_margin_works() { - assert_eq!( - increase_gas_price_by_margin(1_000_000_000, Chain::BaseMainnet), - 1_300_000_000 - ); - assert_eq!( - increase_gas_price_by_margin(9_000_000_000, Chain::PolyAmoy), - 11_700_000_000 - ); + assert_eq!(increase_gas_price_by_margin(1_000_000_000), 1_300_000_000); + assert_eq!(increase_gas_price_by_margin(9_000_000_000), 11_700_000_000); } } diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 9911cbe80..77a630319 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -20,7 +20,7 @@ use actix::Recipient; use ethereum_types::U64; use web3::transports::{EventLoopHandle, Http}; use web3::types::{Address, Log, H256, U256, FilterBuilder, TransactionReceipt, BlockNumber}; -use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::accountant::scanners::payable_scanner_extension::msgs::{UnpricedQualifiedPayables, PricedQualifiedPayables}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{LowBlockchainIntWeb3, TransactionReceiptResult, TxReceipt, TxStatus}; @@ -164,14 +164,8 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { fn introduce_blockchain_agent( &self, - qualified_payables: QualifiedPayablesRawPack, consuming_wallet: Wallet, - ) -> Box< - dyn Future< - Item = (Box, QualifiedPayablesRipePack), - Error = BlockchainAgentBuildError, - >, - > { + ) -> Box, Error = BlockchainAgentBuildError>> { let wallet_address = consuming_wallet.address(); let gas_limit_const_part = self.gas_limit_const_part; // TODO: Would it be better to wrap these 3 calls into a single batch call? @@ -205,9 +199,8 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { masq_token_balance, }; Ok(create_blockchain_agent_web3( - qualified_payables, - gas_limit_const_part, blockchain_agent_future_result, + gas_limit_const_part, consuming_wallet, chain, )) @@ -259,7 +252,7 @@ impl BlockchainInterface for BlockchainInterfaceWeb3 { logger: Logger, agent: Box, fingerprints_recipient: Recipient, - affordable_accounts: QualifiedPayablesRipePack, + affordable_accounts: PricedQualifiedPayables, ) -> Box, Error = PayableTransactionError>> { let consuming_wallet = agent.consuming_wallet().clone(); @@ -843,17 +836,16 @@ mod tests { #[test] fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_new_payables_mode() { - let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let raw_qualified_payables = - QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 let gas_price_wei_from_rpc_u128_wei = u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); let gas_price_wei_from_rpc_u128_wei_with_margin = - increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); - let expected_ripe_qualified_payables = QualifiedPayablesRipePack { + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); + let expected_ripe_qualified_payables = PricedQualifiedPayables { payables: vec![ QualifiedPayablesWithGasPrice::new( account_1, @@ -877,14 +869,13 @@ mod tests { #[test] fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_retry_payables_mode() { - let chain = TEST_DEFAULT_CHAIN; let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 let gas_price_wei_from_rpc_u128_wei = u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); - let raw_qualified_payables = QualifiedPayablesRawPack { + let raw_qualified_payables = UnpricedQualifiedPayables { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), @@ -902,13 +893,11 @@ mod tests { }; let expected_ripe_qualified_payables = { - let gas_price_account_1 = - increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); - let gas_price_account_2 = - increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei, chain); + let gas_price_account_1 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); + let gas_price_account_2 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); let gas_price_account_3 = - increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1, chain); - QualifiedPayablesRipePack { + increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1); + PricedQualifiedPayables { payables: vec![ QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), @@ -927,9 +916,9 @@ mod tests { } fn test_blockchain_interface_web3_can_introduce_blockchain_agent( - raw_qualified_payables: QualifiedPayablesRawPack, + qualified_payables: UnpricedQualifiedPayables, gas_price_wei_from_rpc_hex: &str, - expected_ripe_qualified_payables: QualifiedPayablesRipePack, + expected_ripe_qualified_payables: PricedQualifiedPayables, expected_estimated_transaction_fee: u128, ) { let port = find_free_port(); @@ -947,8 +936,8 @@ mod tests { let wallet = make_wallet("abc"); let subject = make_blockchain_interface_web3(port); - let (result, ripe_qualified_payables) = subject - .introduce_blockchain_agent(raw_qualified_payables, wallet.clone()) + let result = subject + .introduce_blockchain_agent(wallet.clone()) .wait() .unwrap(); @@ -962,9 +951,10 @@ mod tests { masq_token_balance_in_minor_units: expected_masq_balance } ); - assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); + let priced_qualified_payables = result.price_qualified_payables(qualified_payables); + assert_eq!(priced_qualified_payables, expected_ripe_qualified_payables); assert_eq!( - result.estimated_transaction_fee_total(), + result.estimated_transaction_fee_total(&priced_qualified_payables), expected_estimated_transaction_fee ) } @@ -976,15 +966,9 @@ mod tests { F: FnOnce(&Wallet) -> BlockchainAgentBuildError, { let wallet = make_wallet("bcd"); - let account_1 = make_payable_account(12); - let account_2 = make_payable_account(34); - let raw_qualified_payables = - QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); let subject = make_blockchain_interface_web3(port); - let result = subject - .introduce_blockchain_agent(raw_qualified_payables, wallet.clone()) - .wait(); + let result = subject.introduce_blockchain_agent(wallet.clone()).wait(); let err = match result { Err(e) => e, diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index ac0447ee1..1aefa1b03 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -3,7 +3,7 @@ use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesRawPack, QualifiedPayablesRipePack, + PricedQualifiedPayables, UnpricedQualifiedPayables, }; use crate::blockchain::blockchain_agent::agent_web3::BlockchainAgentWeb3; use crate::blockchain::blockchain_agent::BlockchainAgent; @@ -89,13 +89,13 @@ pub fn merged_output_data( pub fn transmission_log( chain: Chain, - qualified_payables_pack: &QualifiedPayablesRipePack, + qualified_payables: &PricedQualifiedPayables, lowest_nonce_used: U256, ) -> String { let chain_name = chain.rec().literal_identifier; - let account_count = qualified_payables_pack.payables.len(); + let account_count = qualified_payables.payables.len(); let last_nonce_used = lowest_nonce_used + U256::from(account_count - 1); - let biggest_payable = qualified_payables_pack + let biggest_payable = qualified_payables .payables .iter() .map(|payable_with_gas_price| payable_with_gas_price.payable.balance_wei) @@ -126,7 +126,7 @@ pub fn transmission_log( payment_column_width = payment_column_width, )); - let body = qualified_payables_pack + let body = qualified_payables .payables .iter() .map(|payable_with_gas_price| { @@ -246,7 +246,7 @@ pub fn sign_and_append_multiple_payments( web3_batch: &Web3>, consuming_wallet: Wallet, mut pending_nonce: U256, - accounts: &QualifiedPayablesRipePack, + accounts: &PricedQualifiedPayables, ) -> Vec { let mut hash_and_amount_list = vec![]; accounts.payables.iter().for_each(|payable_pack| { @@ -282,7 +282,7 @@ pub fn send_payables_within_batch( consuming_wallet: Wallet, pending_nonce: U256, new_fingerprints_recipient: Recipient, - accounts: QualifiedPayablesRipePack, + accounts: PricedQualifiedPayables, ) -> Box, Error = PayableTransactionError> + 'static> { debug!( @@ -335,12 +335,11 @@ pub fn send_payables_within_batch( } pub fn create_blockchain_agent_web3( - qualified_payables: QualifiedPayablesRawPack, - gas_limit_const_part: u128, blockchain_agent_future_result: BlockchainAgentFutureResult, + gas_limit_const_part: u128, wallet: Wallet, chain: Chain, -) -> (Box, QualifiedPayablesRipePack) { +) -> Box { let transaction_fee_balance_in_minor_units = blockchain_agent_future_result.transaction_fee_balance; let masq_token_balance_in_minor_units = blockchain_agent_future_result.masq_token_balance; @@ -348,14 +347,13 @@ pub fn create_blockchain_agent_web3( transaction_fee_balance_in_minor_units, masq_token_balance_in_minor_units, ); - BlockchainAgentWeb3::new( - qualified_payables, + Box::new(BlockchainAgentWeb3::new( blockchain_agent_future_result.gas_price_wei.as_u128(), gas_limit_const_part, wallet, cons_wallet_balances, chain, - ) + )) } #[cfg(test)] @@ -365,7 +363,7 @@ mod tests { use crate::accountant::gwei_to_wei; use crate::accountant::test_utils::{ make_payable_account, make_payable_account_with_wallet_and_balance_and_timestamp_opt, - make_ripe_qualified_payables, + make_priced_qualified_payables, }; use crate::blockchain::bip32::Bip32EncryptionKeyProvider; use crate::blockchain::blockchain_agent::agent_web3::WEB3_MAXIMAL_GAS_LIMIT_MARGIN; @@ -466,8 +464,10 @@ mod tests { let consuming_wallet = make_paying_wallet(b"paying_wallet"); let account_1 = make_payable_account(1); let account_2 = make_payable_account(2); - let accounts = - make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]); + let accounts = make_priced_qualified_payables(vec![ + (account_1, 111_111_111), + (account_2, 222_222_222), + ]); let result = sign_and_append_multiple_payments( &logger, @@ -519,9 +519,9 @@ mod tests { nonces: 123,456,789...123,456,791\n\ \n\ [wallet address] [payment wei] [gas price wei]\n\ - 0x0000000000000000000000000000000077313233 900,000,000,000,000,000 123,456,789\n\ - 0x0000000000000000000000000000000077353535 123,456,789 234,567,890\n\ - 0x0000000000000000000000000000000077393837 33,355,666,000,000,000 345,678,901\n"; + 0x0000000000000000000000000077616c6c657430 900,000,000,000,000,000 246,913,578\n\ + 0x0000000000000000000000000077616c6c657431 123,456,789 493,827,156\n\ + 0x0000000000000000000000000077616c6c657432 33,355,666,000,000,000 740,740,734\n"; test_transmission_log( 1, @@ -546,9 +546,9 @@ mod tests { nonces: 100...102\n\ \n\ [wallet address] [payment wei] [gas price wei]\n\ - 0x0000000000000000000000000000000077313233 5,400,000,000,000 123,456,789\n\ - 0x0000000000000000000000000000000077353535 10,000,000,000,000 234,567,890\n\ - 0x0000000000000000000000000000000077393837 44,444,555 345,678,901\n"; + 0x0000000000000000000000000077616c6c657430 5,400,000,000,000 246,913,578\n\ + 0x0000000000000000000000000077616c6c657431 10,000,000,000,000 493,827,156\n\ + 0x0000000000000000000000000077616c6c657432 44,444,555 740,740,734\n"; test_transmission_log( 2, @@ -569,9 +569,9 @@ mod tests { nonces: 1...3\n\ \n\ [wallet address] [payment wei] [gas price wei]\n\ - 0x0000000000000000000000000000000077313233 45,000,888 123,456,789\n\ - 0x0000000000000000000000000000000077353535 1,999,999 234,567,890\n\ - 0x0000000000000000000000000000000077393837 444,444,555 345,678,901\n"; + 0x0000000000000000000000000077616c6c657430 45,000,888 246,913,578\n\ + 0x0000000000000000000000000077616c6c657431 1,999,999 493,827,156\n\ + 0x0000000000000000000000000077616c6c657432 444,444,555 740,740,734\n"; test_transmission_log( 3, @@ -589,26 +589,19 @@ mod tests { pending_nonce: U256, expected_result: &str, ) { - let account_1 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( - make_wallet("w123"), - payments[0], - None, - ); - let account_2 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( - make_wallet("w555"), - payments[1], - None, - ); - let account_3 = make_payable_account_with_wallet_and_balance_and_timestamp_opt( - make_wallet("w987"), - payments[2], - None, - ); - let accounts_to_process = make_ripe_qualified_payables(vec![ - (account_1, 123_456_789), - (account_2, 234_567_890), - (account_3, 345_678_901), - ]); + let accounts_to_process_seeds = payments + .iter() + .enumerate() + .map(|(i, payment)| { + let wallet = make_wallet(&format!("wallet{}", i)); + let gas_price = (i as u128 + 1) * 2 * 123_456_789; + let account = make_payable_account_with_wallet_and_balance_and_timestamp_opt( + wallet, *payment, None, + ); + (account, gas_price) + }) + .collect(); + let accounts_to_process = make_priced_qualified_payables(accounts_to_process_seeds); let result = transmission_log(chain, &accounts_to_process, pending_nonce); @@ -678,7 +671,7 @@ mod tests { fn test_send_payables_within_batch( test_name: &str, - accounts: QualifiedPayablesRipePack, + accounts: PricedQualifiedPayables, expected_result: Result, PayableTransactionError>, port: u16, ) { @@ -764,7 +757,10 @@ mod tests { test_send_payables_within_batch( "send_payables_within_batch_works", - make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 222_222_222)]), + make_priced_qualified_payables(vec![ + (account_1, 111_111_111), + (account_2, 222_222_222), + ]), expected_result, port, ); @@ -772,7 +768,7 @@ mod tests { #[test] fn send_payables_within_batch_fails_on_submit_batch_call() { - let accounts = make_ripe_qualified_payables(vec![ + let accounts = make_priced_qualified_payables(vec![ (make_payable_account(1), 111_222_333), (make_payable_account(2), 222_333_444), ]); @@ -839,7 +835,10 @@ mod tests { test_send_payables_within_batch( "send_payables_within_batch_all_payments_fail", - make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), + make_priced_qualified_payables(vec![ + (account_1, 111_111_111), + (account_2, 111_111_111), + ]), expected_result, port, ); @@ -879,7 +878,10 @@ mod tests { test_send_payables_within_batch( "send_payables_within_batch_one_payment_works_the_other_fails", - make_ripe_qualified_payables(vec![(account_1, 111_111_111), (account_2, 111_111_111)]), + make_priced_qualified_payables(vec![ + (account_1, 111_111_111), + (account_2, 111_111_111), + ]), expected_result, port, ); diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index 6a4762673..ac08ebd98 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -14,7 +14,7 @@ use futures::Future; use masq_lib::blockchains::chains::Chain; use web3::types::Address; use masq_lib::logger::Logger; -use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesRawPack, QualifiedPayablesRipePack}; +use crate::accountant::scanners::payable_scanner_extension::msgs::{UnpricedQualifiedPayables, PricedQualifiedPayables}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TransactionReceiptResult; @@ -35,14 +35,8 @@ pub trait BlockchainInterface { fn introduce_blockchain_agent( &self, - qualified_payables: QualifiedPayablesRawPack, consuming_wallet: Wallet, - ) -> Box< - dyn Future< - Item = (Box, QualifiedPayablesRipePack), - Error = BlockchainAgentBuildError, - >, - >; + ) -> Box, Error = BlockchainAgentBuildError>>; fn process_transaction_receipts( &self, @@ -54,7 +48,7 @@ pub trait BlockchainInterface { logger: Logger, agent: Box, fingerprints_recipient: Recipient, - affordable_accounts: QualifiedPayablesRipePack, + affordable_accounts: PricedQualifiedPayables, ) -> Box, Error = PayableTransactionError>>; as_any_ref_in_trait!(); diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index d9b54a39d..03513fb05 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -45,7 +45,7 @@ impl BlockchainInterfaceInitializer { #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesRawPack, QualifiedPayablesRipePack, QualifiedPayablesWithGasPrice, + PricedQualifiedPayables, QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, }; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; @@ -80,24 +80,29 @@ mod tests { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = - QualifiedPayablesRawPack::from(vec![account_1.clone(), account_2.clone()]); + let qualified_payables_without_price = + UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); let payable_wallet = make_wallet("payable"); - let (blockchain_agent, ripe_qualified_payables) = result - .introduce_blockchain_agent(raw_qualified_payables, payable_wallet.clone()) + let blockchain_agent = result + .introduce_blockchain_agent(payable_wallet.clone()) .wait() .unwrap(); assert_eq!(blockchain_agent.consuming_wallet(), &payable_wallet); - let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000, chain); - let expected_ripe_qualified_payables = QualifiedPayablesRipePack { + let priced_qualified_payables = + blockchain_agent.price_qualified_payables(qualified_payables_without_price); + let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000); + let expected_priced_qualified_payables = PricedQualifiedPayables { payables: vec![ QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin), QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin), ], }; - assert_eq!(ripe_qualified_payables, expected_ripe_qualified_payables); assert_eq!( - blockchain_agent.estimated_transaction_fee_total(), + priced_qualified_payables, + expected_priced_qualified_payables + ); + assert_eq!( + blockchain_agent.estimated_transaction_fee_total(&priced_qualified_payables), 190_652_800_000_000 ); } diff --git a/node/src/sub_lib/blockchain_bridge.rs b/node/src/sub_lib/blockchain_bridge.rs index 24c88ac9a..669e37042 100644 --- a/node/src/sub_lib/blockchain_bridge.rs +++ b/node/src/sub_lib/blockchain_bridge.rs @@ -1,7 +1,7 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. use crate::accountant::scanners::payable_scanner_extension::msgs::{ - QualifiedPayablesMessage, QualifiedPayablesRipePack, + PricedQualifiedPayables, QualifiedPayablesMessage, }; use crate::accountant::{RequestTransactionReceipts, ResponseSkeleton, SkeletonOptHolder}; use crate::blockchain::blockchain_agent::BlockchainAgent; @@ -42,14 +42,14 @@ impl Debug for BlockchainBridgeSubs { #[derive(Message)] pub struct OutboundPaymentsInstructions { - pub affordable_accounts: QualifiedPayablesRipePack, + pub affordable_accounts: PricedQualifiedPayables, pub agent: Box, pub response_skeleton_opt: Option, } impl OutboundPaymentsInstructions { pub fn new( - affordable_accounts: QualifiedPayablesRipePack, + affordable_accounts: PricedQualifiedPayables, agent: Box, response_skeleton_opt: Option, ) -> Self { From 5ebae769405543b9186d1dd56b786ef796c32870 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Sat, 28 Jun 2025 16:30:07 +0200 Subject: [PATCH 13/17] GH-638: added warning --- .../payable_scanner_extension/msgs.rs | 6 +- .../payable_scanner_extension/test_utils.rs | 4 +- node/src/accountant/test_utils.rs | 7 +- .../blockchain/blockchain_agent/agent_web3.rs | 379 +++++++++++++++--- node/src/blockchain/blockchain_bridge.rs | 20 +- .../blockchain_interface_web3/mod.rs | 12 +- .../blockchain_interface_web3/utils.rs | 4 +- .../blockchain/blockchain_interface/mod.rs | 2 +- .../blockchain_interface_initializer.rs | 10 +- 9 files changed, 353 insertions(+), 91 deletions(-) diff --git a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs index a89a1e73d..1e9dbe59d 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/msgs.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/msgs.rs @@ -50,7 +50,7 @@ impl QualifiedPayablesBeforeGasPriceSelection { #[derive(Debug, PartialEq, Eq, Clone)] pub struct PricedQualifiedPayables { - pub payables: Vec, + pub payables: Vec, } impl Into> for PricedQualifiedPayables { @@ -63,12 +63,12 @@ impl Into> for PricedQualifiedPayables { } #[derive(Debug, PartialEq, Eq, Clone)] -pub struct QualifiedPayablesWithGasPrice { +pub struct QualifiedPayableWithGasPrice { pub payable: PayableAccount, pub gas_price_minor: u128, } -impl QualifiedPayablesWithGasPrice { +impl QualifiedPayableWithGasPrice { pub fn new(payable: PayableAccount, gas_price_minor: u128) -> Self { Self { payable, diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index e27bad120..63947b8f2 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -36,9 +36,9 @@ impl Default for BlockchainAgentMock { impl BlockchainAgent for BlockchainAgentMock { fn price_qualified_payables( &self, - qualified_payables: UnpricedQualifiedPayables, + _qualified_payables: UnpricedQualifiedPayables, ) -> PricedQualifiedPayables { - todo!() + unimplemented!("not needed yet") } fn estimated_transaction_fee_total( diff --git a/node/src/accountant/test_utils.rs b/node/src/accountant/test_utils.rs index dd02a2cdf..a186ff016 100644 --- a/node/src/accountant/test_utils.rs +++ b/node/src/accountant/test_utils.rs @@ -17,9 +17,8 @@ use crate::accountant::db_access_objects::utils::{ }; use crate::accountant::payment_adjuster::{Adjustment, AnalysisError, PaymentAdjuster}; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - BlockchainAgentWithContextMessage, PricedQualifiedPayables, - QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesWithGasPrice, - UnpricedQualifiedPayables, + BlockchainAgentWithContextMessage, PricedQualifiedPayables, QualifiedPayableWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, UnpricedQualifiedPayables, }; use crate::accountant::scanners::payable_scanner_extension::PreparedAdjustment; use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableThresholdsGauge; @@ -1508,7 +1507,7 @@ pub fn make_priced_qualified_payables( PricedQualifiedPayables { payables: inputs .into_iter() - .map(|(payable, gas_price_minor)| QualifiedPayablesWithGasPrice { + .map(|(payable, gas_price_minor)| QualifiedPayableWithGasPrice { payable, gas_price_minor, }) diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index b4a25c1e8..257cdb98f 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -1,16 +1,23 @@ // Copyright (c) 2019, MASQ (https://masq.ai) and/or its affiliates. All rights reserved. +use crate::accountant::comma_joined_stringifiable; use crate::accountant::scanners::payable_scanner_extension::msgs::{ - PricedQualifiedPayables, QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, + PricedQualifiedPayables, QualifiedPayableWithGasPrice, UnpricedQualifiedPayables, }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::sub_lib::wallet::Wallet; +use itertools::{Either, Itertools}; use masq_lib::blockchains::chains::Chain; +use masq_lib::logger::Logger; +use masq_lib::utils::ExpectValue; +use thousands::Separable; +use web3::types::Address; #[derive(Debug, Clone)] pub struct BlockchainAgentWeb3 { + logger: Logger, latest_gas_price_wei: u128, gas_limit_const_part: u128, consuming_wallet: Wallet, @@ -23,35 +30,66 @@ impl BlockchainAgent for BlockchainAgentWeb3 { &self, qualified_payables: UnpricedQualifiedPayables, ) -> PricedQualifiedPayables { - let priced_qualified_payables = qualified_payables - .payables - .into_iter() - .map(|payable_without_gas_price| { - let selected_gas_price_wei = - match payable_without_gas_price.previous_attempt_gas_price_minor_opt { - None => self.latest_gas_price_wei, - Some(previous_price) if self.latest_gas_price_wei < previous_price => { - previous_price - } - Some(_) => self.latest_gas_price_wei, - }; - - let gas_price_increased_by_margin_wei = - increase_gas_price_by_margin(selected_gas_price_wei); - - let price_ceiling = self.chain.rec().gas_price_safe_ceiling_minor; - let checked_gas_price_wei = if gas_price_increased_by_margin_wei > price_ceiling { - price_ceiling - } else { - gas_price_increased_by_margin_wei - }; + let warning_data_collector_opt = + self.set_up_warning_data_collector_opt(&qualified_payables); + + let init: ( + Vec, + Option, + ) = (vec![], warning_data_collector_opt); + let (priced_qualified_payables, warning_data_collector_opt) = + qualified_payables.payables.into_iter().fold( + init, + |(mut priced_payables, mut warning_data_collector_opt), unpriced_payable| { + let selected_gas_price_wei = + match unpriced_payable.previous_attempt_gas_price_minor_opt { + None => self.latest_gas_price_wei, + Some(previous_price) if self.latest_gas_price_wei < previous_price => { + previous_price + } + Some(_) => self.latest_gas_price_wei, + }; + + let gas_price_increased_by_margin_wei = + increase_gas_price_by_margin(selected_gas_price_wei); + + let price_ceiling_wei = self.chain.rec().gas_price_safe_ceiling_minor; + let checked_gas_price_wei = + if gas_price_increased_by_margin_wei > price_ceiling_wei { + warning_data_collector_opt.as_mut().map(|collector| { + match collector.data.as_mut() { + Either::Left(new_payable_data) => { + new_payable_data + .addresses + .push(unpriced_payable.payable.wallet.address()); + new_payable_data.gas_price_above_limit_wei = + gas_price_increased_by_margin_wei + } + Either::Right(retry_payable_data) => retry_payable_data + .addresses_and_gas_price_value_above_limit_wei + .push(( + unpriced_payable.payable.wallet.address(), + gas_price_increased_by_margin_wei, + )), + } + }); + price_ceiling_wei + } else { + gas_price_increased_by_margin_wei + }; + + priced_payables.push(QualifiedPayableWithGasPrice::new( + unpriced_payable.payable, + checked_gas_price_wei, + )); + + (priced_payables, warning_data_collector_opt) + }, + ); + + warning_data_collector_opt + .map(|collector| collector.log_warning_if_some_reason(&self.logger, self.chain)); - QualifiedPayablesWithGasPrice::new( - payable_without_gas_price.payable, - checked_gas_price_wei, - ) - }) - .collect(); PricedQualifiedPayables { payables: priced_qualified_payables, } @@ -82,6 +120,89 @@ impl BlockchainAgent for BlockchainAgentWeb3 { } } +struct GasPriceAboveLimitWarningReporter { + data: Either, +} + +impl GasPriceAboveLimitWarningReporter { + fn log_warning_if_some_reason(self, logger: &Logger, chain: Chain) { + let ceiling_value_wei = chain.rec().gas_price_safe_ceiling_minor; + match self.data { + Either::Left(new_payable_data) => { + if !new_payable_data.addresses.is_empty() { + warning!( + logger, + "{}", + Self::new_payables_warning_msg(new_payable_data, ceiling_value_wei) + ) + } + } + Either::Right(retry_payable_data) => { + if !retry_payable_data + .addresses_and_gas_price_value_above_limit_wei + .is_empty() + { + warning!( + logger, + "{}", + Self::retry_payable_warning_msg(retry_payable_data, ceiling_value_wei) + ) + } + } + } + } + + fn new_payables_warning_msg( + new_payable_warning_data: NewPayableWarningData, + ceiling_value_wei: u128, + ) -> String { + let accounts = comma_joined_stringifiable(&new_payable_warning_data.addresses, |address| { + format!("{:?}", address) + }); + format!( + "Calculated gas price {} wei for txs to {} is over the spend limit {} wei.", + new_payable_warning_data + .gas_price_above_limit_wei + .separate_with_commas(), + accounts, + ceiling_value_wei.separate_with_commas() + ) + } + + fn retry_payable_warning_msg( + retry_payable_warning_data: RetryPayableWarningData, + ceiling_value_wei: u128, + ) -> String { + let accounts = retry_payable_warning_data + .addresses_and_gas_price_value_above_limit_wei + .into_iter() + .map(|(address, calculated_price_wei)| { + format!( + "{} wei for tx to {:?}", + calculated_price_wei.separate_with_commas(), + address + ) + }) + .join(", "); + format!( + "Calculated gas price {} surplussed the spend limit {} wei.", + accounts, + ceiling_value_wei.separate_with_commas() + ) + } +} + +#[derive(Default)] +struct NewPayableWarningData { + addresses: Vec
, + gas_price_above_limit_wei: u128, +} + +#[derive(Default)] +struct RetryPayableWarningData { + addresses_and_gas_price_value_above_limit_wei: Vec<(Address, u128)>, +} + // 64 * (64 - 12) ... std transaction has data of 64 bytes and 12 bytes are never used with us; // each non-zero byte costs 64 units of gas pub const WEB3_MAXIMAL_GAS_LIMIT_MARGIN: u128 = 3328; @@ -95,6 +216,7 @@ impl BlockchainAgentWeb3 { chain: Chain, ) -> BlockchainAgentWeb3 { Self { + logger: Logger::new("BlockchainAgentWeb3"), latest_gas_price_wei, gas_limit_const_part, consuming_wallet, @@ -102,26 +224,55 @@ impl BlockchainAgentWeb3 { chain, } } + + fn set_up_warning_data_collector_opt( + &self, + qualified_payables: &UnpricedQualifiedPayables, + ) -> Option { + self.logger.warning_enabled().then(|| { + let is_retry = Self::is_retry(qualified_payables); + GasPriceAboveLimitWarningReporter { + data: if !is_retry { + Either::Left(NewPayableWarningData::default()) + } else { + Either::Right(RetryPayableWarningData::default()) + }, + } + }) + } + + fn is_retry(qualified_payables: &UnpricedQualifiedPayables) -> bool { + qualified_payables + .payables + .first() + .expectv("payable") + .previous_attempt_gas_price_minor_opt + .is_some() + } } #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - PricedQualifiedPayables, QualifiedPayablesBeforeGasPriceSelection, - QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, + PricedQualifiedPayables, QualifiedPayableWithGasPrice, + QualifiedPayablesBeforeGasPriceSelection, UnpricedQualifiedPayables, }; use crate::accountant::test_utils::{ make_payable_account, make_unpriced_qualified_payables_for_retry_mode, }; use crate::blockchain::blockchain_agent::agent_web3::{ - BlockchainAgentWeb3, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, + BlockchainAgentWeb3, GasPriceAboveLimitWarningReporter, NewPayableWarningData, + RetryPayableWarningData, WEB3_MAXIMAL_GAS_LIMIT_MARGIN, }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::test_utils::make_wallet; use masq_lib::blockchains::chains::Chain; + use masq_lib::logger::Logger; + use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; + use thousands::Separable; use web3::types::U256; #[test] @@ -131,6 +282,8 @@ mod tests { #[test] fn returns_correct_priced_qualified_payables_for_new_payable_scan() { + init_test_logging(); + let test_name = "returns_correct_priced_qualified_payables_for_new_payable_scan"; let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -138,33 +291,49 @@ mod tests { }; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let qualified_payables_without_price = + let address_1 = account_1.wallet.address(); + let address_2 = account_2.wallet.address(); + let unpriced_qualified_payables = UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); let rpc_gas_price_wei = 555_666_777; let chain = TEST_DEFAULT_CHAIN; - let subject = BlockchainAgentWeb3::new( + let mut subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + subject.logger = Logger::new(test_name); let priced_qualified_payables = - subject.price_qualified_payables(qualified_payables_without_price); + subject.price_qualified_payables(unpriced_qualified_payables); let gas_price_with_margin_wei = increase_gas_price_by_margin(rpc_gas_price_wei); let expected_result = PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin_wei), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin_wei), + QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin_wei), + QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin_wei), ], }; assert_eq!(priced_qualified_payables, expected_result); + let msg_that_should_not_occur = { + let mut new_payable_data = NewPayableWarningData::default(); + new_payable_data.addresses = vec![address_1, address_2]; + + GasPriceAboveLimitWarningReporter::new_payables_warning_msg( + new_payable_data, + chain.rec().gas_price_safe_ceiling_minor, + ) + }; + TestLogHandler::new() + .exists_no_log_containing(&format!("WARN: {test_name}: {msg_that_should_not_occur}")); } #[test] fn returns_correct_priced_qualified_payables_for_retry_payable_scan() { + init_test_logging(); + let test_name = "returns_correct_priced_qualified_payables_for_retry_payable_scan"; let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -177,7 +346,7 @@ mod tests { let account_3 = make_payable_account(56); let account_4 = make_payable_account(78); let account_5 = make_payable_account(90); - let qualified_payables_without_price = UnpricedQualifiedPayables { + let unpriced_qualified_payables = UnpricedQualifiedPayables { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), @@ -201,16 +370,17 @@ mod tests { ), ], }; - let subject = BlockchainAgentWeb3::new( + let mut subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + subject.logger = Logger::new(test_name); let priced_qualified_payables = - subject.price_qualified_payables(qualified_payables_without_price); + subject.price_qualified_payables(unpriced_qualified_payables); let expected_result = { let gas_price_account_wei_1 = increase_gas_price_by_margin(rpc_gas_price_wei); @@ -220,19 +390,39 @@ mod tests { let gas_price_account_wei_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789); PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_wei_1), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_wei_2), - QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_wei_3), - QualifiedPayablesWithGasPrice::new(account_4, gas_price_account_wei_4), - QualifiedPayablesWithGasPrice::new(account_5, gas_price_account_wei_5), + QualifiedPayableWithGasPrice::new(account_1, gas_price_account_wei_1), + QualifiedPayableWithGasPrice::new(account_2, gas_price_account_wei_2), + QualifiedPayableWithGasPrice::new(account_3, gas_price_account_wei_3), + QualifiedPayableWithGasPrice::new(account_4, gas_price_account_wei_4), + QualifiedPayableWithGasPrice::new(account_5, gas_price_account_wei_5), ], } }; assert_eq!(priced_qualified_payables, expected_result); + let msg_that_should_not_occur = { + let mut retry_payable_data = RetryPayableWarningData::default(); + retry_payable_data.addresses_and_gas_price_value_above_limit_wei = expected_result + .payables + .into_iter() + .map(|payable_with_gas_price| { + ( + payable_with_gas_price.payable.wallet.address(), + payable_with_gas_price.gas_price_minor, + ) + }) + .collect(); + GasPriceAboveLimitWarningReporter::retry_payable_warning_msg( + retry_payable_data, + chain.rec().gas_price_safe_ceiling_minor, + ) + }; + TestLogHandler::new() + .exists_no_log_containing(&format!("WARN: {test_name}: {}", msg_that_should_not_occur)); } #[test] fn new_payables_gas_price_ceiling_test_if_latest_price_is_a_border_value() { + let test_name = "new_payables_gas_price_ceiling_test_if_latest_price_is_a_border_value"; let chain = TEST_DEFAULT_CHAIN; let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; @@ -244,8 +434,10 @@ mod tests { let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + test_name, chain, rpc_gas_price_wei, + 50_000_000_001, ); assert!( @@ -258,30 +450,39 @@ mod tests { #[test] fn new_payables_gas_price_ceiling_test_if_latest_price_is_a_bit_bigger_even_with_no_margin() { + let test_name = "new_payables_gas_price_ceiling_test_if_latest_price_is_a_bit_bigger_even_with_no_margin"; let chain = TEST_DEFAULT_CHAIN; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + test_name, chain, ceiling_gas_price_wei + 1, + 65_000_000_001, ); } #[test] fn new_payables_gas_price_ceiling_test_if_latest_price_is_just_gigantic() { + let test_name = "new_payables_gas_price_ceiling_test_if_latest_price_is_just_gigantic"; let chain = TEST_DEFAULT_CHAIN; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + test_name, chain, 10 * ceiling_gas_price_wei, + 650_000_000_000, ); } fn test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( + test_name: &str, chain: Chain, rpc_gas_price_wei: u128, + expected_calculated_surplus_value_wei: u128, ) { + init_test_logging(); let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { @@ -292,27 +493,40 @@ mod tests { let account_2 = make_payable_account(34); let qualified_payables = UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); - let subject = BlockchainAgentWeb3::new( + let mut subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + subject.logger = Logger::new(test_name); let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); let expected_result = PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, ceiling_gas_price_wei), - QualifiedPayablesWithGasPrice::new(account_2, ceiling_gas_price_wei), + QualifiedPayableWithGasPrice::new(account_1.clone(), ceiling_gas_price_wei), + QualifiedPayableWithGasPrice::new(account_2.clone(), ceiling_gas_price_wei), ], }; assert_eq!(priced_qualified_payables, expected_result); + TestLogHandler::new().exists_log_containing(&format!( + "WARN: {test_name}: Calculated gas price {} wei for txs to {}, {} is over the spend \ + limit {} wei.", + expected_calculated_surplus_value_wei.separate_with_commas(), + account_1.wallet, + account_2.wallet, + chain + .rec() + .gas_price_safe_ceiling_minor + .separate_with_commas() + )); } #[test] fn retry_payables_gas_price_ceiling_test_of_border_value_if_the_latest_fetch_being_bigger() { + let test_name = "retry_payables_gas_price_ceiling_test_of_border_value_if_the_latest_fetch_being_bigger"; let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); @@ -328,11 +542,16 @@ mod tests { (account_1.clone(), rpc_gas_price_wei - 1), (account_2.clone(), rpc_gas_price_wei - 2), ]); + let expected_surpluses_wallet_and_wei_as_text = "\ + 50,000,000,001 wei for tx to 0x00000000000000000000000077616c6c65743132, 50,000,000,001 \ + wei for tx to 0x00000000000000000000000077616c6c65743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name, chain, rpc_gas_price_wei, raw_qualified_payables, + expected_surpluses_wallet_and_wei_as_text, ); assert!( @@ -346,6 +565,7 @@ mod tests { #[test] fn retry_payables_gas_price_ceiling_test_of_border_value_if_the_previous_attempt_being_bigger() { + let test_name = "retry_payables_gas_price_ceiling_test_of_border_value_if_the_previous_attempt_being_bigger"; let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); @@ -360,37 +580,49 @@ mod tests { (account_1.clone(), border_gas_price_wei), (account_2.clone(), border_gas_price_wei), ]); + let expected_surpluses_wallet_and_wei_as_text = "50,000,000,001 wei for tx to \ + 0x00000000000000000000000077616c6c65743132, 50,000,000,001 wei for tx to \ + 0x00000000000000000000000077616c6c65743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name, chain, rpc_gas_price_wei, raw_qualified_payables, + expected_surpluses_wallet_and_wei_as_text, ); - assert!(check_value_wei > ceiling_gas_price_wei); } #[test] fn retry_payables_gas_price_ceiling_test_of_big_value_if_the_latest_fetch_being_bigger() { + let test_name = + "retry_payables_gas_price_ceiling_test_of_big_value_if_the_latest_fetch_being_bigger"; let chain = TEST_DEFAULT_CHAIN; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let fetched_gas_price_wei = ceiling_gas_price_wei - 1; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ - (account_1.clone(), fetched_gas_price_wei - 1), - (account_2.clone(), fetched_gas_price_wei - 2), + (account_1.clone(), fetched_gas_price_wei - 2), + (account_2.clone(), fetched_gas_price_wei - 3), ]); + let expected_surpluses_wallet_and_wei_as_text = "64,999,999,998 wei for tx to \ + 0x00000000000000000000000077616c6c65743132, 64,999,999,998 wei for tx to \ + 0x00000000000000000000000077616c6c65743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name, chain, fetched_gas_price_wei, raw_qualified_payables, + expected_surpluses_wallet_and_wei_as_text, ); } #[test] fn retry_payables_gas_price_ceiling_test_of_big_value_if_the_previous_attempt_being_bigger() { + let test_name = "retry_payables_gas_price_ceiling_test_of_big_value_if_the_previous_attempt_being_bigger"; let chain = TEST_DEFAULT_CHAIN; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let account_1 = make_payable_account(12); @@ -399,16 +631,22 @@ mod tests { (account_1.clone(), ceiling_gas_price_wei - 1), (account_2.clone(), ceiling_gas_price_wei - 2), ]); + let expected_surpluses_wallet_and_wei_as_text = "64,999,999,998 wei for tx to \ + 0x00000000000000000000000077616c6c65743132, 64,999,999,997 wei for tx to \ + 0x00000000000000000000000077616c6c65743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name, chain, ceiling_gas_price_wei - 3, raw_qualified_payables, + expected_surpluses_wallet_and_wei_as_text, ); } #[test] fn retry_payables_gas_price_ceiling_test_of_giant_value_for_the_latest_fetch() { + let test_name = "retry_payables_gas_price_ceiling_test_of_giant_value_for_the_latest_fetch"; let chain = TEST_DEFAULT_CHAIN; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let fetched_gas_price_wei = 10 * ceiling_gas_price_wei; @@ -420,19 +658,28 @@ mod tests { (account_1.clone(), ceiling_gas_price_wei), (account_2.clone(), ceiling_gas_price_wei), ]); + let expected_surpluses_wallet_and_wei_as_text = + "650,000,000,000 wei for tx to 0x00000000000000000000\ + 000077616c6c65743132, 650,000,000,000 wei for tx to 0x00000000000000000000000077616c6c6\ + 5743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name, chain, fetched_gas_price_wei, raw_qualified_payables, + expected_surpluses_wallet_and_wei_as_text, ); } fn test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( + test_name: &str, chain: Chain, rpc_gas_price_wei: u128, qualified_payables: UnpricedQualifiedPayables, + expected_surpluses_wallet_and_wei_as_text: &str, ) { + init_test_logging(); let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = ConsumingWalletBalances { transaction_fee_balance_in_minor_units: Default::default(), @@ -445,21 +692,27 @@ mod tests { .clone() .into_iter() .map(|payable| { - QualifiedPayablesWithGasPrice::new(payable.payable, ceiling_gas_price_wei) + QualifiedPayableWithGasPrice::new(payable.payable, ceiling_gas_price_wei) }) .collect(), }; - let subject = BlockchainAgentWeb3::new( + let mut subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, consuming_wallet, consuming_wallet_balances, chain, ); + subject.logger = Logger::new(test_name); let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); assert_eq!(priced_qualified_payables, expected_priced_payables); + TestLogHandler::new().exists_log_containing(&format!( + "WARN: {test_name}: Calculated gas price {expected_surpluses_wallet_and_wei_as_text} \ + surplussed the spend limit {} wei.", + ceiling_gas_price_wei.separate_with_commas() + )); } #[test] @@ -580,4 +833,24 @@ mod tests { * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) ) } + + #[test] + fn blockchain_agent_web3_logs_with_right_name() { + let test_name = "blockchain_agent_web3_logs_with_right_name"; + let subject = BlockchainAgentWeb3::new( + 0, + 0, + make_wallet("abcde"), + ConsumingWalletBalances { + transaction_fee_balance_in_minor_units: U256::from(0), + masq_token_balance_in_minor_units: U256::from(0), + }, + TEST_DEFAULT_CHAIN, + ); + + info!(subject.logger, "{}", test_name); + + TestLogHandler::new() + .exists_log_containing(&format!("INFO: BlockchainAgentWeb3: {}", test_name)); + } } diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 005c2b866..2c8d0b64c 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -597,7 +597,7 @@ mod tests { use std::time::{Duration, SystemTime}; use web3::types::{TransactionReceipt, H160}; use masq_lib::constants::DEFAULT_MAX_BLOCK_COUNT; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, UnpricedQualifiedPayables, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{UnpricedQualifiedPayables, QualifiedPayableWithGasPrice}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt}; impl Handler> for BlockchainBridge { @@ -723,18 +723,10 @@ mod tests { false, ); subject.payable_payments_setup_subs_opt = Some(accountant_recipient); - let qualified_payables_without_price = UnpricedQualifiedPayables { - payables: qualified_payables - .clone() - .into_iter() - .map(|payable| QualifiedPayablesBeforeGasPriceSelection { - payable, - previous_attempt_gas_price_minor_opt: None, - }) - .collect(), - }; + let unpriced_qualified_payables = + UnpricedQualifiedPayables::from(qualified_payables.clone()); let qualified_payables_msg = QualifiedPayablesMessage { - qualified_payables: qualified_payables_without_price.clone(), + qualified_payables: unpriced_qualified_payables.clone(), consuming_wallet: consuming_wallet.clone(), response_skeleton_opt: Some(ResponseSkeleton { client_id: 11122, @@ -755,7 +747,7 @@ mod tests { let expected_ripe_qualified_payables = PricedQualifiedPayables { payables: qualified_payables .into_iter() - .map(|payable| QualifiedPayablesWithGasPrice { + .map(|payable| QualifiedPayableWithGasPrice { payable, gas_price_minor: increase_gas_price_by_margin(0x230000000), }) @@ -773,7 +765,7 @@ mod tests { ); assert_eq!( actual_agent.estimated_transaction_fee_total( - &actual_agent.price_qualified_payables(qualified_payables_without_price) + &actual_agent.price_qualified_payables(unpriced_qualified_payables) ), 1_791_228_995_698_688 ); diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 77a630319..5b2ccb471 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -460,7 +460,7 @@ mod tests { use std::str::FromStr; use web3::transports::Http; use web3::types::{H256, U256}; - use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesWithGasPrice}; + use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayableWithGasPrice}; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock, TxReceipt, TxStatus}; @@ -847,11 +847,11 @@ mod tests { increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); let expected_ripe_qualified_payables = PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new( + QualifiedPayableWithGasPrice::new( account_1, gas_price_wei_from_rpc_u128_wei_with_margin, ), - QualifiedPayablesWithGasPrice::new( + QualifiedPayableWithGasPrice::new( account_2, gas_price_wei_from_rpc_u128_wei_with_margin, ), @@ -899,9 +899,9 @@ mod tests { increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei + 1); PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_account_1), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_account_2), - QualifiedPayablesWithGasPrice::new(account_3, gas_price_account_3), + QualifiedPayableWithGasPrice::new(account_1, gas_price_account_1), + QualifiedPayableWithGasPrice::new(account_2, gas_price_account_2), + QualifiedPayableWithGasPrice::new(account_3, gas_price_account_3), ], } }; diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs index 1aefa1b03..00489febc 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/utils.rs @@ -2,9 +2,7 @@ use crate::accountant::db_access_objects::payable_dao::PayableAccount; use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable; -use crate::accountant::scanners::payable_scanner_extension::msgs::{ - PricedQualifiedPayables, UnpricedQualifiedPayables, -}; +use crate::accountant::scanners::payable_scanner_extension::msgs::PricedQualifiedPayables; use crate::blockchain::blockchain_agent::agent_web3::BlockchainAgentWeb3; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::PendingPayableFingerprintSeeds; diff --git a/node/src/blockchain/blockchain_interface/mod.rs b/node/src/blockchain/blockchain_interface/mod.rs index ac08ebd98..242bf433f 100644 --- a/node/src/blockchain/blockchain_interface/mod.rs +++ b/node/src/blockchain/blockchain_interface/mod.rs @@ -14,7 +14,7 @@ use futures::Future; use masq_lib::blockchains::chains::Chain; use web3::types::Address; use masq_lib::logger::Logger; -use crate::accountant::scanners::payable_scanner_extension::msgs::{UnpricedQualifiedPayables, PricedQualifiedPayables}; +use crate::accountant::scanners::payable_scanner_extension::msgs::{PricedQualifiedPayables}; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::{BlockMarker, BlockScanRange, PendingPayableFingerprintSeeds}; use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::TransactionReceiptResult; diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index 03513fb05..362239c06 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -45,7 +45,7 @@ impl BlockchainInterfaceInitializer { #[cfg(test)] mod tests { use crate::accountant::scanners::payable_scanner_extension::msgs::{ - PricedQualifiedPayables, QualifiedPayablesWithGasPrice, UnpricedQualifiedPayables, + PricedQualifiedPayables, QualifiedPayableWithGasPrice, UnpricedQualifiedPayables, }; use crate::accountant::test_utils::make_payable_account; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; @@ -80,7 +80,7 @@ mod tests { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let qualified_payables_without_price = + let unpriced_qualified_payables = UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); let payable_wallet = make_wallet("payable"); let blockchain_agent = result @@ -89,12 +89,12 @@ mod tests { .unwrap(); assert_eq!(blockchain_agent.consuming_wallet(), &payable_wallet); let priced_qualified_payables = - blockchain_agent.price_qualified_payables(qualified_payables_without_price); + blockchain_agent.price_qualified_payables(unpriced_qualified_payables); let gas_price_with_margin = increase_gas_price_by_margin(1_000_000_000); let expected_priced_qualified_payables = PricedQualifiedPayables { payables: vec![ - QualifiedPayablesWithGasPrice::new(account_1, gas_price_with_margin), - QualifiedPayablesWithGasPrice::new(account_2, gas_price_with_margin), + QualifiedPayableWithGasPrice::new(account_1, gas_price_with_margin), + QualifiedPayableWithGasPrice::new(account_2, gas_price_with_margin), ], }; assert_eq!( From ba6769be8a1bab662b4ecb19f8309ce7ec8332ef Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Sat, 28 Jun 2025 16:42:39 +0200 Subject: [PATCH 14/17] GH-638: another comment res --- node/src/accountant/scanners/test_utils.rs | 6 ++- .../blockchain/blockchain_agent/agent_web3.rs | 42 ++++--------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/node/src/accountant/scanners/test_utils.rs b/node/src/accountant/scanners/test_utils.rs index 26aa15dc3..2445ff565 100644 --- a/node/src/accountant/scanners/test_utils.rs +++ b/node/src/accountant/scanners/test_utils.rs @@ -23,7 +23,7 @@ use crate::accountant::{ SentPayables, }; use crate::blockchain::blockchain_bridge::RetrieveTransactions; -use crate::sub_lib::blockchain_bridge::OutboundPaymentsInstructions; +use crate::sub_lib::blockchain_bridge::{ConsumingWalletBalances, OutboundPaymentsInstructions}; use crate::sub_lib::wallet::Wallet; use actix::{Message, System}; use itertools::Either; @@ -488,3 +488,7 @@ impl RescheduleScanOnErrorResolverMock { self } } + +pub fn make_zeroed_consuming_wallet_balances() -> ConsumingWalletBalances { + ConsumingWalletBalances::new(0.into(), 0.into()) +} diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 257cdb98f..3c63d511a 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -257,6 +257,7 @@ mod tests { PricedQualifiedPayables, QualifiedPayableWithGasPrice, QualifiedPayablesBeforeGasPriceSelection, UnpricedQualifiedPayables, }; + use crate::accountant::scanners::test_utils::make_zeroed_consuming_wallet_balances; use crate::accountant::test_utils::{ make_payable_account, make_unpriced_qualified_payables_for_retry_mode, }; @@ -273,7 +274,6 @@ mod tests { use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; use thousands::Separable; - use web3::types::U256; #[test] fn constants_are_correct() { @@ -285,10 +285,7 @@ mod tests { init_test_logging(); let test_name = "returns_correct_priced_qualified_payables_for_new_payable_scan"; let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let address_1 = account_1.wallet.address(); @@ -335,10 +332,7 @@ mod tests { init_test_logging(); let test_name = "returns_correct_priced_qualified_payables_for_retry_payable_scan"; let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); @@ -485,10 +479,7 @@ mod tests { init_test_logging(); let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let qualified_payables = @@ -681,10 +672,7 @@ mod tests { ) { init_test_logging(); let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let expected_priced_payables = PricedQualifiedPayables { payables: qualified_payables @@ -719,10 +707,7 @@ mod tests { fn returns_correct_non_computed_values() { let gas_limit_const_part = 44_000; let consuming_wallet = make_wallet("abcde"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::from(456_789), - masq_token_balance_in_minor_units: U256::from(123_000_000), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let subject = BlockchainAgentWeb3::new( 222_333_444, @@ -743,10 +728,7 @@ mod tests { #[test] fn estimated_transaction_fee_works_for_new_payable() { let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let chain = TEST_DEFAULT_CHAIN; @@ -772,10 +754,7 @@ mod tests { #[test] fn estimated_transaction_fee_works_for_retry_payable() { let consuming_wallet = make_wallet("efg"); - let consuming_wallet_balances = ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: Default::default(), - masq_token_balance_in_minor_units: Default::default(), - }; + let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); @@ -841,10 +820,7 @@ mod tests { 0, 0, make_wallet("abcde"), - ConsumingWalletBalances { - transaction_fee_balance_in_minor_units: U256::from(0), - masq_token_balance_in_minor_units: U256::from(0), - }, + make_zeroed_consuming_wallet_balances(), TEST_DEFAULT_CHAIN, ); From ba1935c42230cb1ec25aeaf589f46a23b671c637 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Sat, 28 Jun 2025 17:28:06 +0200 Subject: [PATCH 15/17] GH-638: ref tests with a lot of created accounts --- .../blockchain/blockchain_agent/agent_web3.rs | 155 +++++++++--------- 1 file changed, 73 insertions(+), 82 deletions(-) diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 3c63d511a..745dbd37e 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -267,8 +267,8 @@ mod tests { }; use crate::blockchain::blockchain_agent::BlockchainAgent; use crate::blockchain::blockchain_bridge::increase_gas_price_by_margin; - use crate::sub_lib::blockchain_bridge::ConsumingWalletBalances; use crate::test_utils::make_wallet; + use itertools::Itertools; use masq_lib::blockchains::chains::Chain; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; @@ -335,35 +335,31 @@ mod tests { let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; - let account_1 = make_payable_account(12); - let account_2 = make_payable_account(34); - let account_3 = make_payable_account(56); - let account_4 = make_payable_account(78); - let account_5 = make_payable_account(90); - let unpriced_qualified_payables = UnpricedQualifiedPayables { - payables: vec![ - QualifiedPayablesBeforeGasPriceSelection::new( - account_1.clone(), - Some(rpc_gas_price_wei - 1), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_2.clone(), - Some(rpc_gas_price_wei), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_3.clone(), - Some(rpc_gas_price_wei + 1), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_4.clone(), - Some(rpc_gas_price_wei - 123_456), - ), + let unpriced_qualified_payables = { + let payables = vec![ + rpc_gas_price_wei - 1, + rpc_gas_price_wei, + rpc_gas_price_wei + 1, + rpc_gas_price_wei - 123_456, + rpc_gas_price_wei + 456_789, + ] + .into_iter() + .enumerate() + .map(|(idx, previous_attempt_gas_price_wei)| { + let account = make_payable_account((idx as u64 + 1) * 3_000); QualifiedPayablesBeforeGasPriceSelection::new( - account_5.clone(), - Some(rpc_gas_price_wei + 456_789), - ), - ], + account, + Some(previous_attempt_gas_price_wei), + ) + }) + .collect_vec(); + UnpricedQualifiedPayables { payables } }; + let accounts_from_1_to_5 = unpriced_qualified_payables + .payables + .iter() + .map(|unpriced_payable| unpriced_payable.payable.clone()) + .collect_vec(); let mut subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, 77_777, @@ -377,19 +373,24 @@ mod tests { subject.price_qualified_payables(unpriced_qualified_payables); let expected_result = { - let gas_price_account_wei_1 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_2 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1); - let gas_price_account_wei_4 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789); + let price_wei_for_accounts_from_1_to_5 = vec![ + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei + 1), + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei + 456_789), + ]; + if price_wei_for_accounts_from_1_to_5.len() != accounts_from_1_to_5.len() { + panic!("Corrupted test") + } PricedQualifiedPayables { - payables: vec![ - QualifiedPayableWithGasPrice::new(account_1, gas_price_account_wei_1), - QualifiedPayableWithGasPrice::new(account_2, gas_price_account_wei_2), - QualifiedPayableWithGasPrice::new(account_3, gas_price_account_wei_3), - QualifiedPayableWithGasPrice::new(account_4, gas_price_account_wei_4), - QualifiedPayableWithGasPrice::new(account_5, gas_price_account_wei_5), - ], + payables: accounts_from_1_to_5 + .into_iter() + .zip(price_wei_for_accounts_from_1_to_5.into_iter()) + .map(|(account, previous_attempt_price_wei)| { + QualifiedPayableWithGasPrice::new(account, previous_attempt_price_wei) + }) + .collect_vec(), } }; assert_eq!(priced_qualified_payables, expected_result); @@ -757,34 +758,25 @@ mod tests { let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let rpc_gas_price_wei = 444_555_666; let chain = TEST_DEFAULT_CHAIN; - let account_1 = make_payable_account(12); - let account_2 = make_payable_account(34); - let account_3 = make_payable_account(56); - let account_4 = make_payable_account(78); - let account_5 = make_payable_account(90); - let qualified_payables = UnpricedQualifiedPayables { - payables: vec![ - QualifiedPayablesBeforeGasPriceSelection::new( - account_1.clone(), - Some(rpc_gas_price_wei - 1), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_2.clone(), - Some(rpc_gas_price_wei), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_3.clone(), - Some(rpc_gas_price_wei + 1), - ), - QualifiedPayablesBeforeGasPriceSelection::new( - account_4.clone(), - Some(rpc_gas_price_wei - 123_456), - ), + let unpriced_qualified_payables = { + let payables = vec![ + rpc_gas_price_wei - 1, + rpc_gas_price_wei, + rpc_gas_price_wei + 1, + rpc_gas_price_wei - 123_456, + rpc_gas_price_wei + 456_789, + ] + .into_iter() + .enumerate() + .map(|(idx, previous_attempt_gas_price_wei)| { + let account = make_payable_account((idx as u64 + 1) * 3_000); QualifiedPayablesBeforeGasPriceSelection::new( - account_5.clone(), - Some(rpc_gas_price_wei + 456_789), - ), - ], + account, + Some(previous_attempt_gas_price_wei), + ) + }) + .collect_vec(); + UnpricedQualifiedPayables { payables } }; let subject = BlockchainAgentWeb3::new( rpc_gas_price_wei, @@ -793,24 +785,23 @@ mod tests { consuming_wallet_balances, chain, ); - let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); + let priced_qualified_payables = + subject.price_qualified_payables(unpriced_qualified_payables); let result = subject.estimated_transaction_fee_total(&priced_qualified_payables); - let gas_price_account_wei_1 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_2 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_3 = increase_gas_price_by_margin(rpc_gas_price_wei + 1); - let gas_price_account_wei_4 = increase_gas_price_by_margin(rpc_gas_price_wei); - let gas_price_account_wei_5 = increase_gas_price_by_margin(rpc_gas_price_wei + 456_789); - assert_eq!( - result, - (gas_price_account_wei_1 - + gas_price_account_wei_2 - + gas_price_account_wei_3 - + gas_price_account_wei_4 - + gas_price_account_wei_5) - * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN) - ) + let gas_prices_for_accounts_from_1_to_5 = vec![ + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei + 1), + increase_gas_price_by_margin(rpc_gas_price_wei), + increase_gas_price_by_margin(rpc_gas_price_wei + 456_789), + ]; + let expected_result = gas_prices_for_accounts_from_1_to_5 + .into_iter() + .sum::() + * (77_777 + WEB3_MAXIMAL_GAS_LIMIT_MARGIN); + assert_eq!(result, expected_result) } #[test] From 83795537c9b3362c1282bfcb1dc2eed8f1a344e3 Mon Sep 17 00:00:00 2001 From: Bert <65427484+bertllll@users.noreply.github.com> Date: Sat, 28 Jun 2025 18:07:49 +0200 Subject: [PATCH 16/17] GH-638: fixed chain records with more constants --- .../src/blockchains/blockchain_records.rs | 58 ++++++++----------- masq_lib/src/blockchains/chains.rs | 1 - masq_lib/src/constants.rs | 22 +++++++ .../blockchain/blockchain_agent/agent_web3.rs | 10 ++-- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/masq_lib/src/blockchains/blockchain_records.rs b/masq_lib/src/blockchains/blockchain_records.rs index 3b592f597..067c36a14 100644 --- a/masq_lib/src/blockchains/blockchain_records.rs +++ b/masq_lib/src/blockchains/blockchain_records.rs @@ -2,13 +2,16 @@ use crate::blockchains::chains::Chain; use crate::constants::{ - BASE_MAINNET_CONTRACT_CREATION_BLOCK, BASE_MAINNET_FULL_IDENTIFIER, - BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, BASE_SEPOLIA_FULL_IDENTIFIER, DEV_CHAIN_FULL_IDENTIFIER, - ETH_MAINNET_CONTRACT_CREATION_BLOCK, ETH_MAINNET_FULL_IDENTIFIER, + BASE_GAS_PRICE_CEILING_WEI, BASE_MAINNET_CHAIN_ID, BASE_MAINNET_CONTRACT_CREATION_BLOCK, + BASE_MAINNET_FULL_IDENTIFIER, BASE_SEPOLIA_CHAIN_ID, BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, + BASE_SEPOLIA_FULL_IDENTIFIER, DEV_CHAIN_FULL_IDENTIFIER, DEV_CHAIN_ID, + DEV_GAS_PRICE_CEILING_WEI, ETH_GAS_PRICE_CEIOLING_WEI, ETH_MAINNET_CHAIN_ID, + ETH_MAINNET_CONTRACT_CREATION_BLOCK, ETH_MAINNET_FULL_IDENTIFIER, ETH_ROPSTEN_CHAIN_ID, ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, ETH_ROPSTEN_FULL_IDENTIFIER, - MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, POLYGON_AMOY_CONTRACT_CREATION_BLOCK, - POLYGON_AMOY_FULL_IDENTIFIER, POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, - POLYGON_MAINNET_FULL_IDENTIFIER, + MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, POLYGON_AMOY_CHAIN_ID, + POLYGON_AMOY_CONTRACT_CREATION_BLOCK, POLYGON_AMOY_FULL_IDENTIFIER, + POLYGON_GAS_PRICE_CEILING_WEI, POLYGON_MAINNET_CHAIN_ID, + POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, POLYGON_MAINNET_FULL_IDENTIFIER, }; use ethereum_types::{Address, H160}; @@ -17,64 +20,57 @@ use ethereum_types::{Address, H160}; pub const CHAINS: [BlockchainRecord; 7] = [ BlockchainRecord { self_id: Chain::PolyMainnet, - num_chain_id: 137, + num_chain_id: POLYGON_MAINNET_CHAIN_ID, literal_identifier: POLYGON_MAINNET_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 200_000_000_000, + gas_price_safe_ceiling_minor: POLYGON_GAS_PRICE_CEILING_WEI, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::EthMainnet, - num_chain_id: 1, + num_chain_id: ETH_MAINNET_CHAIN_ID, literal_identifier: ETH_MAINNET_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 100_000_000_000, + gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEIOLING_WEI, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::BaseMainnet, - num_chain_id: 8453, + num_chain_id: BASE_MAINNET_CHAIN_ID, literal_identifier: BASE_MAINNET_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 50_000_000_000, + gas_price_safe_ceiling_minor: BASE_GAS_PRICE_CEILING_WEI, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::BaseSepolia, - num_chain_id: 84532, + num_chain_id: BASE_SEPOLIA_CHAIN_ID, literal_identifier: BASE_SEPOLIA_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 50_000_000_000, + gas_price_safe_ceiling_minor: BASE_GAS_PRICE_CEILING_WEI, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::PolyAmoy, - num_chain_id: 80002, + num_chain_id: POLYGON_AMOY_CHAIN_ID, literal_identifier: POLYGON_AMOY_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 200_000_000_000, + gas_price_safe_ceiling_minor: POLYGON_GAS_PRICE_CEILING_WEI, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::EthRopsten, - num_chain_id: 3, + num_chain_id: ETH_ROPSTEN_CHAIN_ID, literal_identifier: ETH_ROPSTEN_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 100_000_000_000, + gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEIOLING_WEI, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, }, BlockchainRecord { self_id: Chain::Dev, - num_chain_id: 2, + num_chain_id: DEV_CHAIN_ID, literal_identifier: DEV_CHAIN_FULL_IDENTIFIER, - gas_price_default_margin_percents: 30, - gas_price_safe_ceiling_minor: 200_000_000_000, + gas_price_safe_ceiling_minor: DEV_GAS_PRICE_CEILING_WEI, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, }, @@ -85,7 +81,6 @@ pub struct BlockchainRecord { pub self_id: Chain, pub num_chain_id: u64, pub literal_identifier: &'static str, - pub gas_price_default_margin_percents: u8, pub gas_price_safe_ceiling_minor: u128, pub contract: Address, pub contract_creation_block: u64, @@ -213,7 +208,6 @@ mod tests { num_chain_id: 1, self_id: examined_chain, literal_identifier: "eth-mainnet", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 100 * WEIS_IN_GWEI as u128, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, @@ -231,7 +225,6 @@ mod tests { num_chain_id: 3, self_id: examined_chain, literal_identifier: "eth-ropsten", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 100 * WEIS_IN_GWEI as u128, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, @@ -249,7 +242,6 @@ mod tests { num_chain_id: 137, self_id: examined_chain, literal_identifier: "polygon-mainnet", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: POLYGON_MAINNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_MAINNET_CONTRACT_CREATION_BLOCK, @@ -267,7 +259,6 @@ mod tests { num_chain_id: 80002, self_id: examined_chain, literal_identifier: "polygon-amoy", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: POLYGON_AMOY_TESTNET_CONTRACT_ADDRESS, contract_creation_block: POLYGON_AMOY_CONTRACT_CREATION_BLOCK, @@ -285,7 +276,6 @@ mod tests { num_chain_id: 8453, self_id: examined_chain, literal_identifier: "base-mainnet", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 50 * WEIS_IN_GWEI as u128, contract: BASE_MAINNET_CONTRACT_ADDRESS, contract_creation_block: BASE_MAINNET_CONTRACT_CREATION_BLOCK, @@ -303,7 +293,6 @@ mod tests { num_chain_id: 84532, self_id: examined_chain, literal_identifier: "base-sepolia", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 50 * WEIS_IN_GWEI as u128, contract: BASE_SEPOLIA_TESTNET_CONTRACT_ADDRESS, contract_creation_block: BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, @@ -321,7 +310,6 @@ mod tests { num_chain_id: 2, self_id: examined_chain, literal_identifier: "dev", - gas_price_default_margin_percents: 30, gas_price_safe_ceiling_minor: 200 * WEIS_IN_GWEI as u128, contract: MULTINODE_TESTNET_CONTRACT_ADDRESS, contract_creation_block: MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, diff --git a/masq_lib/src/blockchains/chains.rs b/masq_lib/src/blockchains/chains.rs index e43f58edd..b7061d899 100644 --- a/masq_lib/src/blockchains/chains.rs +++ b/masq_lib/src/blockchains/chains.rs @@ -141,7 +141,6 @@ mod tests { num_chain_id: 0, self_id: Chain::PolyMainnet, literal_identifier: "", - gas_price_default_margin_percents: 0, gas_price_safe_ceiling_minor: 0, contract: Default::default(), contract_creation_block: 0, diff --git a/masq_lib/src/constants.rs b/masq_lib/src/constants.rs index 3d09904ad..0d163c34b 100644 --- a/masq_lib/src/constants.rs +++ b/masq_lib/src/constants.rs @@ -95,6 +95,13 @@ pub const CENTRAL_DELIMITER: char = '@'; pub const CHAIN_IDENTIFIER_DELIMITER: char = ':'; //chains +pub const POLYGON_MAINNET_CHAIN_ID: u64 = 137; +pub const POLYGON_AMOY_CHAIN_ID: u64 = 80002; +pub const BASE_MAINNET_CHAIN_ID: u64 = 8453; +pub const BASE_SEPOLIA_CHAIN_ID: u64 = 84532; +pub const ETH_MAINNET_CHAIN_ID: u64 = 1; +pub const ETH_ROPSTEN_CHAIN_ID: u64 = 3; +pub const DEV_CHAIN_ID: u64 = 2; const POLYGON_FAMILY: &str = "polygon"; const ETH_FAMILY: &str = "eth"; const BASE_FAMILY: &str = "base"; @@ -107,6 +114,10 @@ pub const ETH_ROPSTEN_FULL_IDENTIFIER: &str = concatcp!(ETH_FAMILY, LINK, "ropst pub const BASE_MAINNET_FULL_IDENTIFIER: &str = concatcp!(BASE_FAMILY, LINK, MAINNET); pub const BASE_SEPOLIA_FULL_IDENTIFIER: &str = concatcp!(BASE_FAMILY, LINK, "sepolia"); pub const DEV_CHAIN_FULL_IDENTIFIER: &str = "dev"; +pub const POLYGON_GAS_PRICE_CEILING_WEI: u128 = 200_000_000_000; +pub const ETH_GAS_PRICE_CEIOLING_WEI: u128 = 100_000_000_000; +pub const BASE_GAS_PRICE_CEILING_WEI: u128 = 50_000_000_000; +pub const DEV_GAS_PRICE_CEILING_WEI: u128 = 200_000_000_000; #[cfg(test)] mod tests { @@ -171,6 +182,13 @@ mod tests { assert_eq!(VALUE_EXCEEDS_ALLOWED_LIMIT, ACCOUNTANT_PREFIX | 3); assert_eq!(CENTRAL_DELIMITER, '@'); assert_eq!(CHAIN_IDENTIFIER_DELIMITER, ':'); + assert_eq!(POLYGON_MAINNET_CHAIN_ID, 137); + assert_eq!(POLYGON_AMOY_CHAIN_ID, 80002); + assert_eq!(BASE_MAINNET_CHAIN_ID, 8453); + assert_eq!(BASE_SEPOLIA_CHAIN_ID, 84532); + assert_eq!(ETH_MAINNET_CHAIN_ID, 1); + assert_eq!(ETH_ROPSTEN_CHAIN_ID, 3); + assert_eq!(DEV_CHAIN_ID, 2); assert_eq!(POLYGON_FAMILY, "polygon"); assert_eq!(ETH_FAMILY, "eth"); assert_eq!(BASE_FAMILY, "base"); @@ -182,6 +200,10 @@ mod tests { assert_eq!(ETH_ROPSTEN_FULL_IDENTIFIER, "eth-ropsten"); assert_eq!(BASE_SEPOLIA_FULL_IDENTIFIER, "base-sepolia"); assert_eq!(DEV_CHAIN_FULL_IDENTIFIER, "dev"); + assert_eq!(POLYGON_GAS_PRICE_CEILING_WEI, 200_000_000_000); + assert_eq!(ETH_GAS_PRICE_CEIOLING_WEI, 100_000_000_000); + assert_eq!(BASE_GAS_PRICE_CEILING_WEI, 50_000_000_000); + assert_eq!(DEV_GAS_PRICE_CEILING_WEI, 200_000_000_000); assert_eq!( CLIENT_REQUEST_PAYLOAD_CURRENT_VERSION, DataVersion { major: 0, minor: 1 } diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 745dbd37e..421c652e4 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -270,6 +270,7 @@ mod tests { use crate::test_utils::make_wallet; use itertools::Itertools; use masq_lib::blockchains::chains::Chain; + use masq_lib::constants::DEFAULT_GAS_PRICE_MARGIN; use masq_lib::logger::Logger; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; @@ -419,13 +420,12 @@ mod tests { fn new_payables_gas_price_ceiling_test_if_latest_price_is_a_border_value() { let test_name = "new_payables_gas_price_ceiling_test_if_latest_price_is_a_border_value"; let chain = TEST_DEFAULT_CHAIN; - let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; // This should be the value that would surplus the ceiling just slightly if the margin is // applied. // Adding just 1 didn't work, therefore 2 let rpc_gas_price_wei = - ((ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100)) + 2; + ((ceiling_gas_price_wei * 100) / (DEFAULT_GAS_PRICE_MARGIN as u128 + 100)) + 2; let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); test_gas_price_must_not_break_through_ceiling_value_in_the_new_payable_mode( @@ -522,13 +522,12 @@ mod tests { let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; // This should be the value that would surplus the ceiling just slightly if the margin is // applied. // Adding just 1 didn't work, therefore 2 let rpc_gas_price_wei = - (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; + (ceiling_gas_price_wei * 100) / (DEFAULT_GAS_PRICE_MARGIN as u128 + 100) + 2; let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), rpc_gas_price_wei - 1), @@ -561,11 +560,10 @@ mod tests { let chain = TEST_DEFAULT_CHAIN; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let default_gas_price_margin_percents = chain.rec().gas_price_default_margin_percents; let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; // This should be the value that would surplus the ceiling just slightly if the margin is applied let border_gas_price_wei = - (ceiling_gas_price_wei * 100) / (default_gas_price_margin_percents as u128 + 100) + 2; + (ceiling_gas_price_wei * 100) / (DEFAULT_GAS_PRICE_MARGIN as u128 + 100) + 2; let rpc_gas_price_wei = border_gas_price_wei - 1; let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei); let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ From 61ae15c01dafd77e6910c5a5941106e828da0f18 Mon Sep 17 00:00:00 2001 From: Bert Date: Tue, 1 Jul 2025 10:59:39 +0200 Subject: [PATCH 17/17] GH-638: review two addressed --- .../src/blockchains/blockchain_records.rs | 6 +- masq_lib/src/constants.rs | 4 +- .../payable_scanner_extension/test_utils.rs | 2 +- .../blockchain/blockchain_agent/agent_web3.rs | 36 +++--- node/src/blockchain/blockchain_agent/mod.rs | 3 +- node/src/blockchain/blockchain_bridge.rs | 6 +- .../blockchain_interface_web3/mod.rs | 42 +++--- .../blockchain_interface_initializer.rs | 2 +- node/src/hopper/routing_service.rs | 121 +++++++++++------- 9 files changed, 125 insertions(+), 97 deletions(-) diff --git a/masq_lib/src/blockchains/blockchain_records.rs b/masq_lib/src/blockchains/blockchain_records.rs index 067c36a14..00ac1bb66 100644 --- a/masq_lib/src/blockchains/blockchain_records.rs +++ b/masq_lib/src/blockchains/blockchain_records.rs @@ -5,7 +5,7 @@ use crate::constants::{ BASE_GAS_PRICE_CEILING_WEI, BASE_MAINNET_CHAIN_ID, BASE_MAINNET_CONTRACT_CREATION_BLOCK, BASE_MAINNET_FULL_IDENTIFIER, BASE_SEPOLIA_CHAIN_ID, BASE_SEPOLIA_CONTRACT_CREATION_BLOCK, BASE_SEPOLIA_FULL_IDENTIFIER, DEV_CHAIN_FULL_IDENTIFIER, DEV_CHAIN_ID, - DEV_GAS_PRICE_CEILING_WEI, ETH_GAS_PRICE_CEIOLING_WEI, ETH_MAINNET_CHAIN_ID, + DEV_GAS_PRICE_CEILING_WEI, ETH_GAS_PRICE_CEILING_WEI, ETH_MAINNET_CHAIN_ID, ETH_MAINNET_CONTRACT_CREATION_BLOCK, ETH_MAINNET_FULL_IDENTIFIER, ETH_ROPSTEN_CHAIN_ID, ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, ETH_ROPSTEN_FULL_IDENTIFIER, MULTINODE_TESTNET_CONTRACT_CREATION_BLOCK, POLYGON_AMOY_CHAIN_ID, @@ -30,7 +30,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthMainnet, num_chain_id: ETH_MAINNET_CHAIN_ID, literal_identifier: ETH_MAINNET_FULL_IDENTIFIER, - gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEIOLING_WEI, + gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEILING_WEI, contract: ETH_MAINNET_CONTRACT_ADDRESS, contract_creation_block: ETH_MAINNET_CONTRACT_CREATION_BLOCK, }, @@ -62,7 +62,7 @@ pub const CHAINS: [BlockchainRecord; 7] = [ self_id: Chain::EthRopsten, num_chain_id: ETH_ROPSTEN_CHAIN_ID, literal_identifier: ETH_ROPSTEN_FULL_IDENTIFIER, - gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEIOLING_WEI, + gas_price_safe_ceiling_minor: ETH_GAS_PRICE_CEILING_WEI, contract: ETH_ROPSTEN_TESTNET_CONTRACT_ADDRESS, contract_creation_block: ETH_ROPSTEN_CONTRACT_CREATION_BLOCK, }, diff --git a/masq_lib/src/constants.rs b/masq_lib/src/constants.rs index 0d163c34b..67338f5a3 100644 --- a/masq_lib/src/constants.rs +++ b/masq_lib/src/constants.rs @@ -115,7 +115,7 @@ pub const BASE_MAINNET_FULL_IDENTIFIER: &str = concatcp!(BASE_FAMILY, LINK, MAIN pub const BASE_SEPOLIA_FULL_IDENTIFIER: &str = concatcp!(BASE_FAMILY, LINK, "sepolia"); pub const DEV_CHAIN_FULL_IDENTIFIER: &str = "dev"; pub const POLYGON_GAS_PRICE_CEILING_WEI: u128 = 200_000_000_000; -pub const ETH_GAS_PRICE_CEIOLING_WEI: u128 = 100_000_000_000; +pub const ETH_GAS_PRICE_CEILING_WEI: u128 = 100_000_000_000; pub const BASE_GAS_PRICE_CEILING_WEI: u128 = 50_000_000_000; pub const DEV_GAS_PRICE_CEILING_WEI: u128 = 200_000_000_000; @@ -201,7 +201,7 @@ mod tests { assert_eq!(BASE_SEPOLIA_FULL_IDENTIFIER, "base-sepolia"); assert_eq!(DEV_CHAIN_FULL_IDENTIFIER, "dev"); assert_eq!(POLYGON_GAS_PRICE_CEILING_WEI, 200_000_000_000); - assert_eq!(ETH_GAS_PRICE_CEIOLING_WEI, 100_000_000_000); + assert_eq!(ETH_GAS_PRICE_CEILING_WEI, 100_000_000_000); assert_eq!(BASE_GAS_PRICE_CEILING_WEI, 50_000_000_000); assert_eq!(DEV_GAS_PRICE_CEILING_WEI, 200_000_000_000); assert_eq!( diff --git a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs index 63947b8f2..b8e83b78d 100644 --- a/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs +++ b/node/src/accountant/scanners/payable_scanner_extension/test_utils.rs @@ -41,7 +41,7 @@ impl BlockchainAgent for BlockchainAgentMock { unimplemented!("not needed yet") } - fn estimated_transaction_fee_total( + fn estimate_transaction_fee_total( &self, _qualified_payables: &PricedQualifiedPayables, ) -> u128 { diff --git a/node/src/blockchain/blockchain_agent/agent_web3.rs b/node/src/blockchain/blockchain_agent/agent_web3.rs index 421c652e4..8899a0743 100644 --- a/node/src/blockchain/blockchain_agent/agent_web3.rs +++ b/node/src/blockchain/blockchain_agent/agent_web3.rs @@ -95,10 +95,7 @@ impl BlockchainAgent for BlockchainAgentWeb3 { } } - fn estimated_transaction_fee_total( - &self, - qualified_payables: &PricedQualifiedPayables, - ) -> u128 { + fn estimate_transaction_fee_total(&self, qualified_payables: &PricedQualifiedPayables) -> u128 { let prices_sum: u128 = qualified_payables .payables .iter() @@ -529,7 +526,7 @@ mod tests { let rpc_gas_price_wei = (ceiling_gas_price_wei * 100) / (DEFAULT_GAS_PRICE_MARGIN as u128 + 100) + 2; let check_value_wei = increase_gas_price_by_margin(rpc_gas_price_wei); - let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + let unpriced_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), rpc_gas_price_wei - 1), (account_2.clone(), rpc_gas_price_wei - 2), ]); @@ -541,7 +538,7 @@ mod tests { test_name, chain, rpc_gas_price_wei, - raw_qualified_payables, + unpriced_qualified_payables, expected_surpluses_wallet_and_wei_as_text, ); @@ -566,7 +563,7 @@ mod tests { (ceiling_gas_price_wei * 100) / (DEFAULT_GAS_PRICE_MARGIN as u128 + 100) + 2; let rpc_gas_price_wei = border_gas_price_wei - 1; let check_value_wei = increase_gas_price_by_margin(border_gas_price_wei); - let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + let unpriced_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), border_gas_price_wei), (account_2.clone(), border_gas_price_wei), ]); @@ -578,7 +575,7 @@ mod tests { test_name, chain, rpc_gas_price_wei, - raw_qualified_payables, + unpriced_qualified_payables, expected_surpluses_wallet_and_wei_as_text, ); assert!(check_value_wei > ceiling_gas_price_wei); @@ -593,7 +590,7 @@ mod tests { let fetched_gas_price_wei = ceiling_gas_price_wei - 1; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + let unpriced_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), fetched_gas_price_wei - 2), (account_2.clone(), fetched_gas_price_wei - 3), ]); @@ -605,7 +602,7 @@ mod tests { test_name, chain, fetched_gas_price_wei, - raw_qualified_payables, + unpriced_qualified_payables, expected_surpluses_wallet_and_wei_as_text, ); } @@ -617,7 +614,7 @@ mod tests { let ceiling_gas_price_wei = chain.rec().gas_price_safe_ceiling_minor; let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + let unpriced_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), ceiling_gas_price_wei - 1), (account_2.clone(), ceiling_gas_price_wei - 2), ]); @@ -629,7 +626,7 @@ mod tests { test_name, chain, ceiling_gas_price_wei - 3, - raw_qualified_payables, + unpriced_qualified_payables, expected_surpluses_wallet_and_wei_as_text, ); } @@ -644,20 +641,19 @@ mod tests { let account_2 = make_payable_account(34); // The values can never go above the ceiling, therefore, we can assume only values even or // smaller than that in the previous attempts - let raw_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ + let unpriced_qualified_payables = make_unpriced_qualified_payables_for_retry_mode(vec![ (account_1.clone(), ceiling_gas_price_wei), (account_2.clone(), ceiling_gas_price_wei), ]); let expected_surpluses_wallet_and_wei_as_text = "650,000,000,000 wei for tx to 0x00000000000000000000\ - 000077616c6c65743132, 650,000,000,000 wei for tx to 0x00000000000000000000000077616c6c6\ - 5743334"; + 000077616c6c65743132, 650,000,000,000 wei for tx to 0x00000000000000000000000077616c6c65743334"; test_gas_price_must_not_break_through_ceiling_value_in_the_retry_payable_mode( test_name, chain, fetched_gas_price_wei, - raw_qualified_payables, + unpriced_qualified_payables, expected_surpluses_wallet_and_wei_as_text, ); } @@ -725,7 +721,7 @@ mod tests { } #[test] - fn estimated_transaction_fee_works_for_new_payable() { + fn estimate_transaction_fee_total_works_for_new_payable() { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let account_1 = make_payable_account(12); @@ -741,7 +737,7 @@ mod tests { ); let priced_qualified_payables = subject.price_qualified_payables(qualified_payables); - let result = subject.estimated_transaction_fee_total(&priced_qualified_payables); + let result = subject.estimate_transaction_fee_total(&priced_qualified_payables); assert_eq!( result, @@ -751,7 +747,7 @@ mod tests { } #[test] - fn estimated_transaction_fee_works_for_retry_payable() { + fn estimate_transaction_fee_total_works_for_retry_payable() { let consuming_wallet = make_wallet("efg"); let consuming_wallet_balances = make_zeroed_consuming_wallet_balances(); let rpc_gas_price_wei = 444_555_666; @@ -786,7 +782,7 @@ mod tests { let priced_qualified_payables = subject.price_qualified_payables(unpriced_qualified_payables); - let result = subject.estimated_transaction_fee_total(&priced_qualified_payables); + let result = subject.estimate_transaction_fee_total(&priced_qualified_payables); let gas_prices_for_accounts_from_1_to_5 = vec![ increase_gas_price_by_margin(rpc_gas_price_wei), diff --git a/node/src/blockchain/blockchain_agent/mod.rs b/node/src/blockchain/blockchain_agent/mod.rs index b8538d97e..fb8030a09 100644 --- a/node/src/blockchain/blockchain_agent/mod.rs +++ b/node/src/blockchain/blockchain_agent/mod.rs @@ -30,8 +30,7 @@ pub trait BlockchainAgent: Send { &self, qualified_payables: UnpricedQualifiedPayables, ) -> PricedQualifiedPayables; - fn estimated_transaction_fee_total(&self, qualified_payables: &PricedQualifiedPayables) - -> u128; + fn estimate_transaction_fee_total(&self, qualified_payables: &PricedQualifiedPayables) -> u128; fn consuming_wallet_balances(&self) -> ConsumingWalletBalances; fn consuming_wallet(&self) -> &Wallet; fn get_chain(&self) -> Chain; diff --git a/node/src/blockchain/blockchain_bridge.rs b/node/src/blockchain/blockchain_bridge.rs index 2c8d0b64c..e427ab934 100644 --- a/node/src/blockchain/blockchain_bridge.rs +++ b/node/src/blockchain/blockchain_bridge.rs @@ -744,7 +744,7 @@ mod tests { let accountant_received_payment = accountant_recording_arc.lock().unwrap(); let blockchain_agent_with_context_msg_actual: &BlockchainAgentWithContextMessage = accountant_received_payment.get_record(0); - let expected_ripe_qualified_payables = PricedQualifiedPayables { + let expected_priced_qualified_payables = PricedQualifiedPayables { payables: qualified_payables .into_iter() .map(|payable| QualifiedPayableWithGasPrice { @@ -755,7 +755,7 @@ mod tests { }; assert_eq!( blockchain_agent_with_context_msg_actual.qualified_payables, - expected_ripe_qualified_payables + expected_priced_qualified_payables ); let actual_agent = blockchain_agent_with_context_msg_actual.agent.as_ref(); assert_eq!(actual_agent.consuming_wallet(), &consuming_wallet); @@ -764,7 +764,7 @@ mod tests { ConsumingWalletBalances::new(0xAAAA.into(), 0xFFFF.into()) ); assert_eq!( - actual_agent.estimated_transaction_fee_total( + actual_agent.estimate_transaction_fee_total( &actual_agent.price_qualified_payables(unpriced_qualified_payables) ), 1_791_228_995_698_688 diff --git a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs index 5b2ccb471..81c7fe62d 100644 --- a/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs +++ b/node/src/blockchain/blockchain_interface/blockchain_interface_web3/mod.rs @@ -838,14 +838,14 @@ mod tests { fn blockchain_interface_web3_can_introduce_blockchain_agent_in_the_new_payables_mode() { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); - let raw_qualified_payables = + let unpriced_qualified_payables = UnpricedQualifiedPayables::from(vec![account_1.clone(), account_2.clone()]); let gas_price_wei_from_rpc_hex = "0x3B9ACA00"; // 1000000000 let gas_price_wei_from_rpc_u128_wei = u128::from_str_radix(&gas_price_wei_from_rpc_hex[2..], 16).unwrap(); let gas_price_wei_from_rpc_u128_wei_with_margin = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); - let expected_ripe_qualified_payables = PricedQualifiedPayables { + let expected_priced_qualified_payables = PricedQualifiedPayables { payables: vec![ QualifiedPayableWithGasPrice::new( account_1, @@ -857,13 +857,13 @@ mod tests { ), ], }; - let expected_estimated_transaction_fee = 190_652_800_000_000; + let expected_estimated_transaction_fee_total = 190_652_800_000_000; test_blockchain_interface_web3_can_introduce_blockchain_agent( - raw_qualified_payables, + unpriced_qualified_payables, gas_price_wei_from_rpc_hex, - expected_ripe_qualified_payables, - expected_estimated_transaction_fee, + expected_priced_qualified_payables, + expected_estimated_transaction_fee_total, ); } @@ -875,7 +875,7 @@ mod tests { let account_1 = make_payable_account(12); let account_2 = make_payable_account(34); let account_3 = make_payable_account(56); - let raw_qualified_payables = UnpricedQualifiedPayables { + let unpriced_qualified_payables = UnpricedQualifiedPayables { payables: vec![ QualifiedPayablesBeforeGasPriceSelection::new( account_1.clone(), @@ -892,7 +892,7 @@ mod tests { ], }; - let expected_ripe_qualified_payables = { + let expected_priced_qualified_payables = { let gas_price_account_1 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); let gas_price_account_2 = increase_gas_price_by_margin(gas_price_wei_from_rpc_u128_wei); let gas_price_account_3 = @@ -905,21 +905,21 @@ mod tests { ], } }; - let expected_estimated_transaction_fee = 285_979_200_073_328; + let expected_estimated_transaction_fee_total = 285_979_200_073_328; test_blockchain_interface_web3_can_introduce_blockchain_agent( - raw_qualified_payables, + unpriced_qualified_payables, gas_price_wei_from_rpc_hex, - expected_ripe_qualified_payables, - expected_estimated_transaction_fee, + expected_priced_qualified_payables, + expected_estimated_transaction_fee_total, ); } fn test_blockchain_interface_web3_can_introduce_blockchain_agent( - qualified_payables: UnpricedQualifiedPayables, + unpriced_qualified_payables: UnpricedQualifiedPayables, gas_price_wei_from_rpc_hex: &str, - expected_ripe_qualified_payables: PricedQualifiedPayables, - expected_estimated_transaction_fee: u128, + expected_priced_qualified_payables: PricedQualifiedPayables, + expected_estimated_transaction_fee_total: u128, ) { let port = find_free_port(); let _blockchain_client_server = MBCSBuilder::new(port) @@ -951,11 +951,15 @@ mod tests { masq_token_balance_in_minor_units: expected_masq_balance } ); - let priced_qualified_payables = result.price_qualified_payables(qualified_payables); - assert_eq!(priced_qualified_payables, expected_ripe_qualified_payables); + let priced_qualified_payables = + result.price_qualified_payables(unpriced_qualified_payables); assert_eq!( - result.estimated_transaction_fee_total(&priced_qualified_payables), - expected_estimated_transaction_fee + priced_qualified_payables, + expected_priced_qualified_payables + ); + assert_eq!( + result.estimate_transaction_fee_total(&priced_qualified_payables), + expected_estimated_transaction_fee_total ) } diff --git a/node/src/blockchain/blockchain_interface_initializer.rs b/node/src/blockchain/blockchain_interface_initializer.rs index 362239c06..d7f452311 100644 --- a/node/src/blockchain/blockchain_interface_initializer.rs +++ b/node/src/blockchain/blockchain_interface_initializer.rs @@ -102,7 +102,7 @@ mod tests { expected_priced_qualified_payables ); assert_eq!( - blockchain_agent.estimated_transaction_fee_total(&priced_qualified_payables), + blockchain_agent.estimate_transaction_fee_total(&priced_qualified_payables), 190_652_800_000_000 ); } diff --git a/node/src/hopper/routing_service.rs b/node/src/hopper/routing_service.rs index 05d8af9d6..478441159 100644 --- a/node/src/hopper/routing_service.rs +++ b/node/src/hopper/routing_service.rs @@ -529,6 +529,7 @@ mod tests { use masq_lib::test_utils::environment_guard::EnvironmentGuard; use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler}; use masq_lib::test_utils::utils::TEST_DEFAULT_CHAIN; + use std::fmt::format; use std::net::SocketAddr; use std::str::FromStr; use std::time::SystemTime; @@ -593,6 +594,7 @@ mod tests { #[test] fn logs_and_ignores_message_that_cannot_be_deserialized() { init_test_logging(); + let test_name = "logs_and_ignores_message_that_cannot_be_deserialized"; let cryptdes = make_cryptde_pair(); let route = route_from_proxy_client(&cryptdes.main.public_key(), cryptdes.main); let lcp = LiveCoresPackage::new( @@ -610,7 +612,7 @@ mod tests { data: data_enc.into(), }; let peer_actors = peer_actors_builder().build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( cryptdes, RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -624,17 +626,19 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Couldn't expire CORES package with 35-byte payload to ProxyClient using main key", + &format!("ERROR: {test_name}: Couldn't expire CORES package with 35-byte payload to ProxyClient using main key"), ); } #[test] fn logs_and_ignores_message_that_cannot_be_decrypted() { init_test_logging(); + let test_name = "logs_and_ignores_message_that_cannot_be_decrypted"; let (main_cryptde, alias_cryptde) = { //initialization to real CryptDEs let pair = Bootstrapper::pub_initialize_cryptdes_for_testing(&None, &None); @@ -657,7 +661,7 @@ mod tests { data: data_enc.into(), }; let peer_actors = peer_actors_builder().build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -674,11 +678,12 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Couldn't expire CORES package with 51-byte payload to ProxyClient using main key: DecryptionError(OpeningFailed)", + &format!("ERROR: {test_name}: Couldn't expire CORES package with 51-byte payload to ProxyClient using main key: DecryptionError(OpeningFailed)") ); } @@ -809,6 +814,7 @@ mod tests { let _eg = EnvironmentGuard::new(); init_test_logging(); BAN_CACHE.clear(); + let test_name = "complains_about_live_message_for_nonexistent_proxy_client"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let route = route_to_proxy_client(&main_cryptde.public_key(), main_cryptde); @@ -838,7 +844,7 @@ mod tests { let system = System::new("converts_live_message_to_expired_for_proxy_client"); let peer_actors = peer_actors_builder().build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -855,6 +861,7 @@ mod tests { 0, false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); @@ -862,7 +869,7 @@ mod tests { system.run(); let tlh = TestLogHandler::new(); tlh.exists_no_log_containing("Couldn't decode CORES package in 8-byte buffer"); - tlh.exists_log_containing("WARN: RoutingService: Received CORES package from 1.2.3.4:5678 for Proxy Client, but Proxy Client isn't running"); + tlh.exists_log_containing(&format!("WARN: {test_name}: Received CORES package from 1.2.3.4:5678 for Proxy Client, but Proxy Client isn't running")); } #[test] @@ -1281,6 +1288,8 @@ mod tests { let _eg = EnvironmentGuard::new(); BAN_CACHE.clear(); init_test_logging(); + let test_name = + "route_logs_and_ignores_cores_package_that_demands_routing_without_paying_wallet"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let origin_key = PublicKey::new(&[1, 2]); @@ -1313,9 +1322,7 @@ mod tests { sequence_number: None, data: data_enc.into(), }; - let system = System::new( - "route_logs_and_ignores_cores_package_that_demands_routing_without_paying_wallet", - ); + let system = System::new(test_name); let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let (neighborhood, _, neighborhood_recording_arc) = make_recorder(); @@ -1328,7 +1335,7 @@ mod tests { .dispatcher(dispatcher) .accountant(accountant) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1345,13 +1352,14 @@ mod tests { 200, true, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); System::current().stop_with_code(0); system.run(); TestLogHandler::new().exists_log_matching( - "WARN: RoutingService: Refusing to route Live CORES package with \\d+-byte payload without paying wallet", + &format!("WARN: {test_name}: Refusing to route Live CORES package with \\d+-byte payload without paying wallet"), ); assert_eq!(proxy_client_recording_arc.lock().unwrap().len(), 0); assert_eq!(proxy_server_recording_arc.lock().unwrap().len(), 0); @@ -1366,6 +1374,7 @@ mod tests { let _eg = EnvironmentGuard::new(); BAN_CACHE.clear(); init_test_logging(); + let test_name = "route_logs_and_ignores_cores_package_that_demands_proxy_client_routing_with_paying_wallet_that_cant_pay"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let public_key = main_cryptde.public_key(); @@ -1414,9 +1423,7 @@ mod tests { sequence_number: None, data: data_enc.into(), }; - let system = System::new( - "route_logs_and_ignores_cores_package_that_demands_proxy_client_routing_with_paying_wallet_that_cant_pay", - ); + let system = System::new(test_name); let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let (neighborhood, _, neighborhood_recording_arc) = make_recorder(); @@ -1429,7 +1436,7 @@ mod tests { .dispatcher(dispatcher) .accountant(accountant) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1446,13 +1453,14 @@ mod tests { 200, true, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); System::current().stop_with_code(0); system.run(); TestLogHandler::new().exists_log_matching( - "WARN: RoutingService: Refusing to route Expired CORES package with \\d+-byte payload without proof of 0x0a26dc9ebb2124baf1efe9d460f1ce59cd7944bd paying wallet ownership.", + &format!("WARN: {test_name}: Refusing to route Expired CORES package with \\d+-byte payload without proof of 0x0a26dc9ebb2124baf1efe9d460f1ce59cd7944bd paying wallet ownership."), ); assert_eq!(proxy_client_recording_arc.lock().unwrap().len(), 0); assert_eq!(proxy_server_recording_arc.lock().unwrap().len(), 0); @@ -1467,6 +1475,7 @@ mod tests { let _eg = EnvironmentGuard::new(); BAN_CACHE.clear(); init_test_logging(); + let test_name = "route_logs_and_ignores_cores_package_that_demands_hopper_routing_with_paying_wallet_that_cant_pay"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let current_key = main_cryptde.public_key(); @@ -1512,9 +1521,7 @@ mod tests { encodex(main_cryptde, &destination_key, &payload).unwrap(), ); - let system = System::new( - "route_logs_and_ignores_cores_package_that_demands_hopper_routing_with_paying_wallet_that_cant_pay", - ); + let system = System::new(test_name); let (proxy_client, _, proxy_client_recording_arc) = make_recorder(); let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let (neighborhood, _, neighborhood_recording_arc) = make_recorder(); @@ -1527,7 +1534,7 @@ mod tests { .dispatcher(dispatcher) .accountant(accountant) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1544,6 +1551,7 @@ mod tests { 200, true, ); + subject.logger = Logger::new(test_name); subject.route_data_externally( lcp, @@ -1554,7 +1562,7 @@ mod tests { System::current().stop_with_code(0); system.run(); TestLogHandler::new().exists_log_matching( - "WARN: RoutingService: Refusing to route Live CORES package with \\d+-byte payload without proof of 0x0a26dc9ebb2124baf1efe9d460f1ce59cd7944bd paying wallet ownership.", + &format!("WARN: {test_name}: Refusing to route Live CORES package with \\d+-byte payload without proof of 0x0a26dc9ebb2124baf1efe9d460f1ce59cd7944bd paying wallet ownership."), ); assert_eq!(proxy_client_recording_arc.lock().unwrap().len(), 0); assert_eq!(proxy_server_recording_arc.lock().unwrap().len(), 0); @@ -1568,6 +1576,8 @@ mod tests { let _eg = EnvironmentGuard::new(); BAN_CACHE.clear(); init_test_logging(); + let test_name = + "route_logs_and_ignores_cores_package_from_delinquent_that_demands_external_routing"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let paying_wallet = make_paying_wallet(b"wallet"); @@ -1603,7 +1613,7 @@ mod tests { .dispatcher(dispatcher) .accountant(accountant) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1620,6 +1630,7 @@ mod tests { rate_pack_routing_byte(103), false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); @@ -1630,7 +1641,7 @@ mod tests { assert_eq!(dispatcher_recording.len(), 0); let accountant_recording = accountant_recording_arc.lock().unwrap(); assert_eq!(accountant_recording.len(), 0); - TestLogHandler::new().exists_log_containing("WARN: RoutingService: Node with consuming wallet 0x71d0fc7d1c570b1ed786382b551a09391c91e33d is delinquent; electing not to route 7-byte payload further"); + TestLogHandler::new().exists_log_containing(&format!("WARN: {test_name}: Node with consuming wallet 0x71d0fc7d1c570b1ed786382b551a09391c91e33d is delinquent; electing not to route 7-byte payload further")); } #[test] @@ -1638,6 +1649,8 @@ mod tests { let _eg = EnvironmentGuard::new(); BAN_CACHE.clear(); init_test_logging(); + let test_name = + "route_logs_and_ignores_cores_package_from_delinquent_that_demands_internal_routing"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let paying_wallet = make_paying_wallet(b"wallet"); @@ -1677,7 +1690,7 @@ mod tests { .dispatcher(dispatcher) .accountant(accountant) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1694,6 +1707,7 @@ mod tests { rate_pack_routing_byte(103), false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); @@ -1704,12 +1718,14 @@ mod tests { assert_eq!(dispatcher_recording.len(), 0); let accountant_recording = accountant_recording_arc.lock().unwrap(); assert_eq!(accountant_recording.len(), 0); - TestLogHandler::new().exists_log_containing("WARN: RoutingService: Node with consuming wallet 0x71d0fc7d1c570b1ed786382b551a09391c91e33d is delinquent; electing not to route 36-byte payload to ProxyServer"); + TestLogHandler::new().exists_log_containing(&format!("WARN: {test_name}: Node with consuming wallet 0x71d0fc7d1c570b1ed786382b551a09391c91e33d is delinquent; electing not to route 36-byte payload to ProxyServer")); } #[test] fn route_logs_and_ignores_inbound_client_data_that_doesnt_deserialize_properly() { init_test_logging(); + let test_name = + "route_logs_and_ignores_inbound_client_data_that_doesnt_deserialize_properly"; let inbound_client_data = InboundClientData { timestamp: SystemTime::now(), client_addr: SocketAddr::from_str("1.2.3.4:5678").unwrap(), @@ -1730,7 +1746,7 @@ mod tests { .neighborhood(neighborhood) .dispatcher(dispatcher) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -1744,13 +1760,14 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); System::current().stop_with_code(0); system.run(); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Couldn't decode CORES package in 0-byte buffer from 1.2.3.4:5678: DecryptionError(EmptyData)", + &format!("ERROR: {test_name}: Couldn't decode CORES package in 0-byte buffer from 1.2.3.4:5678: DecryptionError(EmptyData)"), ); assert_eq!(proxy_client_recording_arc.lock().unwrap().len(), 0); assert_eq!(proxy_server_recording_arc.lock().unwrap().len(), 0); @@ -1761,6 +1778,7 @@ mod tests { #[test] fn route_logs_and_ignores_invalid_live_cores_package() { init_test_logging(); + let test_name = "route_logs_and_ignores_invalid_live_cores_package"; let main_cryptde = main_cryptde(); let alias_cryptde = alias_cryptde(); let lcp = LiveCoresPackage::new(Route { hops: vec![] }, CryptData::new(&[])); @@ -1788,7 +1806,7 @@ mod tests { .neighborhood(neighborhood) .dispatcher(dispatcher) .build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( CryptDEPair { main: main_cryptde, alias: alias_cryptde, @@ -1805,14 +1823,15 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); subject.route(inbound_client_data); System::current().stop_with_code(0); system.run(); - TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Invalid 67-byte CORES package: RoutingError(EmptyRoute)", - ); + TestLogHandler::new().exists_log_containing(&format!( + "ERROR: {test_name}: Invalid 67-byte CORES package: RoutingError(EmptyRoute)" + )); assert_eq!(proxy_client_recording_arc.lock().unwrap().len(), 0); assert_eq!(proxy_server_recording_arc.lock().unwrap().len(), 0); assert_eq!(neighborhood_recording_arc.lock().unwrap().len(), 0); @@ -1822,8 +1841,9 @@ mod tests { #[test] fn route_data_around_again_logs_and_ignores_bad_lcp() { init_test_logging(); + let test_name = "route_data_around_again_logs_and_ignores_bad_lcp"; let peer_actors = peer_actors_builder().build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -1837,6 +1857,7 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); let lcp = LiveCoresPackage::new(Route { hops: vec![] }, CryptData::new(&[])); let ibcd = InboundClientData { timestamp: SystemTime::now(), @@ -1850,9 +1871,9 @@ mod tests { subject.route_data_around_again(lcp, &ibcd); - TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: bad zero-hop route: RoutingError(EmptyRoute)", - ); + TestLogHandler::new().exists_log_containing(&format!( + "ERROR: {test_name}: bad zero-hop route: RoutingError(EmptyRoute)" + )); } fn make_routing_service_subs(peer_actors: PeerActors) -> RoutingServiceSubs { @@ -1985,9 +2006,10 @@ mod tests { #[test] fn route_expired_package_handles_unmigratable_gossip() { init_test_logging(); + let test_name = "route_expired_package_handles_unmigratable_gossip"; let (neighborhood, _, neighborhood_recording_arc) = make_recorder(); let peer_actors = peer_actors_builder().neighborhood(neighborhood).build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -2001,6 +2023,7 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); let expired_package = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), None, @@ -2008,7 +2031,7 @@ mod tests { MessageType::Gossip(VersionedData::test_new(dv!(0, 0), vec![])), 0, ); - let system = System::new("route_expired_package_handles_unmigratable_gossip"); + let system = System::new(test_name); subject.route_expired_package(Component::Neighborhood, expired_package, true); @@ -2017,7 +2040,7 @@ mod tests { let neighborhood_recording = neighborhood_recording_arc.lock().unwrap(); assert_eq!(neighborhood_recording.len(), 0); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Received unmigratable Gossip: MigrationNotFound(DataVersion { major: 0, minor: 0 }, DataVersion { major: 0, minor: 1 })", + &format!("ERROR: {test_name}: Received unmigratable Gossip: MigrationNotFound(DataVersion {{ major: 0, minor: 0 }}, DataVersion {{ major: 0, minor: 1 }})"), ); } @@ -2063,9 +2086,10 @@ mod tests { #[test] fn route_expired_package_handles_unmigratable_client_response() { init_test_logging(); + let test_name = "route_expired_package_handles_unmigratable_client_response"; let (proxy_server, _, proxy_server_recording_arc) = make_recorder(); let peer_actors = peer_actors_builder().proxy_server(proxy_server).build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -2079,6 +2103,7 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); let expired_package = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), None, @@ -2086,7 +2111,7 @@ mod tests { MessageType::ClientResponse(VersionedData::test_new(dv!(0, 0), vec![])), 0, ); - let system = System::new("route_expired_package_handles_unmigratable_client_response"); + let system = System::new(test_name); subject.route_expired_package(Component::ProxyServer, expired_package, true); @@ -2095,16 +2120,17 @@ mod tests { let proxy_server_recording = proxy_server_recording_arc.lock().unwrap(); assert_eq!(proxy_server_recording.len(), 0); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Received unmigratable ClientResponsePayload: MigrationNotFound(DataVersion { major: 0, minor: 0 }, DataVersion { major: 0, minor: 1 })", + &format!("ERROR: {test_name}: Received unmigratable ClientResponsePayload: MigrationNotFound(DataVersion {{ major: 0, minor: 0 }}, DataVersion {{ major: 0, minor: 1 }})"), ); } #[test] fn route_expired_package_handles_unmigratable_dns_resolve_failure() { init_test_logging(); + let test_name = "route_expired_package_handles_unmigratable_dns_resolve_failure"; let (hopper, _, hopper_recording_arc) = make_recorder(); let peer_actors = peer_actors_builder().hopper(hopper).build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -2118,6 +2144,7 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); let expired_package = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), None, @@ -2125,7 +2152,7 @@ mod tests { MessageType::DnsResolveFailed(VersionedData::test_new(dv!(0, 0), vec![])), 0, ); - let system = System::new("route_expired_package_handles_unmigratable_dns_resolve_failure"); + let system = System::new(test_name); subject.route_expired_package(Component::ProxyServer, expired_package, true); @@ -2134,16 +2161,17 @@ mod tests { let hopper_recording = hopper_recording_arc.lock().unwrap(); assert_eq!(hopper_recording.len(), 0); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Received unmigratable DnsResolveFailed: MigrationNotFound(DataVersion { major: 0, minor: 0 }, DataVersion { major: 0, minor: 1 })", + &format!("ERROR: {test_name}: Received unmigratable DnsResolveFailed: MigrationNotFound(DataVersion {{ major: 0, minor: 0 }}, DataVersion {{ major: 0, minor: 1 }})"), ); } #[test] fn route_expired_package_handles_unmigratable_gossip_failure() { init_test_logging(); + let test_name = "route_expired_package_handles_unmigratable_gossip_failure"; let (neighborhood, _, neighborhood_recording_arc) = make_recorder(); let peer_actors = peer_actors_builder().neighborhood(neighborhood).build(); - let subject = RoutingService::new( + let mut subject = RoutingService::new( make_cryptde_pair(), RoutingServiceSubs { proxy_client_subs_opt: peer_actors.proxy_client_opt, @@ -2157,6 +2185,7 @@ mod tests { 200, false, ); + subject.logger = Logger::new(test_name); let expired_package = ExpiredCoresPackage::new( SocketAddr::from_str("1.2.3.4:1234").unwrap(), None, @@ -2173,7 +2202,7 @@ mod tests { let neighborhood_recording = neighborhood_recording_arc.lock().unwrap(); assert_eq!(neighborhood_recording.len(), 0); TestLogHandler::new().exists_log_containing( - "ERROR: RoutingService: Received unmigratable GossipFailure: MigrationNotFound(DataVersion { major: 0, minor: 0 }, DataVersion { major: 0, minor: 1 })", + &format!("ERROR: {test_name}: Received unmigratable GossipFailure: MigrationNotFound(DataVersion {{ major: 0, minor: 0 }}, DataVersion {{ major: 0, minor: 1 }})"), ); } }