Skip to content

Commit df80ad7

Browse files
bertllllBert
andauthored
GH-664: HOT FIX ... updating at overflow SQL wrongly written (#224)
* GH-664: fixed the place with the critical issue and also created even better test coverage for receivable_dao.rs; gonna continue at payable_dao.rs too * GH-664: payable_dao.rs completed and another issue with optional parameters in the overflow sql * GH-644: neatened, when I had more time to fiddle with the code * GH-644: Clippy in Node/node * GH-664: libc changed back to version unspecified + making two tests stronger and sensitive to unintentionally changed rows Co-authored-by: Bert <[email protected]>
1 parent 773fcf0 commit df80ad7

File tree

5 files changed

+352
-117
lines changed

5 files changed

+352
-117
lines changed

multinode_integration_tests/docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
FROM debian:bookworm-slim
66

77
RUN apt-get update && \
8-
apt-get install -y libc6=2.36-6 && \
8+
apt-get install -y libc6 && \
99
# These lines are commented out because for some reason the installation of iptables-persistent hangs forever on
1010
# bullseye-slim. Its absence means that the NodeStartupConfigBuilder::open_firewall_port() function won't work, but
1111
# at the time of this comment it's used in only one place in a way that doesn't have any value. So we decided to

node/src/accountant/big_int_processing/big_int_db_processor.rs

Lines changed: 114 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl<'a, T: TableNameDAO> BigIntDbProcessor<T> {
2828
let mut stm = Self::prepare_statement(conn, main_sql);
2929
let params = config
3030
.params
31-
.merge_pure_rusqlite_and_wei_params((&config.params.wei_change_params).into());
31+
.merge_other_and_wei_params((&config.params.wei_change_params).into());
3232
match stm.execute(params.as_slice()) {
3333
Ok(_) => Ok(()),
3434
//SQLITE_CONSTRAINT_DATATYPE (3091),
@@ -119,7 +119,7 @@ impl<T: TableNameDAO> UpdateOverflowHandler<T> for UpdateOverflowHandlerReal<T>
119119

120120
let execute_params = config
121121
.params
122-
.merge_pure_rusqlite_and_wei_params(wei_update_array);
122+
.merge_other_and_wei_params_with_conditional_participants(wei_update_array);
123123

124124
Self::execute_update(conn, &config, &execute_params);
125125
Ok(())
@@ -219,7 +219,7 @@ impl<'a, T: TableNameDAO> BigIntSqlConfig<'a, T> {
219219
}
220220

221221
fn key_param_value(&self) -> &'a dyn ExtendedParamsMarker {
222-
self.params.params_except_wei_change[0].1
222+
self.params.params_except_wei_change[0].value_pair.1
223223
}
224224

225225
fn balance_change(&self) -> i128 {
@@ -267,7 +267,7 @@ impl_of_extended_params_marker!(i64, &str, Wallet);
267267
pub struct SQLParamsBuilder<'a> {
268268
key_spec_opt: Option<UniqueKeySpec<'a>>,
269269
wei_change_spec_opt: Option<WeiChange>,
270-
other_params: Vec<(&'a str, &'a dyn ExtendedParamsMarker)>,
270+
other_params: Vec<Param<'a>>,
271271
}
272272

273273
impl<'a> SQLParamsBuilder<'a> {
@@ -286,7 +286,7 @@ impl<'a> SQLParamsBuilder<'a> {
286286
self
287287
}
288288

289-
pub fn other(mut self, params: Vec<(&'a str, &'a (dyn ExtendedParamsMarker + 'a))>) -> Self {
289+
pub fn other(mut self, params: Vec<Param<'a>>) -> Self {
290290
self.other_params = params;
291291
self
292292
}
@@ -301,7 +301,7 @@ impl<'a> SQLParamsBuilder<'a> {
301301
let ((high_bytes_param_name, low_bytes_param_name), (high_bytes_value, low_bytes_value)) =
302302
Self::expand_wei_params(wei_change_spec);
303303
let key_as_the_first_param = (key_spec.substitution_name_in_sql, key_spec.value_itself);
304-
let params = once(key_as_the_first_param)
304+
let params = once(Param::new(key_as_the_first_param, true))
305305
.chain(self.other_params.into_iter())
306306
.collect();
307307
SQLParams {
@@ -386,7 +386,7 @@ impl Display for ByteMagnitude {
386386
pub struct SQLParams<'a> {
387387
table_unique_key_name: &'a str,
388388
wei_change_params: WeiChangeAsHighAndLowBytes,
389-
params_except_wei_change: Vec<(&'a str, &'a dyn ExtendedParamsMarker)>,
389+
params_except_wei_change: Vec<Param<'a>>,
390390
}
391391

392392
#[derive(Debug, PartialEq)]
@@ -407,6 +407,27 @@ impl StdNumParamFormNamed {
407407
}
408408
}
409409

410+
pub struct Param<'a> {
411+
value_pair: (&'a str, &'a dyn ExtendedParamsMarker),
412+
participates_in_overflow_clause: bool,
413+
}
414+
415+
impl<'a> Param<'a> {
416+
pub fn new(
417+
value_pair: (&'a str, &'a (dyn ExtendedParamsMarker + 'a)),
418+
participates_in_overflow_clause: bool,
419+
) -> Self {
420+
Self {
421+
value_pair,
422+
participates_in_overflow_clause,
423+
}
424+
}
425+
426+
fn as_rusqlite_params(&'a self) -> (&'a str, &'a dyn ToSql) {
427+
(self.value_pair.0, &self.value_pair.1 as &dyn ToSql)
428+
}
429+
}
430+
410431
impl<'a> From<&'a WeiChangeAsHighAndLowBytes> for [(&'a str, &'a dyn ToSql); 2] {
411432
fn from(wei_change: &'a WeiChangeAsHighAndLowBytes) -> Self {
412433
[
@@ -417,22 +438,32 @@ impl<'a> From<&'a WeiChangeAsHighAndLowBytes> for [(&'a str, &'a dyn ToSql); 2]
417438
}
418439

419440
impl<'a> SQLParams<'a> {
420-
fn merge_pure_rusqlite_and_wei_params(
441+
fn merge_other_and_wei_params(
421442
&'a self,
422443
wei_change_params: [(&'a str, &'a dyn ToSql); 2],
423444
) -> Vec<(&'a str, &'a dyn ToSql)> {
424-
self.pure_rusqlite_params(wei_change_params.into_iter())
425-
.collect()
445+
Self::merge_params(self.params_except_wei_change.iter(), wei_change_params)
426446
}
427447

428-
fn pure_rusqlite_params(
448+
fn merge_other_and_wei_params_with_conditional_participants(
429449
&'a self,
430-
wei_change_params: impl Iterator<Item = (&'a str, &'a dyn ToSql)>,
431-
) -> impl Iterator<Item = (&'a str, &'a dyn ToSql)> {
432-
self.params_except_wei_change
450+
wei_change_params: [(&'a str, &'a dyn ToSql); 2],
451+
) -> Vec<(&'a str, &'a dyn ToSql)> {
452+
let preselection = self
453+
.params_except_wei_change
433454
.iter()
434-
.map(|(name, value)| (*name, value as &dyn ToSql))
435-
.chain(wei_change_params)
455+
.filter(|param| param.participates_in_overflow_clause);
456+
Self::merge_params(preselection, wei_change_params)
457+
}
458+
459+
fn merge_params(
460+
params: impl Iterator<Item = &'a Param<'a>>,
461+
wei_change_params: [(&'a str, &'a dyn ToSql); 2],
462+
) -> Vec<(&'a str, &'a dyn ToSql)> {
463+
params
464+
.map(|param| param.as_rusqlite_params())
465+
.chain(wei_change_params.into_iter())
466+
.collect()
436467
}
437468
}
438469

@@ -546,14 +577,17 @@ mod tests {
546577
sub_name: ":some_key",
547578
val: &"blah",
548579
})
549-
.other(vec![("other_thing", &46565)]);
580+
.other(vec![Param::new(("other_thing", &46565), true)]);
550581

551582
assert_eq!(result.wei_change_spec_opt, Some(Addition("balance", 4546)));
552583
let key_spec = result.key_spec_opt.unwrap();
553584
assert_eq!(key_spec.definition_name, "some_key");
554585
assert_eq!(key_spec.substitution_name_in_sql, ":some_key");
555586
assert_eq!(key_spec.value_itself.to_string(), "blah".to_string());
556-
assert!(matches!(result.other_params[0], ("other_thing", _)));
587+
assert!(matches!(
588+
result.other_params[0].value_pair,
589+
("other_thing", _)
590+
));
557591
assert_eq!(result.other_params.len(), 1)
558592
}
559593

@@ -568,7 +602,7 @@ mod tests {
568602
sub_name: ":some_key",
569603
val: &"blah",
570604
})
571-
.other(vec![(":other_thing", &11111)])
605+
.other(vec![Param::new((":other_thing", &11111), true)])
572606
.build();
573607

574608
assert_eq!(result.table_unique_key_name, "some_key");
@@ -579,14 +613,17 @@ mod tests {
579613
low: StdNumParamFormNamed::new(":balance_low_b".to_string(), 115898)
580614
}
581615
);
582-
assert_eq!(result.params_except_wei_change[0].0, ":some_key");
616+
assert_eq!(result.params_except_wei_change[0].value_pair.0, ":some_key");
583617
assert_eq!(
584-
result.params_except_wei_change[0].1.to_string(),
618+
result.params_except_wei_change[0].value_pair.1.to_string(),
585619
"blah".to_string()
586620
);
587-
assert_eq!(result.params_except_wei_change[1].0, ":other_thing");
588621
assert_eq!(
589-
result.params_except_wei_change[1].1.to_string(),
622+
result.params_except_wei_change[1].value_pair.0,
623+
":other_thing"
624+
);
625+
assert_eq!(
626+
result.params_except_wei_change[1].value_pair.1.to_string(),
590627
"11111".to_string()
591628
);
592629
assert_eq!(result.params_except_wei_change.len(), 2)
@@ -603,7 +640,7 @@ mod tests {
603640
sub_name: ":some_key",
604641
val: &"wooow",
605642
})
606-
.other(vec![(":other_thing", &46565)])
643+
.other(vec![Param::new((":other_thing", &46565), true)])
607644
.build();
608645

609646
assert_eq!(result.table_unique_key_name, "some_key");
@@ -614,14 +651,17 @@ mod tests {
614651
low: StdNumParamFormNamed::new(":balance_low_b".to_string(), 9223372036854321124)
615652
}
616653
);
617-
assert_eq!(result.params_except_wei_change[0].0, ":some_key");
654+
assert_eq!(result.params_except_wei_change[0].value_pair.0, ":some_key");
618655
assert_eq!(
619-
result.params_except_wei_change[0].1.to_string(),
656+
result.params_except_wei_change[0].value_pair.1.to_string(),
620657
"wooow".to_string()
621658
);
622-
assert_eq!(result.params_except_wei_change[1].0, ":other_thing");
623659
assert_eq!(
624-
result.params_except_wei_change[1].1.to_string(),
660+
result.params_except_wei_change[1].value_pair.0,
661+
":other_thing"
662+
);
663+
assert_eq!(
664+
result.params_except_wei_change[1].value_pair.1.to_string(),
625665
"46565".to_string()
626666
);
627667
assert_eq!(result.params_except_wei_change.len(), 2)
@@ -634,7 +674,7 @@ mod tests {
634674

635675
let _ = subject
636676
.wei_change(Addition("balance", 4546))
637-
.other(vec![("laughter", &"hahaha")])
677+
.other(vec![Param::new(("laughter", &"hahaha"), true)])
638678
.build();
639679
}
640680

@@ -649,7 +689,7 @@ mod tests {
649689
sub_name: ":wallet",
650690
val: &make_wallet("wallet"),
651691
})
652-
.other(vec![("other_thing", &46565)])
692+
.other(vec![Param::new(("other_thing", &46565), true)])
653693
.build();
654694
}
655695

@@ -667,6 +707,50 @@ mod tests {
667707
.build();
668708
}
669709

710+
#[test]
711+
fn merge_other_and_wei_params_with_conditional_participants_can_filter_out_just_update_params()
712+
{
713+
let tuple_matrix = [
714+
("blah", &456_i64 as &dyn ExtendedParamsMarker),
715+
("super key", &"abcxy"),
716+
("time", &779988),
717+
("error", &"no threat"),
718+
];
719+
let update_positive_1 = tuple_matrix[0];
720+
let update_positive_2 = tuple_matrix[1];
721+
let update_negative_1 = tuple_matrix[2];
722+
let update_negative_2 = tuple_matrix[3];
723+
let subject = SQLParams {
724+
table_unique_key_name: "",
725+
wei_change_params: WeiChangeAsHighAndLowBytes {
726+
high: StdNumParamFormNamed {
727+
name: "".to_string(),
728+
value: 0,
729+
},
730+
low: StdNumParamFormNamed {
731+
name: "".to_string(),
732+
value: 0,
733+
},
734+
},
735+
params_except_wei_change: vec![
736+
Param::new(update_positive_2, true),
737+
Param::new(update_negative_1, false),
738+
Param::new(update_positive_1, true),
739+
Param::new(update_negative_2, false),
740+
],
741+
};
742+
743+
let result = subject.merge_other_and_wei_params_with_conditional_participants([
744+
("always_present_1", &12),
745+
("always_present_2", &77),
746+
]);
747+
748+
assert_eq!(result[0].0, update_positive_2.0);
749+
assert_eq!(result[1].0, update_positive_1.0);
750+
assert_eq!(result[2].0, "always_present_1");
751+
assert_eq!(result[3].0, "always_present_2")
752+
}
753+
670754
#[test]
671755
fn return_first_error_works_for_first_error() {
672756
let results = [Err(Error::GetAuxWrongType), Ok(45465)];

node/src/accountant/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ pub struct ResponseSkeleton {
113113

114114
#[derive(Debug, Message, PartialEq, Eq)]
115115
pub struct ReceivedPayments {
116+
//TODO When we decide whether to delinquency-ban a debtor, we do so based on the age
117+
// of his debt. That age is calculated from the last time he made a payment. It would
118+
// be most accurate to draw that timestamp from the time the block containing the
119+
// payment was placed on the blockchain; however, we're actually drawing the timestamp
120+
// from the moment we discovered and accepted the payment, which is less accurate and
121+
// detects any upcoming delinquency later than the more accurate version would. Is this
122+
// a problem? Do we want to correct the timestamp? Discuss.
116123
pub timestamp: SystemTime,
117124
pub payments: Vec<BlockchainTransaction>,
118125
pub response_skeleton_opt: Option<ResponseSkeleton>,

0 commit comments

Comments
 (0)