From ddb8453b85cca4b6e5ba615a1afb49630f7da5c0 Mon Sep 17 00:00:00 2001 From: jorgeantonio21 Date: Wed, 20 Jul 2022 14:20:32 +0100 Subject: [PATCH] fix: possible overflow in difficulty calculation (fixes #3923) companion (#4097) Description Quick fix to overflow problem in difficulty. This problem had already been settled for `big_endian_difficulty`. Motivation and Context In https://github.com/tari-project/tari/pull/4090, @CjS77 point it out that the `little_endian_difficulty` method had the same problem. This PR is an attempt to tackle it. How Has This Been Tested? Adapted tests from previous PR (https://github.com/tari-project/tari/pull/4090) --- .../core/src/proof_of_work/difficulty.rs | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/base_layer/core/src/proof_of_work/difficulty.rs b/base_layer/core/src/proof_of_work/difficulty.rs index aaaef91bc4..fcfc918a10 100644 --- a/base_layer/core/src/proof_of_work/difficulty.rs +++ b/base_layer/core/src/proof_of_work/difficulty.rs @@ -132,6 +132,7 @@ pub mod util { pub(crate) fn little_endian_difficulty(hash: &[u8]) -> Difficulty { let scalar = U256::from_little_endian(hash); // Little endian so the hash has trailing zeroes let result = U256::MAX / scalar; + let result = result.min(u64::MAX.into()); result.low_u64().into() } @@ -140,7 +141,7 @@ pub mod util { use super::*; #[test] - fn high_target() { + fn be_high_target() { let target: &[u8] = &[ 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -150,7 +151,7 @@ pub mod util { } #[test] - fn max_difficulty() { + fn be_max_difficulty() { let target = U256::MAX / U256::from(u64::MAX); let mut bytes = [0u8; 32]; target.to_big_endian(&mut bytes); @@ -158,11 +159,39 @@ pub mod util { } #[test] - fn stop_overflow() { + fn be_stop_overflow() { let target: u64 = 64; let expected = u64::MAX; assert_eq!(big_endian_difficulty(&target.to_be_bytes()), Difficulty::from(expected)); } + + #[test] + fn le_high_target() { + let target: &[u8] = &[ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + ]; + let expected = Difficulty::from(1); + assert_eq!(little_endian_difficulty(target), expected); + } + + #[test] + fn le_max_difficulty() { + let target = U256::MAX / U256::from(u64::MAX); + let mut bytes = [0u8; 32]; + target.to_little_endian(&mut bytes); + assert_eq!(little_endian_difficulty(&bytes), Difficulty::from(u64::MAX)); + } + + #[test] + fn le_stop_overflow() { + let target: u64 = 64; + let expected = u64::MAX; + assert_eq!( + little_endian_difficulty(&target.to_be_bytes()), + Difficulty::from(expected) + ); + } } }