Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
24e0a8a
GH-598-json-hotfix (#699)
bertllll Sep 9, 2025
ca6cb36
GH-642: Redesigning PendingPayableScanner (#677)
bertllll Sep 15, 2025
6e020c7
GH-689: Amend scanner scheduling: Handling ScanError msg (#691)
bertllll Sep 15, 2025
24396b1
GH-605: add TODO for the test
utkarshg6 Sep 16, 2025
647d61a
GH-606: Sweeping for ending the first stage (#706)
bertllll Sep 16, 2025
d2fd9cd
GH-605: more and more changes
utkarshg6 Sep 18, 2025
52411c9
GH-605: bit more refactoring
utkarshg6 Sep 18, 2025
398bdd9
GH-605: bit more changes
utkarshg6 Sep 18, 2025
e044dc4
GH-605: changing to & works
utkarshg6 Sep 18, 2025
8227dc8
GH-605: further changes
utkarshg6 Sep 18, 2025
ff6e400
GH-605: more TODOs
utkarshg6 Sep 18, 2025
dc863ef
GH-605: derive Copy for PayableScanType
utkarshg6 Sep 19, 2025
9fd9ee7
GH-605: add scan_type function
utkarshg6 Sep 19, 2025
9ba398e
GH-605: comment out unused code in test
utkarshg6 Sep 19, 2025
80711d4
GH-605: refactor the code a bit
utkarshg6 Sep 19, 2025
4ac6418
GH-605: refactor signable_tx_templates_can_be_created_from_priced_ret…
utkarshg6 Sep 19, 2025
83d6155
GH-605: the helper functions have more realistic args name
utkarshg6 Sep 19, 2025
141d10a
GH-605: more refactoring of signable_tx_templates_can_be_created_from…
utkarshg6 Sep 19, 2025
4f91045
GH-605: more refactored changes
utkarshg6 Sep 19, 2025
896f7d0
GH-605: further refactoring changes
utkarshg6 Sep 19, 2025
18e0a54
GH-605: handle_batch_results has been renamed
utkarshg6 Sep 19, 2025
cf0938a
GH-605: few more changes
utkarshg6 Sep 20, 2025
9308d37
GH-605: few more changes
utkarshg6 Sep 20, 2025
73395d8
GH-605: Review 4
utkarshg6 Sep 22, 2025
7522708
GH-605: Bug bot error
utkarshg6 Sep 22, 2025
e7c7716
GH-605: Just merged; 567 errors
utkarshg6 Sep 23, 2025
794d23a
GH-605: reduced errors to 97
utkarshg6 Sep 24, 2025
655830d
GH-605: only 37 errors remaining
utkarshg6 Sep 24, 2025
06106f7
GH-605: only 5 errors remaining
utkarshg6 Sep 25, 2025
8947136
GH-605: only 2 errors remaining
utkarshg6 Sep 25, 2025
b2df759
GH-605: all errors gone
utkarshg6 Sep 25, 2025
2828f80
GH-605: tests in sent_payable_dao are passing
utkarshg6 Sep 25, 2025
9a51af4
GH-605: all tests pass in payable scanner
utkarshg6 Sep 26, 2025
663c30e
GH-605: fix most of the clippy warnings
utkarshg6 Sep 26, 2025
6c84f82
GH-605: fix more of these problems
utkarshg6 Sep 26, 2025
2f07581
GH-605: write test for the ordering of ValidationStatus
utkarshg6 Sep 26, 2025
d6b8592
GH-605: implement ordering for ValidationStatus
utkarshg6 Sep 26, 2025
5838a52
GH-605: comment out unused code
utkarshg6 Sep 26, 2025
eab920d
GH-605: more changes fixed
utkarshg6 Sep 26, 2025
2cbdffe
GH-605: more fixing
utkarshg6 Sep 26, 2025
62f3542
GH-605: interim commit
Sep 26, 2025
97f54c8
GH-605: all tests in Node passing
Sep 27, 2025
d94d5cb
GH-605: last todo removed
Sep 28, 2025
b82e3d2
GH-605: fixed poor test coverage
Sep 28, 2025
76a857c
GH-605: free of unnecessary boilerplate code - erased manual impls fo…
Sep 28, 2025
b9ad935
GH-605: continuous impovement -- Ord and little refactoring
Sep 29, 2025
00f0223
GH-605: CI except MNT just fine
Sep 29, 2025
15a4de1
GH-605: MNT fixed
Sep 29, 2025
02d98fb
GH-605: small correction
Sep 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions node/src/accountant/db_access_objects/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::accountant::db_access_objects::failed_payable_dao::{
};
use crate::accountant::db_access_objects::sent_payable_dao::{Tx, TxStatus};
use crate::accountant::db_access_objects::utils::{current_unix_timestamp, TxHash};
use crate::accountant::scanners::payable_scanner::tx_templates::signable::SignableTxTemplate;
use crate::blockchain::test_utils::make_tx_hash;
use crate::database::db_initializer::{
DbInitializationConfig, DbInitializer, DbInitializerReal, DATABASE_FILE,
Expand Down Expand Up @@ -51,6 +52,14 @@ impl TxBuilder {
self
}

pub fn template(mut self, signable_tx_template: SignableTxTemplate) -> Self {
self.receiver_address_opt = Some(signable_tx_template.receiver_address);
self.amount_opt = Some(signable_tx_template.amount_in_wei);
self.gas_price_wei_opt = Some(signable_tx_template.gas_price_wei);
self.nonce_opt = Some(signable_tx_template.nonce);
self
}

pub fn status(mut self, status: TxStatus) -> Self {
self.status_opt = Some(status);
self
Expand Down Expand Up @@ -123,6 +132,14 @@ impl FailedTxBuilder {
self
}

pub fn template(mut self, signable_tx_template: SignableTxTemplate) -> Self {
self.receiver_address_opt = Some(signable_tx_template.receiver_address);
self.amount_opt = Some(signable_tx_template.amount_in_wei);
self.gas_price_wei_opt = Some(signable_tx_template.gas_price_wei);
self.nonce_opt = Some(signable_tx_template.nonce);
self
}

pub fn status(mut self, failure_status: FailureStatus) -> Self {
self.status_opt = Some(failure_status);
self
Expand Down
30 changes: 15 additions & 15 deletions node/src/accountant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub struct ReportTransactionReceipts {
pub response_skeleton_opt: Option<ResponseSkeleton>,
}

#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum PayableScanType {
New,
Retry,
Expand Down Expand Up @@ -4866,14 +4866,11 @@ mod tests {

#[test]
fn accountant_processes_sent_payables_and_schedules_pending_payable_scanner() {
let mark_pending_payables_rowids_params_arc = Arc::new(Mutex::new(vec![]));
let pending_payable_notify_later_params_arc = Arc::new(Mutex::new(vec![]));
let inserted_new_records_params_arc = Arc::new(Mutex::new(vec![]));
let expected_wallet = make_wallet("paying_you");
let expected_hash = H256::from("transaction_hash".keccak256());
let payable_dao = PayableDaoMock::new()
.mark_pending_payables_rowids_params(&mark_pending_payables_rowids_params_arc)
.mark_pending_payables_rowids_result(Ok(()));
let payable_dao = PayableDaoMock::new();
let sent_payable_dao = SentPayableDaoMock::new()
.insert_new_records_params(&inserted_new_records_params_arc)
.insert_new_records_result(Ok(()));
Expand All @@ -4890,6 +4887,12 @@ mod tests {
NotifyLaterHandleMock::default()
.notify_later_params(&pending_payable_notify_later_params_arc),
);
subject.scan_schedulers.payable.new_payable_notify =
Box::new(NotifyHandleMock::default().panic_on_schedule_attempt());
subject.scan_schedulers.payable.new_payable_notify_later =
Box::new(NotifyLaterHandleMock::default().panic_on_schedule_attempt());
subject.scan_schedulers.payable.retry_payable_notify =
Box::new(NotifyHandleMock::default().panic_on_schedule_attempt());
let expected_tx = TxBuilder::default().hash(expected_hash.clone()).build();
let sent_payable = SentPayables {
payment_procedure_result: Ok(BatchResults {
Expand All @@ -4916,21 +4919,15 @@ mod tests {
*pending_payable_notify_later_params,
vec![(ScanForPendingPayables::default(), pending_payable_interval)]
);
// The accountant is unbound here. We don't use the bind message. It means we can prove
// none of those other scan requests could have been sent (especially ScanForNewPayables,
// ScanForRetryPayables)
}

#[test]
fn accountant_finishes_processing_of_retry_payables_and_schedules_pending_payable_scanner() {
let mark_pending_payables_rowids_params_arc = Arc::new(Mutex::new(vec![]));
let pending_payable_notify_later_params_arc = Arc::new(Mutex::new(vec![]));
let inserted_new_records_params_arc = Arc::new(Mutex::new(vec![]));
let expected_wallet = make_wallet("paying_you");
let expected_hash = H256::from("transaction_hash".keccak256());
let payable_dao = PayableDaoMock::new()
.mark_pending_payables_rowids_params(&mark_pending_payables_rowids_params_arc)
.mark_pending_payables_rowids_result(Ok(()));
let payable_dao = PayableDaoMock::new();
let sent_payable_dao = SentPayableDaoMock::new()
.insert_new_records_params(&inserted_new_records_params_arc)
.insert_new_records_result(Ok(()));
Expand All @@ -4950,6 +4947,12 @@ mod tests {
NotifyLaterHandleMock::default()
.notify_later_params(&pending_payable_notify_later_params_arc),
);
subject.scan_schedulers.payable.new_payable_notify =
Box::new(NotifyHandleMock::default().panic_on_schedule_attempt());
subject.scan_schedulers.payable.new_payable_notify_later =
Box::new(NotifyLaterHandleMock::default().panic_on_schedule_attempt());
subject.scan_schedulers.payable.retry_payable_notify =
Box::new(NotifyHandleMock::default().panic_on_schedule_attempt());
let expected_tx = TxBuilder::default().hash(expected_hash.clone()).build();
let sent_payable = SentPayables {
payment_procedure_result: Ok(BatchResults {
Expand All @@ -4976,9 +4979,6 @@ mod tests {
*pending_payable_notify_later_params,
vec![(ScanForPendingPayables::default(), pending_payable_interval)]
);
// The accountant is unbound here. We don't use the bind message. It means we can prove
// none of those other scan requests could have been sent (especially ScanForNewPayables,
// ScanForRetryPayables)
}

#[test]
Expand Down
14 changes: 12 additions & 2 deletions node/src/accountant/scanners/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,12 +1077,22 @@ mod tests {

#[test]
fn finish_payable_scan_keeps_the_aware_of_unresolved_pending_payable_flag_as_false_in_case_of_err(
) {
assert_finish_payable_scan_keeps_aware_flag_false_on_error(PayableScanType::New);
assert_finish_payable_scan_keeps_aware_flag_false_on_error(PayableScanType::Retry);
}

fn assert_finish_payable_scan_keeps_aware_flag_false_on_error(
payable_scan_type: PayableScanType,
) {
init_test_logging();
let test_name = "finish_payable_scan_keeps_the_aware_of_unresolved_pending_payable_flag_as_false_in_case_of_err";
let test_name = match payable_scan_type {
PayableScanType::New => "finish_payable_scan_keeps_the_aware_of_unresolved_pending_payable_flag_as_false_in_case_of_err_for_new_scan",
PayableScanType::Retry => "finish_payable_scan_keeps_the_aware_of_unresolved_pending_payable_flag_as_false_in_case_of_err_for_retry_scan",
};
let sent_payable = SentPayables {
payment_procedure_result: Err("Some error".to_string()),
payable_scan_type: PayableScanType::New,
payable_scan_type,
response_skeleton_opt: None,
};
let logger = Logger::new(test_name);
Expand Down
62 changes: 41 additions & 21 deletions node/src/accountant/scanners/payable_scanner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::accountant::payment_adjuster::PaymentAdjuster;
use crate::accountant::scanners::payable_scanner::msgs::InitialTemplatesMessage;
use crate::accountant::scanners::payable_scanner::payment_adjuster_integration::SolvencySensitivePaymentInstructor;
use crate::accountant::scanners::payable_scanner::utils::{
batch_stats, calculate_lengths, filter_receiver_addresses_from_txs, generate_status_updates,
batch_stats, calculate_occurences, filter_receiver_addresses_from_txs, generate_status_updates,
payables_debug_summary, NextScanToRun, PayableScanResult, PayableThresholdsGauge,
PayableThresholdsGaugeReal,
};
Expand Down Expand Up @@ -163,15 +163,19 @@ impl PayableScanner {
fn process_message(&self, msg: &SentPayables, logger: &Logger) {
match &msg.payment_procedure_result {
Ok(batch_results) => match msg.payable_scan_type {
PayableScanType::New => self.handle_new(batch_results, logger),
PayableScanType::Retry => self.handle_retry(batch_results, logger),
PayableScanType::New => {
self.handle_batch_results_for_new_scan(batch_results, logger)
}
PayableScanType::Retry => {
self.handle_batch_results_for_retry_scan(batch_results, logger)
}
},
Err(local_error) => Self::log_local_error(local_error, logger),
}
}

fn handle_new(&self, batch_results: &BatchResults, logger: &Logger) {
let (sent, failed) = calculate_lengths(&batch_results);
fn handle_batch_results_for_new_scan(&self, batch_results: &BatchResults, logger: &Logger) {
let (sent, failed) = calculate_occurences(&batch_results);
debug!(
logger,
"Processed new txs while sending to RPC: {}",
Expand All @@ -185,8 +189,8 @@ impl PayableScanner {
}
}

fn handle_retry(&self, batch_results: &BatchResults, logger: &Logger) {
let (sent, failed) = calculate_lengths(&batch_results);
fn handle_batch_results_for_retry_scan(&self, batch_results: &BatchResults, logger: &Logger) {
let (sent, failed) = calculate_occurences(&batch_results);
debug!(
logger,
"Processed retried txs while sending to RPC: {}",
Expand Down Expand Up @@ -572,11 +576,14 @@ mod tests {
}

#[test]
fn handle_new_does_not_perform_any_operation_when_sent_txs_is_empty() {
let insert_new_records_params_sent = Arc::new(Mutex::new(vec![]));
fn handle_batch_results_for_new_scan_does_not_perform_any_operation_when_sent_txs_is_empty() {
let insert_new_records_sent_tx_params_arc = Arc::new(Mutex::new(vec![]));
let insert_new_records_failed_tx_params_arc = Arc::new(Mutex::new(vec![]));
let sent_payable_dao = SentPayableDaoMock::default()
.insert_new_records_params(&insert_new_records_params_sent);
let failed_payable_dao = FailedPayableDaoMock::default().insert_new_records_result(Ok(()));
.insert_new_records_params(&insert_new_records_sent_tx_params_arc);
let failed_payable_dao = FailedPayableDaoMock::default()
.insert_new_records_params(&insert_new_records_failed_tx_params_arc)
.insert_new_records_result(Ok(()));
let subject = PayableScannerBuilder::new()
.sent_payable_dao(sent_payable_dao)
.failed_payable_dao(failed_payable_dao)
Expand All @@ -586,13 +593,23 @@ mod tests {
failed_txs: vec![make_failed_tx(1)],
};

subject.handle_new(&batch_results, &Logger::new("test"));
subject.handle_batch_results_for_new_scan(&batch_results, &Logger::new("test"));

assert!(insert_new_records_params_sent.lock().unwrap().is_empty());
assert_eq!(
insert_new_records_failed_tx_params_arc
.lock()
.unwrap()
.len(),
1
);
assert!(insert_new_records_sent_tx_params_arc
.lock()
.unwrap()
.is_empty());
}

#[test]
fn handle_new_does_not_perform_any_operation_when_failed_txs_is_empty() {
fn handle_batch_results_for_new_scan_does_not_perform_any_operation_when_failed_txs_is_empty() {
let insert_new_records_params_failed = Arc::new(Mutex::new(vec![]));
let sent_payable_dao = SentPayableDaoMock::default().insert_new_records_result(Ok(()));
let failed_payable_dao = FailedPayableDaoMock::default()
Expand All @@ -606,18 +623,18 @@ mod tests {
failed_txs: vec![],
};

subject.handle_new(&batch_results, &Logger::new("test"));
subject.handle_batch_results_for_new_scan(&batch_results, &Logger::new("test"));

assert!(insert_new_records_params_failed.lock().unwrap().is_empty());
}

#[test]
fn handle_retry_does_not_perform_any_operation_when_sent_txs_is_empty() {
let insert_new_records_params_sent = Arc::new(Mutex::new(vec![]));
fn handle_batch_results_for_retry_scan_does_not_perform_any_operation_when_sent_txs_is_empty() {
let insert_new_records_sent_tx_params_arc = Arc::new(Mutex::new(vec![]));
let retrieve_txs_params = Arc::new(Mutex::new(vec![]));
let update_statuses_params = Arc::new(Mutex::new(vec![]));
let sent_payable_dao = SentPayableDaoMock::default()
.insert_new_records_params(&insert_new_records_params_sent);
.insert_new_records_params(&insert_new_records_sent_tx_params_arc);
let failed_payable_dao = FailedPayableDaoMock::default()
.retrieve_txs_params(&retrieve_txs_params)
.update_statuses_params(&update_statuses_params);
Expand All @@ -630,9 +647,12 @@ mod tests {
failed_txs: vec![make_failed_tx(1)],
};

subject.handle_retry(&batch_results, &Logger::new("test"));
subject.handle_batch_results_for_retry_scan(&batch_results, &Logger::new("test"));

assert!(insert_new_records_params_sent.lock().unwrap().is_empty());
assert!(insert_new_records_sent_tx_params_arc
.lock()
.unwrap()
.is_empty());
assert!(retrieve_txs_params.lock().unwrap().is_empty());
assert!(update_statuses_params.lock().unwrap().is_empty());
}
Expand All @@ -655,7 +675,7 @@ mod tests {
failed_txs: vec![],
};

subject.handle_retry(&batch_results, &Logger::new(test_name));
subject.handle_batch_results_for_retry_scan(&batch_results, &Logger::new(test_name));

let tlh = TestLogHandler::new();
tlh.exists_no_log_containing(&format!("WARN: {test_name}"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl PricedNewTxTemplates {
ceil: u128,
) -> String {
format!(
"The computed gas price {} wei is above the ceil value of {} wei set by the Node.\n\
"The computed gas price {} wei is above the ceil value of {} wei computed by this Node.\n\
Copy link
Contributor

@bertllll bertllll Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word "ceil" is a nonsense. And I don't think this kind of shortcut is widely used. 😬

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a commonly used word in programming terminology. See:

  1. Example 1 - JavaScript
  2. Example 2 - C
  3. Example 3 - Python
  4. Example 4 - Rust

I suggest you get used to it, it's short and it conveys what we mean.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But only among programmers and I wouldn't question it as a function name. This message is not necessarily meant for programmers. "Ceil" as a word doesn't exist and it probably is not used as a shortcut either. You should be looking into the linguistic dictionary, not the programming language documentation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transaction(s) to following receivers are affected:\n\
{}",
computed_gas_price_wei.separate_with_commas(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl RetryLogBuilder {
} else {
Some(format!(
"The computed gas price(s) in wei is \
above the ceil value of {} wei set by the Node.\n\
above the ceil value of {} wei computed by this Node.\n\
Transaction(s) to following receivers are affected:\n\
{}",
self.ceil.separate_with_commas(),
Expand Down
Loading