Sdk: start to appease clippy's integer arithmetic check (#15736)

* Move to module-level clippy allowance

* Fix stake_weighted_timestamp math

* Fix genesis_config

* Fix shred_version

* Fix hard_forks

* Fix process_instruction

* Add ArithmeticOverflow ix error

* Fix nonce_keyed_account

* Update BankSlotDelta frozen abi due to new ix error
This commit is contained in:
Tyera Eulberg 2021-03-08 18:37:57 -07:00 committed by GitHub
parent cae8f61952
commit e3e8179f2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 41 additions and 18 deletions

View File

@ -111,7 +111,7 @@ impl ExecuteTimings {
} }
type BankStatusCache = StatusCache<Result<()>>; type BankStatusCache = StatusCache<Result<()>>;
#[frozen_abi(digest = "3ZaEt781qwhfQSE4DZPBHhng2S6MuimchRjkR9ZWzDFs")] #[frozen_abi(digest = "EcB9J7sm37t1R47vLcvGuNeiRciB4Efq1EDWDWL6Bp5h")]
pub type BankSlotDelta = SlotDelta<Result<()>>; pub type BankSlotDelta = SlotDelta<Result<()>>;
type TransactionAccountRefCells = Vec<Rc<RefCell<Account>>>; type TransactionAccountRefCells = Vec<Rc<RefCell<Account>>>;
type TransactionAccountDepRefCells = Vec<(Pubkey, RefCell<Account>)>; type TransactionAccountDepRefCells = Vec<(Pubkey, RefCell<Account>)>;

View File

@ -198,6 +198,9 @@ pub enum InstructionError {
#[error("Invalid account owner")] #[error("Invalid account owner")]
InvalidAccountOwner, InvalidAccountOwner,
#[error("Program arithmetic overflowed")]
ArithmeticOverflow,
} }
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]

View File

@ -218,7 +218,10 @@ impl GenesisConfig {
} }
pub fn ns_per_slot(&self) -> u128 { pub fn ns_per_slot(&self) -> u128 {
self.poh_config.target_tick_duration.as_nanos() * self.ticks_per_slot() as u128 self.poh_config
.target_tick_duration
.as_nanos()
.saturating_mul(self.ticks_per_slot() as u128)
} }
pub fn slots_per_year(&self) -> f64 { pub fn slots_per_year(&self) -> f64 {

View File

@ -18,7 +18,7 @@ impl HardForks {
.iter() .iter()
.position(|(slot, _)| *slot == new_slot) .position(|(slot, _)| *slot == new_slot)
{ {
self.hard_forks[i] = (new_slot, self.hard_forks[i].1 + 1); self.hard_forks[i] = (new_slot, self.hard_forks[i].1.saturating_add(1));
} else { } else {
self.hard_forks.push((new_slot, 1)); self.hard_forks.push((new_slot, 1));
} }

View File

@ -1,6 +1,5 @@
#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))] #![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))]
#![cfg_attr(RUSTC_NEEDS_PROC_MACRO_HYGIENE, feature(proc_macro_hygiene))] #![cfg_attr(RUSTC_NEEDS_PROC_MACRO_HYGIENE, feature(proc_macro_hygiene))]
#![allow(clippy::integer_arithmetic)]
// Allows macro expansion of `use ::solana_sdk::*` to work within this crate // Allows macro expansion of `use ::solana_sdk::*` to work within this crate
extern crate self as solana_sdk; extern crate self as solana_sdk;

View File

@ -153,8 +153,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
} }
self.try_account_ref_mut()?.lamports -= lamports; let nonce_balance = self.try_account_ref_mut()?.lamports;
to.try_account_ref_mut()?.lamports += lamports; self.try_account_ref_mut()?.lamports = nonce_balance
.checked_sub(lamports)
.ok_or(InstructionError::ArithmeticOverflow)?;
let to_balance = to.try_account_ref_mut()?.lamports;
to.try_account_ref_mut()?.lamports = to_balance
.checked_add(lamports)
.ok_or(InstructionError::ArithmeticOverflow)?;
Ok(()) Ok(())
} }

