median time verfication might be unordered?
This commit is contained in:
parent
9f4469e480
commit
a4de321cc7
|
@ -1,6 +1,5 @@
|
||||||
//! Bitcoin chain verifier
|
//! Bitcoin chain verifier
|
||||||
|
|
||||||
use std::cmp;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use db::{self, BlockRef, BlockLocation};
|
use db::{self, BlockRef, BlockLocation};
|
||||||
use super::{Verify, VerificationResult, Chain, Error, TransactionError, ContinueVerify};
|
use super::{Verify, VerificationResult, Chain, Error, TransactionError, ContinueVerify};
|
||||||
|
@ -64,13 +63,6 @@ impl ChainVerifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(median_timestamp) = self.ordered_median_timestamp(block, at_height) {
|
|
||||||
if median_timestamp > block.block_header.time {
|
|
||||||
trace!(target: "verification", "median timestamp verification failed, median: {}, current: {}", median_timestamp, block.block_header.time);
|
|
||||||
return Err(Error::Timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let coinbase_spends = block.transactions()[0].total_spends();
|
let coinbase_spends = block.transactions()[0].total_spends();
|
||||||
|
|
||||||
let mut total_unspent = 0u64;
|
let mut total_unspent = 0u64;
|
||||||
|
@ -219,6 +211,13 @@ impl ChainVerifier {
|
||||||
return Err(Error::Timestamp);
|
return Err(Error::Timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(median_timestamp) = self.median_timestamp(block) {
|
||||||
|
if median_timestamp > block.block_header.time {
|
||||||
|
trace!(target: "verification", "median timestamp verification failed, median: {}, current: {}", median_timestamp, block.block_header.time);
|
||||||
|
return Err(Error::Timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// todo: serialized_size function is at least suboptimal
|
// todo: serialized_size function is at least suboptimal
|
||||||
let size = ::serialization::Serializable::serialized_size(block);
|
let size = ::serialization::Serializable::serialized_size(block);
|
||||||
if size > MAX_BLOCK_SIZE {
|
if size > MAX_BLOCK_SIZE {
|
||||||
|
@ -275,25 +274,26 @@ impl ChainVerifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ordered_median_timestamp(&self, block: &chain::Block, height: u32) -> Option<u32> {
|
fn median_timestamp(&self, block: &chain::Block) -> Option<u32> {
|
||||||
if height == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make 11 a const
|
// TODO: make 11 a const
|
||||||
let max = cmp::min(height, 11);
|
|
||||||
let mut timestamps = HashSet::new();
|
let mut timestamps = HashSet::new();
|
||||||
let mut block_ref = block.block_header.previous_header_hash.clone().into();
|
let mut block_ref = block.block_header.previous_header_hash.clone().into();
|
||||||
// TODO: optimize it, so it does not make 11 redundant queries each time
|
// TODO: optimize it, so it does not make 11 redundant queries each time
|
||||||
for _ in 0..max {
|
for _ in 0..10 {
|
||||||
let previous_header = self.store.block_header(block_ref).expect("block_ref < height; qed");
|
let previous_header = match self.store.block_header(block_ref) {
|
||||||
|
Some(h) => h,
|
||||||
|
None => { break; }
|
||||||
|
};
|
||||||
timestamps.insert(previous_header.time);
|
timestamps.insert(previous_header.time);
|
||||||
block_ref = previous_header.previous_header_hash.into();
|
block_ref = previous_header.previous_header_hash.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if timestamps.len() > 2 {
|
||||||
let timestamps: Vec<_> = timestamps.into_iter().collect();
|
let timestamps: Vec<_> = timestamps.into_iter().collect();
|
||||||
Some(timestamps[timestamps.len() / 2])
|
Some(timestamps[timestamps.len() / 2])
|
||||||
}
|
}
|
||||||
|
else { None }
|
||||||
|
}
|
||||||
|
|
||||||
fn work_required(&self, height: u32) -> Option<u32> {
|
fn work_required(&self, height: u32) -> Option<u32> {
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
|
|
Loading…
Reference in New Issue