utils mod
This commit is contained in:
parent
903d2b8878
commit
567facbe29
|
@ -6,7 +6,7 @@ use db::{self, BlockRef};
|
||||||
use chain;
|
use chain;
|
||||||
use super::{Verify, VerificationResult, Chain, Error};
|
use super::{Verify, VerificationResult, Chain, Error};
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use byteorder::{LittleEndian, BigEndian, ByteOrder};
|
use utils;
|
||||||
|
|
||||||
const BLOCK_MAX_FUTURE: i64 = 2 * 60 * 60; // 2 hours
|
const BLOCK_MAX_FUTURE: i64 = 2 * 60 * 60; // 2 hours
|
||||||
|
|
||||||
|
@ -20,47 +20,6 @@ impl ChainVerifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_nbits(hash: &H256, n_bits: u32) -> bool {
|
|
||||||
let hash_bytes: &[u8] = &**hash;
|
|
||||||
|
|
||||||
let mut nb = [0u8; 4];
|
|
||||||
BigEndian::write_u32(&mut nb, n_bits);
|
|
||||||
let shift = (nb[0] - 3) as usize; // total shift for mantissa
|
|
||||||
|
|
||||||
if shift >= 30 { return false; } // invalid shift
|
|
||||||
|
|
||||||
let should_be_zero = shift + 3..32;
|
|
||||||
let should_be_le = shift..shift + 3;
|
|
||||||
|
|
||||||
for z_check in should_be_zero {
|
|
||||||
if hash_bytes[z_check as usize] != 0 { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// making u32 from 3 bytes
|
|
||||||
let mut order = 0;
|
|
||||||
let hash_val: u32 = hash_bytes[should_be_le].iter().fold(0u32, |s, a| { let r = s + ((*a as u32) << order); order = order + 8; r });
|
|
||||||
|
|
||||||
// using 3 bytes leftover of nbits
|
|
||||||
nb[0] = 0;
|
|
||||||
let threshold = BigEndian::read_u32(&nb);
|
|
||||||
if hash_val < threshold {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if hash_val > threshold {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the case when hash effective bits are equal to nbits
|
|
||||||
// then the rest of the hash must be zero
|
|
||||||
for byte in hash_bytes[0..shift].iter() { if *byte != 0 { return false; } }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn age(protocol_time: u32) -> i64 {
|
|
||||||
::time::get_time().sec - protocol_time as i64
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Verify for ChainVerifier {
|
impl Verify for ChainVerifier {
|
||||||
fn verify(&self, block: &chain::Block) -> VerificationResult {
|
fn verify(&self, block: &chain::Block) -> VerificationResult {
|
||||||
let hash = block.hash();
|
let hash = block.hash();
|
||||||
|
@ -71,12 +30,12 @@ impl Verify for ChainVerifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
// target difficulty threshold
|
// target difficulty threshold
|
||||||
if !check_nbits(&hash, block.header().nbits) {
|
if !utils::check_nbits(&hash, block.header().nbits) {
|
||||||
return Err(Error::Pow);
|
return Err(Error::Pow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if block timestamp is not far in the future
|
// check if block timestamp is not far in the future
|
||||||
if age(block.header().time) < -BLOCK_MAX_FUTURE {
|
if utils::age(block.header().time) < -BLOCK_MAX_FUTURE {
|
||||||
return Err(Error::Timestamp);
|
return Err(Error::Timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +56,7 @@ impl Verify for ChainVerifier {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::{check_nbits, ChainVerifier};
|
use super::ChainVerifier;
|
||||||
use super::super::{Verify, Chain};
|
use super::super::{Verify, Chain};
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use chain;
|
use chain;
|
||||||
|
@ -196,32 +155,4 @@ mod tests {
|
||||||
assert_eq!(Chain::Main, verifier.verify(&b1).unwrap());
|
assert_eq!(Chain::Main, verifier.verify(&b1).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn nbits() {
|
|
||||||
// strictly equal
|
|
||||||
let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000000");
|
|
||||||
let nbits = 0x181bc330u32;
|
|
||||||
assert!(check_nbits(&hash, nbits));
|
|
||||||
|
|
||||||
// nbits match but not equal (greater)
|
|
||||||
let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000001");
|
|
||||||
let nbits = 0x181bc330u32;
|
|
||||||
assert!(!check_nbits(&hash, nbits));
|
|
||||||
|
|
||||||
// greater
|
|
||||||
let hash = H256::from_reversed_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
||||||
let nbits = 0x181bc330u32;
|
|
||||||
assert!(!check_nbits(&hash, nbits));
|
|
||||||
|
|
||||||
|
|
||||||
// some real examples
|
|
||||||
let hash = H256::from_reversed_str("000000000000000001f942eb4bfa0aeccb6a14c268f4c72d5fff17270da771b9");
|
|
||||||
let nbits = 404129525;
|
|
||||||
assert!(check_nbits(&hash, nbits));
|
|
||||||
|
|
||||||
// some real examples
|
|
||||||
let hash = H256::from_reversed_str("00000000000000000e753ef636075711efd2cbf5a8473c7c5b67755a3701e0c2");
|
|
||||||
let nbits = 404129525;
|
|
||||||
assert!(check_nbits(&hash, nbits));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ extern crate ethcore_devtools as devtools;
|
||||||
extern crate test_data;
|
extern crate test_data;
|
||||||
|
|
||||||
mod queue;
|
mod queue;
|
||||||
|
mod utils;
|
||||||
mod chain_verifier;
|
mod chain_verifier;
|
||||||
|
|
||||||
pub use queue::Queue;
|
pub use queue::Queue;
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
//! Verification utilities
|
||||||
|
use primitives::hash::H256;
|
||||||
|
use byteorder::{LittleEndian, BigEndian, ByteOrder};
|
||||||
|
|
||||||
|
pub fn check_nbits(hash: &H256, n_bits: u32) -> bool {
|
||||||
|
let hash_bytes: &[u8] = &**hash;
|
||||||
|
|
||||||
|
let mut nb = [0u8; 4];
|
||||||
|
BigEndian::write_u32(&mut nb, n_bits);
|
||||||
|
let shift = (nb[0] - 3) as usize; // total shift for mantissa
|
||||||
|
|
||||||
|
if shift >= 30 { return false; } // invalid shift
|
||||||
|
|
||||||
|
let should_be_zero = shift + 3..32;
|
||||||
|
let should_be_le = shift..shift + 3;
|
||||||
|
|
||||||
|
for z_check in should_be_zero {
|
||||||
|
if hash_bytes[z_check as usize] != 0 { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// making u32 from 3 bytes
|
||||||
|
let mut order = 0;
|
||||||
|
let hash_val: u32 = hash_bytes[should_be_le].iter().fold(0u32, |s, a| { let r = s + ((*a as u32) << order); order = order + 8; r });
|
||||||
|
|
||||||
|
// using 3 bytes leftover of nbits
|
||||||
|
nb[0] = 0;
|
||||||
|
let threshold = BigEndian::read_u32(&nb);
|
||||||
|
if hash_val < threshold {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if hash_val > threshold {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the case when hash effective bits are equal to nbits
|
||||||
|
// then the rest of the hash must be zero
|
||||||
|
for byte in hash_bytes[0..shift].iter() { if *byte != 0 { return false; } }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn age(protocol_time: u32) -> i64 {
|
||||||
|
::time::get_time().sec - protocol_time as i64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::check_nbits;
|
||||||
|
use primitives::hash::H256;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nbits() {
|
||||||
|
// strictly equal
|
||||||
|
let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000000");
|
||||||
|
let nbits = 0x181bc330u32;
|
||||||
|
assert!(check_nbits(&hash, nbits));
|
||||||
|
|
||||||
|
// nbits match but not equal (greater)
|
||||||
|
let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000001");
|
||||||
|
let nbits = 0x181bc330u32;
|
||||||
|
assert!(!check_nbits(&hash, nbits));
|
||||||
|
|
||||||
|
// greater
|
||||||
|
let hash = H256::from_reversed_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||||
|
let nbits = 0x181bc330u32;
|
||||||
|
assert!(!check_nbits(&hash, nbits));
|
||||||
|
|
||||||
|
|
||||||
|
// some real examples
|
||||||
|
let hash = H256::from_reversed_str("000000000000000001f942eb4bfa0aeccb6a14c268f4c72d5fff17270da771b9");
|
||||||
|
let nbits = 404129525;
|
||||||
|
assert!(check_nbits(&hash, nbits));
|
||||||
|
|
||||||
|
let hash = H256::from_reversed_str("00000000000000000e753ef636075711efd2cbf5a8473c7c5b67755a3701e0c2");
|
||||||
|
let nbits = 404129525;
|
||||||
|
assert!(check_nbits(&hash, nbits));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue