From 79017e2b8d3d887c5e41c39b623b59d3b830f25f Mon Sep 17 00:00:00 2001 From: Aleksandr Logunov Date: Tue, 2 Apr 2024 00:50:04 +0400 Subject: [PATCH] fix: u512 on reward computation (#10909) Fix overflow found at https://near.zulipchat.com/#narrow/stream/422293-core.2Fstake-wars-iv/topic/StatelessNet.20v84.20issue/near/430321806. It happened with values ``` epoch_validator_reward = 1303530277894885217220048460336356 uptime_numer = 5149480000 stake = 19417599724822422137067484572677335 ``` and `log2(epoch_validator_reward * uptime_numer * stake) is ~= 256.17`, so it couldn't fit in `U256`. However, it can fit in U512, because epoch_validator_reward and stake are Balances = u128; uptime_numer fits in u64. Note that final conversion to u128 is valid because uptime_numer/uptime_denom and stake/total_stake are <= 1. Co-authored-by: Longarithm --- chain/epoch-manager/src/reward_calculator.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chain/epoch-manager/src/reward_calculator.rs b/chain/epoch-manager/src/reward_calculator.rs index 804592ccc03..865e8bb8bea 100644 --- a/chain/epoch-manager/src/reward_calculator.rs +++ b/chain/epoch-manager/src/reward_calculator.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use num_rational::Rational32; -use primitive_types::U256; +use primitive_types::{U256, U512}; use near_chain_configs::GenesisConfig; use near_primitives::checked_feature; @@ -138,9 +138,9 @@ impl RewardCalculator { // Apply min between 1. and computed uptime. uptime_numer = if uptime_numer > uptime_denum { uptime_denum } else { uptime_numer }; - (U256::from(epoch_validator_reward) * uptime_numer * U256::from(stake) - / uptime_denum - / U256::from(total_stake)) + (U512::from(epoch_validator_reward) * U512::from(uptime_numer) * U512::from(stake) + / U512::from(uptime_denum) + / U512::from(total_stake)) .as_u128() }; res.insert(account_id, reward);