Skip to content

Commit 2685f85

Browse files
committed
Merge branch 'tomas/checked-arith' (#3074)
* origin/tomas/checked-arith: changelog: add #3074 namada/pos: re-use into_tm_voting_power from pos crate wasm: update to non-panicking core API benches: update to non-panicking core API apps: update to non-panicking core API namada: update to non-panicking core API sdk: update to non-panicking core API eth_bridge: update to non-panicking core API ibc: update to non-panicking core API pos: update to non-panicking core API gov: update to non-panicking core API state: update to non-panicking core API shielded_token: update to non-panicking core API trans_token: update to non-panicking core API vote_ext: update to non-panicking core API controller: replacing panicking code storage/collections/lazy_map: add try_update storage: add conv from core::arith::Error for convenience test/core: fixes for checked arith core: clippy fixes core/dec: sanitize panicking code core/storage: sanitize panicking code core/token: sanitize panicking code core/uint: sanitize panicking code core: add `assert_matches` dev-dep core/voting_power: sanitize panicking code core: strict clippy arith deps: add smooth-operator and re-export from core/arith core: add arith mod with a custom `trait CheckedAdd`
2 parents a11b18b + a78ec98 commit 2685f85

File tree

89 files changed

+2381
-1625
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+2381
-1625
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Prohibit unchecked arithmetics and conversions in the core crate.
2+
([\#3074](https://github.com/anoma/namada/pull/3074))

Cargo.lock

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ sha2 = "0.9.3"
157157
sha2-const = "0.1.2"
158158
signal-hook = "0.3.9"
159159
slip10_ed25519 = "0.1.3"
160+
smooth-operator = {git = "https://github.com/heliaxdev/smooth-operator", tag = "v0.6.0"}
160161
# sysinfo with disabled multithread feature
161162
sysinfo = {version = "0.27.8", default-features = false}
162163
tar = "0.4.37"

crates/apps/src/bin/namada-node/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub fn main() -> Result<()> {
5959
let wasm_dir = chain_ctx.wasm_dir();
6060
chain_ctx.config.ledger.shell.action_at_height =
6161
Some(ActionAtHeight {
62-
height: args.last_height + 2,
62+
height: args.last_height.checked_add(2).unwrap(),
6363
action: Action::Halt,
6464
});
6565
std::env::set_var(

crates/apps/src/lib/bench_utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ impl Default for BenchShell {
257257
author: defaults::albert_address(),
258258
r#type: ProposalType::Default,
259259
voting_start_epoch,
260-
voting_end_epoch: voting_start_epoch + 3_u64,
261-
activation_epoch: voting_start_epoch + 9_u64,
260+
voting_end_epoch: voting_start_epoch.unchecked_add(3_u64),
261+
activation_epoch: voting_start_epoch.unchecked_add(9_u64),
262262
},
263263
None,
264264
Some(vec![content_section]),
@@ -417,7 +417,7 @@ impl BenchShell {
417417
&mut self.state,
418418
&params,
419419
current_epoch,
420-
current_epoch + params.pipeline_len,
420+
current_epoch.unchecked_add(params.pipeline_len),
421421
)
422422
.unwrap();
423423

@@ -573,7 +573,7 @@ impl BenchShell {
573573
self.inner
574574
.state
575575
.in_mem_mut()
576-
.begin_block(last_height + 1)
576+
.begin_block(last_height.next_height())
577577
.unwrap();
578578

579579
self.inner.commit();

crates/apps/src/lib/client/rpc.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -859,11 +859,13 @@ pub async fn query_and_print_unbonds(
859859
let mut not_yet_withdrawable = HashMap::<Epoch, token::Amount>::new();
860860
for ((_start_epoch, withdraw_epoch), amount) in unbonds.into_iter() {
861861
if withdraw_epoch <= current_epoch {
862-
total_withdrawable += amount;
862+
total_withdrawable =
863+
total_withdrawable.checked_add(amount).unwrap();
863864
} else {
864865
let withdrawable_amount =
865866
not_yet_withdrawable.entry(withdraw_epoch).or_default();
866-
*withdrawable_amount += amount;
867+
*withdrawable_amount =
868+
withdrawable_amount.checked_add(amount).unwrap();
867869
}
868870
}
869871
if !total_withdrawable.is_zero() {
@@ -948,7 +950,7 @@ pub async fn query_bonds(
948950
context.io(),
949951
&mut w;
950952
"Active (slashable) bonds total: {}",
951-
details.bonds_total_active().to_string_native()
953+
details.bonds_total_active().unwrap().to_string_native()
952954
)?;
953955
}
954956
display_line!(context.io(), &mut w; "Bonds total: {}", details.bonds_total.to_string_native())?;
@@ -992,7 +994,7 @@ pub async fn query_bonds(
992994
context.io(),
993995
&mut w;
994996
"All bonds total active: {}",
995-
bonds_and_unbonds.bonds_total_active().to_string_native()
997+
bonds_and_unbonds.bonds_total_active().unwrap().to_string_native()
996998
)?;
997999
}
9981000
display_line!(
@@ -1015,7 +1017,7 @@ pub async fn query_bonds(
10151017
context.io(),
10161018
&mut w;
10171019
"All unbonds total active: {}",
1018-
bonds_and_unbonds.unbonds_total_active().to_string_native()
1020+
bonds_and_unbonds.unbonds_total_active().unwrap().to_string_native()
10191021
)?;
10201022
}
10211023
display_line!(

crates/apps/src/lib/client/utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,10 @@ pub fn init_network(
430430
if tm_votes_per_token > Dec::from(1) {
431431
Uint::one()
432432
} else {
433-
(Dec::from(1) / tm_votes_per_token).ceil().abs()
433+
(Dec::from(1).checked_div(tm_votes_per_token).unwrap())
434+
.ceil()
435+
.unwrap()
436+
.abs()
434437
},
435438
token::NATIVE_MAX_DECIMAL_PLACES,
436439
)

crates/apps/src/lib/config/genesis/transactions.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ impl Transactions<Validated> {
543543
BTreeMap::new();
544544
for tx in txs {
545545
let entry = stakes.entry(&tx.validator).or_default();
546-
*entry += tx.amount.amount();
546+
*entry = entry
547+
.checked_add(tx.amount.amount())
548+
.expect("Validator total stake must not overflow");
547549
}
548550

549551
stakes.into_values().any(|stake| {

crates/apps/src/lib/node/ledger/ethereum_oracle/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ async fn run_oracle_aux<C: RpcClient>(mut oracle: Oracle<C>) {
452452
if !config.active {
453453
config = oracle.wait_on_reactivation().await;
454454
}
455-
next_block_to_process += 1.into();
455+
next_block_to_process = next_block_to_process.next();
456456
}
457457
}
458458

@@ -481,8 +481,9 @@ async fn process_events_in_block<C: RpcClient>(
481481
SyncStatus::Syncing => return Err(Error::FallenBehind),
482482
}
483483
.into();
484-
let minimum_latest_block =
485-
block_to_process.clone() + config.min_confirmations.into();
484+
let minimum_latest_block = block_to_process.clone().unchecked_add(
485+
ethereum_structs::BlockHeight::from(config.min_confirmations),
486+
);
486487
if minimum_latest_block > latest_block {
487488
tracing::debug!(
488489
?block_to_process,

crates/apps/src/lib/node/ledger/shell/finalize_block.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ where
545545
/// if necessary. Returns a bool indicating if a new epoch began and the
546546
/// height of the new block.
547547
fn update_state(&mut self, header: Header) -> (BlockHeight, bool) {
548-
let height = self.state.in_mem().get_last_block_height() + 1;
548+
let height = self.state.in_mem().get_last_block_height().next_height();
549549

550550
self.state
551551
.in_mem_mut()
@@ -597,7 +597,9 @@ where
597597
current_epoch: Epoch,
598598
events: &mut impl EmitEvents,
599599
) -> Result<()> {
600-
let last_epoch = current_epoch.prev();
600+
let last_epoch = current_epoch
601+
.prev()
602+
.expect("Must have a prev epoch when applying inflation");
601603

602604
// Get the number of blocks in the last epoch
603605
let first_block_of_last_epoch =
@@ -622,11 +624,9 @@ where
622624

623625
// Take events that may be emitted from PGF
624626
for event in self.state.write_log_mut().take_events() {
625-
events.emit(
626-
event.with(Height(
627-
self.state.in_mem().get_last_block_height() + 1,
628-
)),
629-
);
627+
events.emit(event.with(Height(
628+
self.state.in_mem().get_last_block_height().next_height(),
629+
)));
630630
}
631631

632632
Ok(())
@@ -1923,7 +1923,8 @@ mod test_finalize_block {
19231923
// The total rewards claimed should be approximately equal to the total
19241924
// minted inflation, minus (unbond_amount / initial_stake) * rewards
19251925
// from the unbond epoch and the following epoch (the missed_rewards)
1926-
let ratio = Dec::from(unbond_amount) / Dec::from(init_stake);
1926+
let ratio = Dec::try_from(unbond_amount).unwrap()
1927+
/ Dec::try_from(init_stake).unwrap();
19271928
let lost_rewards = ratio * missed_rewards;
19281929
let uncertainty = Dec::from_str("0.07").unwrap();
19291930
let token_uncertainty = uncertainty * lost_rewards;
@@ -2087,8 +2088,8 @@ mod test_finalize_block {
20872088
));
20882089

20892090
// Check that the commission earned is expected
2090-
let del_stake = Dec::from(del_amount);
2091-
let tot_stake = Dec::from(init_stake + del_amount);
2091+
let del_stake = Dec::try_from(del_amount).unwrap();
2092+
let tot_stake = Dec::try_from(init_stake + del_amount).unwrap();
20922093
let stake_ratio = del_stake / tot_stake;
20932094
let del_rewards_no_commission = stake_ratio * inflation_3;
20942095
let commission = commission_rate * del_rewards_no_commission;
@@ -3592,7 +3593,7 @@ mod test_finalize_block {
35923593
let total_stake =
35933594
read_total_stake(&shell.state, &params, pipeline_epoch)?;
35943595

3595-
let expected_slashed = initial_stake.mul_ceil(cubic_rate);
3596+
let expected_slashed = initial_stake.mul_ceil(cubic_rate).unwrap();
35963597

35973598
println!(
35983599
"Initial stake = {}\nCubic rate = {}\nExpected slashed = {}\n",
@@ -4115,8 +4116,10 @@ mod test_finalize_block {
41154116
)
41164117
.unwrap();
41174118

4118-
let vp_frac_3 = Dec::from(val_stake_3) / Dec::from(tot_stake_3);
4119-
let vp_frac_4 = Dec::from(val_stake_4) / Dec::from(tot_stake_4);
4119+
let vp_frac_3 = Dec::try_from(val_stake_3).unwrap()
4120+
/ Dec::try_from(tot_stake_3).unwrap();
4121+
let vp_frac_4 = Dec::try_from(val_stake_4).unwrap()
4122+
/ Dec::try_from(tot_stake_4).unwrap();
41204123
let tot_frac = Dec::two() * vp_frac_3 + vp_frac_4;
41214124
let cubic_rate = std::cmp::min(
41224125
Dec::one(),
@@ -4126,7 +4129,7 @@ mod test_finalize_block {
41264129

41274130
let equal_enough = |rate1: Dec, rate2: Dec| -> bool {
41284131
let tolerance = Dec::new(1, 9).unwrap();
4129-
rate1.abs_diff(&rate2) < tolerance
4132+
rate1.abs_diff(rate2).unwrap() < tolerance
41304133
};
41314134

41324135
// There should be 2 slashes processed for the validator, each with rate
@@ -4162,7 +4165,8 @@ mod test_finalize_block {
41624165
- del_unbond_1_amount
41634166
+ self_bond_1_amount
41644167
- self_unbond_2_amount)
4165-
.mul_ceil(slash_rate_3);
4168+
.mul_ceil(slash_rate_3)
4169+
.unwrap();
41664170
assert!(
41674171
((pre_stake_10 - post_stake_10).change()
41684172
- exp_slashed_during_processing_9.change())
@@ -4176,22 +4180,27 @@ mod test_finalize_block {
41764180
// Check that we can compute the stake at the pipeline epoch
41774181
// NOTE: may be off. by 1 namnam due to rounding;
41784182
let exp_pipeline_stake = (Dec::one() - slash_rate_3)
4179-
* Dec::from(
4183+
* Dec::try_from(
41804184
initial_stake + del_1_amount
41814185
- self_unbond_1_amount
41824186
- del_unbond_1_amount
41834187
+ self_bond_1_amount
41844188
- self_unbond_2_amount,
41854189
)
4186-
+ Dec::from(del_2_amount);
4190+
.unwrap()
4191+
+ Dec::try_from(del_2_amount).unwrap();
41874192

41884193
assert!(
4189-
exp_pipeline_stake.abs_diff(&Dec::from(post_stake_10))
4194+
exp_pipeline_stake
4195+
.abs_diff(Dec::try_from(post_stake_10).unwrap())
4196+
.unwrap()
41904197
<= Dec::new(2, NATIVE_MAX_DECIMAL_PLACES).unwrap(),
41914198
"Expected {}, got {} (with less than 2 err), diff {}",
41924199
exp_pipeline_stake,
41934200
post_stake_10.to_string_native(),
4194-
exp_pipeline_stake.abs_diff(&Dec::from(post_stake_10)),
4201+
exp_pipeline_stake
4202+
.abs_diff(Dec::try_from(post_stake_10).unwrap())
4203+
.unwrap(),
41954204
);
41964205

41974206
// Check the balance of the Slash Pool
@@ -4418,6 +4427,7 @@ mod test_finalize_block {
44184427
(self_details.unbonds[1].slashed_amount.unwrap().change()
44194428
- (self_unbond_2_amount - self_bond_1_amount)
44204429
.mul_ceil(rate)
4430+
.unwrap()
44214431
.change())
44224432
.abs()
44234433
<= Uint::from(1)
@@ -4438,7 +4448,7 @@ mod test_finalize_block {
44384448
.unwrap();
44394449

44404450
let exp_del_withdraw_slashed_amount =
4441-
del_unbond_1_amount.mul_ceil(slash_rate_3);
4451+
del_unbond_1_amount.mul_ceil(slash_rate_3).unwrap();
44424452
assert!(
44434453
(del_withdraw
44444454
- (del_unbond_1_amount - exp_del_withdraw_slashed_amount))

0 commit comments

Comments
 (0)