View File

@ -1,3 +1,4 @@
#![allow(clippy::integer_arithmetic)]
use crate::clock::DEFAULT_TICKS_PER_SECOND; use crate::clock::DEFAULT_TICKS_PER_SECOND;
use std::time::Duration; use std::time::Duration;

View File

@ -292,11 +292,11 @@ impl Default for MockInvokeContext {
} }
impl InvokeContext for MockInvokeContext { impl InvokeContext for MockInvokeContext {
fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> { fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
self.invoke_depth += 1; self.invoke_depth = self.invoke_depth.saturating_add(1);
Ok(()) Ok(())
} }
fn pop(&mut self) { fn pop(&mut self) {
self.invoke_depth -= 1; self.invoke_depth = self.invoke_depth.saturating_sub(1);
} }
fn invoke_depth(&self) -> usize { fn invoke_depth(&self) -> usize {
self.invoke_depth self.invoke_depth

View File

@ -1,3 +1,4 @@
#![allow(clippy::integer_arithmetic)]
#![cfg(feature = "full")] #![cfg(feature = "full")]
use crate::instruction::Instruction; use crate::instruction::Instruction;

View File

@ -15,6 +15,8 @@ pub fn version_from_hash(hash: &Hash) -> u16 {
.for_each(|(accum, seed)| *accum ^= *seed) .for_each(|(accum, seed)| *accum ^= *seed)
}); });
// convert accum into a u16 // convert accum into a u16
// Because accum[0] is a u8, 8bit left shift of the u16 can never overflow
#[allow(clippy::integer_arithmetic)]
let version = ((accum[0] as u16) << 8) | accum[1] as u16; let version = ((accum[0] as u16) << 8) | accum[1] as u16;
// ensure version is never zero, to avoid looking like an uninitialized version // ensure version is never zero, to avoid looking like an uninitialized version

View File

