Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit b96c802

Browse files
committed
ethcore: fix pow difficulty validation
1 parent e2095d4 commit b96c802

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

ethcore/src/ethereum/ethash.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::sync::Arc;
2121
use hash::{KECCAK_EMPTY_LIST_RLP};
2222
use engines::block_reward::{self, RewardKind};
2323
use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
24-
use ethereum_types::{H256, H64, U256, Address};
24+
use ethereum_types::{H256, H64, U512, U256, Address};
2525
use unexpected::{OutOfBounds, Mismatch};
2626
use block::*;
2727
use error::{BlockError, Error};
@@ -450,11 +450,12 @@ impl Ethash {
450450

451451
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
452452
pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
453-
let d = U256::from(*boundary);
454-
if d <= U256::one() {
453+
let d = U512::from(&**boundary);
454+
if d <= U512::one() {
455455
U256::max_value()
456456
} else {
457-
((U256::one() << 255) / d) << 1
457+
// d > 1, so result should never overflow 256 bits
458+
U256::from((U512::one() << 256) / d)
458459
}
459460
}
460461

@@ -463,7 +464,9 @@ impl Ethash {
463464
if *difficulty <= U256::one() {
464465
U256::max_value().into()
465466
} else {
466-
(((U256::one() << 255) / *difficulty) << 1).into()
467+
let d = U512::from(difficulty);
468+
// d > 1, so result should never overflow 256 bits
469+
U256::from((U512::one() << 256) / d).into()
467470
}
468471
}
469472
}
@@ -776,6 +779,17 @@ mod tests {
776779
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
777780
}
778781

782+
#[test]
783+
fn test_difficulty_to_boundary_regression() {
784+
// the last bit was originally being truncated when performing the conversion
785+
for difficulty in 1..9 {
786+
assert_eq!(U256::from(difficulty), Ethash::boundary_to_difficulty(&Ethash::difficulty_to_boundary(&difficulty.into())));
787+
assert_eq!(H256::from(difficulty), Ethash::difficulty_to_boundary(&Ethash::boundary_to_difficulty(&difficulty.into())));
788+
assert_eq!(U256::from(difficulty), Ethash::boundary_to_difficulty(&Ethash::boundary_to_difficulty(&difficulty.into()).into()));
789+
assert_eq!(H256::from(difficulty), Ethash::difficulty_to_boundary(&Ethash::difficulty_to_boundary(&difficulty.into()).into()));
790+
}
791+
}
792+
779793
#[test]
780794
fn difficulty_frontier() {
781795
let machine = new_homestead_test_machine();

miner/src/work_notify.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use self::ethash::SeedHashCompute;
2828
use self::url::Url;
2929
use self::hyper::header::ContentType;
3030

31-
use ethereum_types::{H256, U256};
31+
use ethereum_types::{H256, U256, U512};
3232
use parking_lot::Mutex;
3333
use futures::Future;
3434

@@ -72,7 +72,9 @@ fn difficulty_to_boundary(difficulty: &U256) -> H256 {
7272
if *difficulty <= U256::one() {
7373
U256::max_value().into()
7474
} else {
75-
(((U256::one() << 255) / *difficulty) << 1).into()
75+
let d = U512::from(difficulty);
76+
// d > 1, so result should never overflow 256 bits
77+
U256::from((U512::one() << 256) / d).into()
7678
}
7779
}
7880

0 commit comments

Comments
 (0)