Skip to content

Commit 7a664d6

Browse files
bertllllBert
andauthored
GH-683: Well structualized blockchain errors (#684)
* GH-683: savepoint * GH-683: interim commit * GH-683: mostly done * GH-683: renamed error * GH-683: additional fix to renaming * GH-683: finished * GH-683: fixed for a review * GH-683: fixed screwed string replacement * GH-683: finished fixing it * GH-683: another fix...BlockchainError --------- Co-authored-by: Bert <Bert@Bert.com>
1 parent b46c9b2 commit 7a664d6

File tree

18 files changed

+657
-264
lines changed

18 files changed

+657
-264
lines changed

node/src/accountant/db_access_objects/failed_payable_dao.rs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use crate::accountant::db_access_objects::utils::{
44
};
55
use crate::accountant::db_big_integer::big_int_divider::BigIntDivider;
66
use crate::accountant::{checked_conversion, comma_joined_stringifiable};
7-
use crate::blockchain::errors::AppRpcError;
7+
use crate::blockchain::errors::rpc_errors::AppRpcErrorKind;
8+
use crate::blockchain::errors::validation_status::PreviousAttempts;
89
use crate::database::rusqlite_wrappers::ConnectionWrapper;
910
use itertools::Itertools;
1011
use masq_lib::utils::ExpectValue;
@@ -25,7 +26,7 @@ pub enum FailedPayableDaoError {
2526

2627
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2728
pub enum FailureReason {
28-
Submission(AppRpcError),
29+
Submission(AppRpcErrorKind),
2930
Reverted,
3031
PendingTooLong,
3132
}
@@ -75,7 +76,7 @@ impl FromStr for FailureStatus {
7576
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7677
pub enum ValidationStatus {
7778
Waiting,
78-
Reattempting { attempt: usize, error: AppRpcError },
79+
Reattempting(PreviousAttempts),
7980
}
8081

8182
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -381,16 +382,22 @@ mod tests {
381382
make_read_only_db_connection, FailedTxBuilder,
382383
};
383384
use crate::accountant::db_access_objects::utils::current_unix_timestamp;
384-
use crate::blockchain::errors::{AppRpcError, LocalError, RemoteError};
385-
use crate::blockchain::test_utils::make_tx_hash;
385+
use crate::blockchain::errors::rpc_errors::AppRpcErrorKind;
386+
use crate::blockchain::errors::validation_status::{
387+
PreviousAttempts, ValidationFailureClockReal,
388+
};
389+
use crate::blockchain::errors::BlockchainErrorKind;
390+
use crate::blockchain::test_utils::{make_tx_hash, ValidationFailureClockMock};
386391
use crate::database::db_initializer::{
387392
DbInitializationConfig, DbInitializer, DbInitializerReal,
388393
};
389394
use crate::database::test_utils::ConnectionWrapperMock;
390395
use masq_lib::test_utils::utils::ensure_node_home_directory_exists;
391396
use rusqlite::Connection;
392397
use std::collections::{HashMap, HashSet};
398+
use std::ops::Add;
393399
use std::str::FromStr;
400+
use std::time::{Duration, SystemTime};
394401

395402
#[test]
396403
fn insert_new_records_works() {
@@ -584,11 +591,8 @@ mod tests {
584591
fn failure_reason_from_str_works() {
585592
// Submission error
586593
assert_eq!(
587-
FailureReason::from_str(r#"{"Submission":{"Local":{"Decoder":"Test decoder error"}}}"#)
588-
.unwrap(),
589-
FailureReason::Submission(AppRpcError::Local(LocalError::Decoder(
590-
"Test decoder error".to_string()
591-
)))
594+
FailureReason::from_str(r#"{"Submission":{"Local":{"Decoder"}}}"#).unwrap(),
595+
FailureReason::Submission(AppRpcErrorKind::Decoder)
592596
);
593597

594598
// Reverted
@@ -620,6 +624,11 @@ mod tests {
620624

621625
#[test]
622626
fn failure_status_from_str_works() {
627+
let validation_failure_clock = ValidationFailureClockMock::default().now_result(
628+
SystemTime::UNIX_EPOCH
629+
.add(Duration::from_secs(1755080031))
630+
.add(Duration::from_nanos(612180914)),
631+
);
623632
assert_eq!(
624633
FailureStatus::from_str("\"RetryRequired\"").unwrap(),
625634
FailureStatus::RetryRequired
@@ -631,8 +640,8 @@ mod tests {
631640
);
632641

633642
assert_eq!(
634-
FailureStatus::from_str(r#"{"RecheckRequired":{"Reattempting":{"attempt":2,"error":{"Remote":"Unreachable"}}}}"#).unwrap(),
635-
FailureStatus::RecheckRequired(ValidationStatus::Reattempting { attempt: 2, error: AppRpcError::Remote(RemoteError::Unreachable) })
643+
FailureStatus::from_str(r#"{"RecheckRequired":{"Reattempting":{"ServerUnreachable":{"firstSeen":{"secs_since_epoch":1755080031,"nanos_since_epoch":612180914},"attempts":1}}}}"#).unwrap(),
644+
FailureStatus::RecheckRequired(ValidationStatus::Reattempting( PreviousAttempts::new(BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable), &validation_failure_clock)))
636645
);
637646

638647
assert_eq!(
@@ -713,10 +722,12 @@ mod tests {
713722
let tx3 = FailedTxBuilder::default()
714723
.hash(make_tx_hash(3))
715724
.reason(PendingTooLong)
716-
.status(RecheckRequired(ValidationStatus::Reattempting {
717-
attempt: 1,
718-
error: AppRpcError::Remote(RemoteError::Unreachable),
719-
}))
725+
.status(RecheckRequired(ValidationStatus::Reattempting(
726+
PreviousAttempts::new(
727+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
728+
&ValidationFailureClockReal::default(),
729+
),
730+
)))
720731
.build();
721732
let tx4 = FailedTxBuilder::default()
722733
.hash(make_tx_hash(4))
@@ -768,10 +779,10 @@ mod tests {
768779
(tx1.hash, Concluded),
769780
(
770781
tx2.hash,
771-
RecheckRequired(ValidationStatus::Reattempting {
772-
attempt: 1,
773-
error: AppRpcError::Remote(RemoteError::Unreachable),
774-
}),
782+
RecheckRequired(ValidationStatus::Reattempting(PreviousAttempts::new(
783+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
784+
&ValidationFailureClockReal::default(),
785+
))),
775786
),
776787
(tx3.hash, Concluded),
777788
]);
@@ -785,10 +796,10 @@ mod tests {
785796
assert_eq!(tx2.status, RecheckRequired(ValidationStatus::Waiting));
786797
assert_eq!(
787798
updated_txs[1].status,
788-
RecheckRequired(ValidationStatus::Reattempting {
789-
attempt: 1,
790-
error: AppRpcError::Remote(RemoteError::Unreachable)
791-
})
799+
RecheckRequired(ValidationStatus::Reattempting(PreviousAttempts::new(
800+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
801+
&ValidationFailureClockReal::default()
802+
)))
792803
);
793804
assert_eq!(tx3.status, RetryRequired);
794805
assert_eq!(updated_txs[2].status, Concluded);

node/src/accountant/db_access_objects/sent_payable_dao.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,10 @@ impl SentPayableDao for SentPayableDaoReal<'_> {
424424
#[cfg(test)]
425425
mod tests {
426426
use std::collections::{HashMap, HashSet};
427+
use std::ops::Add;
427428
use std::str::FromStr;
428429
use std::sync::{Arc, Mutex};
430+
use std::time::{Duration, UNIX_EPOCH};
429431
use crate::accountant::db_access_objects::sent_payable_dao::{Detection, RetrieveCondition, SentPayableDao, SentPayableDaoError, SentPayableDaoReal, TxConfirmation, TxStatus};
430432
use crate::database::db_initializer::{
431433
DbInitializationConfig, DbInitializer, DbInitializerReal,
@@ -439,8 +441,10 @@ mod tests {
439441
use crate::accountant::db_access_objects::sent_payable_dao::SentPayableDaoError::{EmptyInput, PartialExecution};
440442
use crate::accountant::db_access_objects::test_utils::{make_read_only_db_connection, TxBuilder};
441443
use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TransactionBlock};
442-
use crate::blockchain::errors::{AppRpcError, RemoteError};
443-
use crate::blockchain::test_utils::{make_block_hash, make_tx_hash};
444+
use crate::blockchain::errors::BlockchainErrorKind;
445+
use crate::blockchain::errors::rpc_errors::AppRpcErrorKind;
446+
use crate::blockchain::errors::validation_status::{PreviousAttempts, ValidationFailureClockReal};
447+
use crate::blockchain::test_utils::{make_block_hash, make_tx_hash, ValidationFailureClockMock};
444448

445449
#[test]
446450
fn insert_new_records_works() {
@@ -452,10 +456,16 @@ mod tests {
452456
let tx1 = TxBuilder::default().hash(make_tx_hash(1)).build();
453457
let tx2 = TxBuilder::default()
454458
.hash(make_tx_hash(2))
455-
.status(TxStatus::Pending(ValidationStatus::Reattempting {
456-
attempt: 2,
457-
error: AppRpcError::Remote(RemoteError::Unreachable),
458-
}))
459+
.status(TxStatus::Pending(ValidationStatus::Reattempting(
460+
PreviousAttempts::new(
461+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
462+
&ValidationFailureClockReal::default(),
463+
)
464+
.add_attempt(
465+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
466+
&ValidationFailureClockReal::default(),
467+
),
468+
)))
459469
.build();
460470
let subject = SentPayableDaoReal::new(wrapped_conn);
461471
let txs = vec![tx1, tx2];
@@ -682,10 +692,12 @@ mod tests {
682692
.build();
683693
let tx2 = TxBuilder::default()
684694
.hash(make_tx_hash(2))
685-
.status(TxStatus::Pending(ValidationStatus::Reattempting {
686-
attempt: 1,
687-
error: AppRpcError::Remote(RemoteError::Unreachable),
688-
}))
695+
.status(TxStatus::Pending(ValidationStatus::Reattempting(
696+
PreviousAttempts::new(
697+
BlockchainErrorKind::AppRpc(AppRpcErrorKind::ServerUnreachable),
698+
&ValidationFailureClockReal::default(),
699+
),
700+
)))
689701
.build();
690702
let tx3 = TxBuilder::default()
691703
.hash(make_tx_hash(3))
@@ -1169,14 +1181,16 @@ mod tests {
11691181

11701182
#[test]
11711183
fn tx_status_from_str_works() {
1184+
let validation_failure_clock = ValidationFailureClockMock::default()
1185+
.now_result(UNIX_EPOCH.add(Duration::from_secs(12456)));
11721186
assert_eq!(
11731187
TxStatus::from_str(r#"{"Pending":"Waiting"}"#).unwrap(),
11741188
TxStatus::Pending(ValidationStatus::Waiting)
11751189
);
11761190

11771191
assert_eq!(
1178-
TxStatus::from_str(r#"{"Pending":{"Reattempting":{"attempt":3,"error":{"Remote":{"InvalidResponse":"bluh"}}}}}"#).unwrap(),
1179-
TxStatus::Pending(ValidationStatus::Reattempting { attempt: 3, error: AppRpcError::Remote(RemoteError::InvalidResponse("bluh".to_string())) })
1192+
TxStatus::from_str(r#"{"Pending":{"Reattempting":{"InvalidResponse":{"firstSeen":{"secs_since_epoch":12456,"nanos_since_epoch":0},"attempts":1}}}}"#).unwrap(),
1193+
TxStatus::Pending(ValidationStatus::Reattempting(PreviousAttempts::new(BlockchainErrorKind::AppRpc(AppRpcErrorKind::InvalidResponse), &validation_failure_clock)))
11801194
);
11811195

11821196
assert_eq!(

node/src/accountant/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4020,7 +4020,7 @@ mod tests {
40204020
// the first message. Now we reset the state by ending the first scan by a failure and see
40214021
// that the third scan request is going to be accepted willingly again.
40224022
addr.try_send(SentPayables {
4023-
payment_procedure_result: Err(PayableTransactionError::Signing("bluh".to_string())),
4023+
payment_procedure_result: Err(PayableTransactionError::Signing("blah".to_string())),
40244024
response_skeleton_opt: Some(ResponseSkeleton {
40254025
client_id: 1122,
40264026
context_id: 7788,

node/src/accountant/scanners/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@ pub mod test_utils;
99

1010
use crate::accountant::db_access_objects::payable_dao::{PayableAccount, PayableDao};
1111
use crate::accountant::db_access_objects::pending_payable_dao::{PendingPayable, PendingPayableDao};
12-
use crate::accountant::db_access_objects::receivable_dao::ReceivableDao;
1312
use crate::accountant::payment_adjuster::{PaymentAdjuster, PaymentAdjusterReal};
1413
use crate::accountant::scanners::scanners_utils::payable_scanner_utils::PayableTransactingErrorEnum::{
1514
LocallyCausedError, RemotelyCausedErrors,
1615
};
1716
use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{debugging_summary_after_error_separation, err_msg_for_failure_with_expected_but_missing_fingerprints, investigate_debt_extremes, mark_pending_payable_fatal_error, payables_debug_summary, separate_errors, separate_rowids_and_hashes, OperationOutcome, PayableScanResult, PayableThresholdsGauge, PayableThresholdsGaugeReal, PayableTransactingErrorEnum, PendingPayableMetadata};
18-
use crate::accountant::{PendingPayableId, ScanError, ScanForPendingPayables, ScanForRetryPayables};
17+
use crate::accountant::{ScanError, ScanForPendingPayables, ScanForRetryPayables};
1918
use crate::accountant::{
2019
comma_joined_stringifiable, gwei_to_wei, ReceivedPayments,
2120
ReportTransactionReceipts, RequestTransactionReceipts, ResponseSkeleton, ScanForNewPayables,
2221
ScanForReceivables, SentPayables,
2322
};
24-
use crate::blockchain::blockchain_bridge::{BlockMarker, PendingPayableFingerprint, RetrieveTransactions};
23+
use crate::blockchain::blockchain_bridge::{RetrieveTransactions};
2524
use crate::sub_lib::accountant::{
2625
DaoFactories, FinancialStatistics, PaymentThresholds,
2726
};
@@ -48,7 +47,6 @@ use crate::accountant::scanners::payable_scanner_extension::msgs::{BlockchainAge
4847
use crate::accountant::scanners::pending_payable_scanner::PendingPayableScanner;
4948
use crate::accountant::scanners::pending_payable_scanner::utils::PendingPayableScanResult;
5049
use crate::accountant::scanners::receivable_scanner::ReceivableScanner;
51-
use crate::blockchain::blockchain_interface::blockchain_interface_web3::lower_level_interface_web3::{TxStatus};
5250
use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError;
5351
use crate::db_config::persistent_configuration::{PersistentConfigurationReal};
5452

@@ -976,10 +974,10 @@ mod tests {
976974
};
977975
use crate::accountant::db_access_objects::utils::{from_unix_timestamp, to_unix_timestamp};
978976
use crate::accountant::scanners::payable_scanner_extension::msgs::{QualifiedPayablesBeforeGasPriceSelection, QualifiedPayablesMessage, UnpricedQualifiedPayables};
979-
use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult, PendingPayableMetadata};
977+
use crate::accountant::scanners::scanners_utils::payable_scanner_utils::{OperationOutcome, PayableScanResult};
980978
use crate::accountant::scanners::{Scanner, StartScanError, StartableScanner, PayableScanner, PendingPayableScanner, ReceivableScanner, ScannerCommon, Scanners, ManulTriggerError};
981979
use crate::accountant::test_utils::{make_custom_payment_thresholds, make_payable_account, make_qualified_and_unqualified_payables, make_pending_payable_fingerprint, make_receivable_account, BannedDaoFactoryMock, BannedDaoMock, ConfigDaoFactoryMock, PayableDaoFactoryMock, PayableDaoMock, PayableScannerBuilder, PayableThresholdsGaugeMock, PendingPayableDaoFactoryMock, PendingPayableDaoMock, PendingPayableScannerBuilder, ReceivableDaoFactoryMock, ReceivableDaoMock, ReceivableScannerBuilder};
982-
use crate::accountant::{gwei_to_wei, PendingPayableId, ReceivedPayments, ReportTransactionReceipts, RequestTransactionReceipts, ScanError, ScanForRetryPayables, SentPayables, DEFAULT_PENDING_TOO_LONG_SEC};
980+
use crate::accountant::{gwei_to_wei, ReceivedPayments, ReportTransactionReceipts, RequestTransactionReceipts, ScanError, ScanForRetryPayables, SentPayables};
983981
use crate::blockchain::blockchain_bridge::{BlockMarker, PendingPayableFingerprint, RetrieveTransactions};
984982
use crate::blockchain::blockchain_interface::data_structures::errors::PayableTransactionError;
985983
use crate::blockchain::blockchain_interface::data_structures::{
@@ -1004,13 +1002,11 @@ mod tests {
10041002
use regex::{Regex};
10051003
use rusqlite::{ffi, ErrorCode};
10061004
use std::cell::RefCell;
1007-
use std::collections::HashSet;
1008-
use std::ops::Sub;
10091005
use std::panic::{catch_unwind, AssertUnwindSafe};
10101006
use std::rc::Rc;
10111007
use std::sync::{Arc, Mutex};
10121008
use std::time::{Duration, SystemTime};
1013-
use web3::types::{TransactionReceipt, H256};
1009+
use web3::types::{H256};
10141010
use web3::Error;
10151011
use masq_lib::messages::ScanType;
10161012
use masq_lib::ui_gateway::NodeToUiMessage;
@@ -3099,7 +3095,7 @@ mod tests {
30993095
ScanError {
31003096
scan_type,
31013097
response_skeleton_opt: None,
3102-
msg: "bluh".to_string(),
3098+
msg: "blah".to_string(),
31033099
}
31043100
}
31053101

node/src/accountant/scanners/scanners_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ mod tests {
342342
use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler};
343343
use std::time::SystemTime;
344344
use crate::accountant::db_access_objects::pending_payable_dao::PendingPayable;
345-
use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainError, PayableTransactionError};
345+
use crate::blockchain::blockchain_interface::data_structures::errors::{BlockchainInterfaceError, PayableTransactionError};
346346
use crate::blockchain::blockchain_interface::data_structures::{ProcessedPayableFallible, RpcPayableFailure};
347347

348348
#[test]
@@ -645,11 +645,11 @@ mod tests {
645645
#[test]
646646
fn count_total_errors_says_unknown_number_for_early_local_errors() {
647647
let early_local_errors = [
648-
PayableTransactionError::TransactionID(BlockchainError::QueryFailed(
648+
PayableTransactionError::TransactionID(BlockchainInterfaceError::QueryFailed(
649649
"blah".to_string(),
650650
)),
651651
PayableTransactionError::MissingConsumingWallet,
652-
PayableTransactionError::GasPriceQueryFailed(BlockchainError::QueryFailed(
652+
PayableTransactionError::GasPriceQueryFailed(BlockchainInterfaceError::QueryFailed(
653653
"ouch".to_string(),
654654
)),
655655
PayableTransactionError::UnusableWallet("fooo".to_string()),

0 commit comments

Comments
 (0)