@ -40,29 +40,29 @@ where
V: Borrow<(Slot, UnixTimestamp)>, V: Borrow<(Slot, UnixTimestamp)>,
{ {
let mut stake_per_timestamp: BTreeMap<UnixTimestamp, u128> = BTreeMap::new(); let mut stake_per_timestamp: BTreeMap<UnixTimestamp, u128> = BTreeMap::new();
let mut total_stake = 0; let mut total_stake: u128 = 0;
for (vote_pubkey, slot_timestamp) in unique_timestamps { for (vote_pubkey, slot_timestamp) in unique_timestamps {
let (timestamp_slot, timestamp) = slot_timestamp.borrow(); let (timestamp_slot, timestamp) = slot_timestamp.borrow();
let offset = slot.saturating_sub(*timestamp_slot) as u32 * slot_duration; let offset = slot.saturating_sub(*timestamp_slot) as u32 * slot_duration;
let estimate = timestamp + offset.as_secs() as i64; let estimate = timestamp.saturating_add(offset.as_secs() as i64);
let stake = stakes let stake = stakes
.get(vote_pubkey.borrow()) .get(vote_pubkey.borrow())
.map(|(stake, _account)| stake) .map(|(stake, _account)| stake)
.unwrap_or(&0); .unwrap_or(&0);
stake_per_timestamp stake_per_timestamp
.entry(estimate) .entry(estimate)
.and_modify(|stake_sum| *stake_sum += *stake as u128) .and_modify(|stake_sum| *stake_sum = stake_sum.saturating_add(*stake as u128))
.or_insert(*stake as u128); .or_insert(*stake as u128);
total_stake += *stake as u128; total_stake = total_stake.saturating_add(*stake as u128);
} }
if total_stake == 0 { if total_stake == 0 {
return None; return None;
} }
let mut stake_accumulator = 0; let mut stake_accumulator: u128 = 0;
let mut estimate = 0; let mut estimate = 0;
// Populate `estimate` with stake-weighted median timestamp // Populate `estimate` with stake-weighted median timestamp
for (timestamp, stake) in stake_per_timestamp.into_iter() { for (timestamp, stake) in stake_per_timestamp.into_iter() {
stake_accumulator += stake; stake_accumulator = stake_accumulator.saturating_add(stake);
if stake_accumulator > total_stake / 2 { if stake_accumulator > total_stake / 2 {
estimate = timestamp; estimate = timestamp;
break; break;
@ -84,15 +84,16 @@ where
// estimate offset since the start of the epoch is higher than // estimate offset since the start of the epoch is higher than
// `MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW` // `MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW`
estimate = epoch_start_timestamp estimate = epoch_start_timestamp
+ poh_estimate_offset.as_secs() as i64 .saturating_add(poh_estimate_offset.as_secs() as i64)
+ max_allowable_drift_slow.as_secs() as i64; .saturating_add(max_allowable_drift_slow.as_secs() as i64);
} else if estimate_offset < poh_estimate_offset } else if estimate_offset < poh_estimate_offset
&& poh_estimate_offset - estimate_offset > max_allowable_drift_fast && poh_estimate_offset - estimate_offset > max_allowable_drift_fast
{ {
// estimate offset since the start of the epoch is lower than // estimate offset since the start of the epoch is lower than
// `MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST` // `MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST`
estimate = epoch_start_timestamp + poh_estimate_offset.as_secs() as i64 estimate = epoch_start_timestamp
- max_allowable_drift_fast.as_secs() as i64; .saturating_add(poh_estimate_offset.as_secs() as i64)
.saturating_sub(max_allowable_drift_fast.as_secs() as i64);
} }
} }
Some(estimate) Some(estimate)

View File

@ -1,3 +1,4 @@
#![allow(clippy::integer_arithmetic)]
//! The `timing` module provides std::time utility functions. //! The `timing` module provides std::time utility functions.
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};

View File

@ -117,4 +117,5 @@ pub enum InstructionErrorType {
BorshIoError = 44, BorshIoError = 44,
AccountNotRentExempt = 45, AccountNotRentExempt = 45,
InvalidAccountOwner = 46, InvalidAccountOwner = 46,
ArithmeticOverflow = 47,
} }

View File

@ -509,6 +509,7 @@ impl TryFrom<tx_by_addr::TransactionError> for TransactionError {
44 => InstructionError::BorshIoError(String::new()), 44 => InstructionError::BorshIoError(String::new()),
45 => InstructionError::AccountNotRentExempt, 45 => InstructionError::AccountNotRentExempt,
46 => InstructionError::InvalidAccountOwner, 46 => InstructionError::InvalidAccountOwner,
47 => InstructionError::ArithmeticOverflow,
_ => return Err("Invalid InstructionError"), _ => return Err("Invalid InstructionError"),
}; };
@ -735,6 +736,9 @@ impl From<TransactionError> for tx_by_addr::TransactionError {
InstructionError::InvalidAccountOwner => { InstructionError::InvalidAccountOwner => {
tx_by_addr::InstructionErrorType::InvalidAccountOwner tx_by_addr::InstructionErrorType::InvalidAccountOwner
} }
InstructionError::ArithmeticOverflow => {
tx_by_addr::InstructionErrorType::ArithmeticOverflow
}
} as i32, } as i32,
custom: match instruction_error { custom: match instruction_error {
InstructionError::Custom(custom) => { InstructionError::Custom(custom) => {

View File

@ -96,6 +96,7 @@ enum InstructionErrorType {
BORSH_IO_ERROR = 44; BORSH_IO_ERROR = 44;
ACCOUNT_NOT_RENT_EXEMPT = 45; ACCOUNT_NOT_RENT_EXEMPT = 45;
INVALID_ACCOUNT_OWNER = 46; INVALID_ACCOUNT_OWNER = 46;
ARITHMETIC_OVERFLOW = 47;
} }
message UnixTimestamp { message UnixTimestamp {