versionbits in progress

This commit is contained in:
debris 2017-04-27 15:58:16 +02:00
parent 5f7b42c80f
commit 95255d0f58
3 changed files with 74 additions and 17 deletions

29
db/src/block_iterator.rs Normal file
View File

@ -0,0 +1,29 @@
use chain::BlockHeader;
use {BlockRef, BlockHeaderProvider};
pub struct BlockIterator<'a> {
block: u32,
period: u32,
headers: &'a BlockHeaderProvider,
}
impl<'a> BlockIterator<'a> {
pub fn new(block: u32, period: u32, headers: &'a BlockHeaderProvider) -> Self {
BlockIterator {
block: block,
period: period,
headers: headers,
}
}
}
impl<'a> Iterator for BlockIterator<'a> {
type Item = (u32, BlockHeader);
fn next(&mut self) -> Option<Self::Item> {
let result = self.headers.block_header(BlockRef::Number(self.block));
let block = self.block;
self.block += self.period;
result.map(|header| (block, header))
}
}

View File

@ -13,13 +13,14 @@ extern crate chain;
pub mod kv; pub mod kv;
mod best_block; mod best_block;
mod block_ancestors; mod block_ancestors;
mod block_chain;
mod block_chain_db;
mod block_impls;
mod block_iterator;
mod block_origin; mod block_origin;
mod block_provider; mod block_provider;
mod block_ref; mod block_ref;
mod block_chain;
mod block_chain_db;
mod error; mod error;
mod block_impls;
mod store; mod store;
mod transaction_meta; mod transaction_meta;
mod transaction_provider; mod transaction_provider;
@ -28,11 +29,12 @@ pub use primitives::{hash, bytes};
pub use best_block::BestBlock; pub use best_block::BestBlock;
pub use block_ancestors::BlockAncestors; pub use block_ancestors::BlockAncestors;
pub use block_chain::{BlockChain, ForkChain, Forkable};
pub use block_chain_db::{BlockChainDatabase, ForkChainDatabase};
pub use block_iterator::BlockIterator;
pub use block_origin::{BlockOrigin, SideChainOrigin}; pub use block_origin::{BlockOrigin, SideChainOrigin};
pub use block_provider::{BlockHeaderProvider, BlockProvider, IndexedBlockProvider}; pub use block_provider::{BlockHeaderProvider, BlockProvider, IndexedBlockProvider};
pub use block_ref::BlockRef; pub use block_ref::BlockRef;
pub use block_chain::{BlockChain, ForkChain, Forkable};
pub use block_chain_db::{BlockChainDatabase, ForkChainDatabase};
pub use error::Error; pub use error::Error;
pub use store::{AsSubstore, Store, SharedStore, CanonStore}; pub use store::{AsSubstore, Store, SharedStore, CanonStore};
pub use transaction_meta::TransactionMeta; pub use transaction_meta::TransactionMeta;

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use network::Magic; use network::Magic;
use hash::H256; use hash::H256;
use chain::BlockHeader; use chain::BlockHeader;
use db::{BlockHeaderProvider, BlockProvider, BlockRef, BlockAncestors}; use db::{BlockHeaderProvider, BlockProvider, BlockRef, BlockAncestors, BlockIterator};
use timestamp::median_timestamp; use timestamp::median_timestamp;
const VERSIONBITS_TOP_MASK: u32 = 0xe0000000; const VERSIONBITS_TOP_MASK: u32 = 0xe0000000;
@ -17,23 +17,35 @@ pub enum ThresholdState {
Failed, Failed,
} }
impl Default for ThresholdState {
fn default() -> Self {
ThresholdState::Defined
}
}
pub struct ThresholdConditionCache { pub struct ThresholdConditionCache {
map: HashMap<&'static str, HashMap<u32, ThresholdState>>, map: HashMap<&'static str, HashMap<u32, ThresholdState>>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Condition { pub struct Condition {
/// Deployment's name
pub name: &'static str, pub name: &'static str,
/// Bit
pub bit: u8, pub bit: u8,
/// Start time
pub start_time: u32, pub start_time: u32,
/// Timeout
pub timeout: u32, pub timeout: u32,
/// Activation block number (if already activated)
pub activation: Option<u32>,
} }
impl Condition { impl Condition {
pub fn csv(network: Magic) -> Option<Self> { pub fn csv(network: Magic) -> Option<Self> {
let (start_time, timeout) = match network { let (start_time, timeout, activation) = match network {
Magic::Mainnet => (1462060800, 1493596800), Magic::Mainnet => (1462060800, 1493596800, Some(770112)),
Magic::Testnet => (1456790400, 1493596800), Magic::Testnet => (1456790400, 1493596800, Some(419328)),
_ => { return None } _ => { return None }
}; };
@ -42,15 +54,16 @@ impl Condition {
bit: 0, bit: 0,
start_time: start_time, start_time: start_time,
timeout: timeout, timeout: timeout,
activation: activation,
}; };
Some(condition) Some(condition)
} }
pub fn segwit(network: Magic) -> Option<Self> { pub fn segwit(network: Magic) -> Option<Self> {
let (start_time, timeout) = match network { let (start_time, timeout, activation) = match network {
Magic::Mainnet => (1479168000, 1510704000), Magic::Mainnet => (1479168000, 1510704000, None),
Magic::Testnet => (1462060800, 1493596800), Magic::Testnet => (1462060800, 1493596800, Some(834624)),
_ => { return None }, _ => { return None },
}; };
@ -59,6 +72,7 @@ impl Condition {
bit: 1, bit: 1,
start_time: start_time, start_time: start_time,
timeout: timeout, timeout: timeout,
activation: activation,
}; };
Some(condition) Some(condition)
@ -69,12 +83,17 @@ impl Condition {
} }
} }
pub fn threshold_state(cache: &mut ThresholdConditionCache, condition: Condition, block: &H256, headers: &BlockProvider) -> ThresholdState { pub fn threshold_state(cache: &mut ThresholdConditionCache, condition: Condition, number: u32, headers: &BlockHeaderProvider, network: Magic) -> ThresholdState {
if let Some(activation) = condition.activation {
if activation <= number {
return ThresholdState::Active;
}
}
// A block's state is always the same as that of the first of its period, so it is computed based on a // A block's state is always the same as that of the first of its period, so it is computed based on a
// pindexPrev whose height equals a multiple of nPeriod - 1. // pindexPrev whose height equals a multiple of nPeriod - 1.
// get number of the first block in the period // get number of the first block in the period
let number = 0; let number = first_of_the_period(number);
{ {
let condition_cache = cache.map.get(condition.name).expect("condition cache expected to be known"); let condition_cache = cache.map.get(condition.name).expect("condition cache expected to be known");
@ -83,7 +102,13 @@ pub fn threshold_state(cache: &mut ThresholdConditionCache, condition: Condition
} }
} }
unimplemented!(); // TODO: get proper start number
let (block_number, state) = ThresholdConditionIterator::new(condition, headers, number, network)
.last()
.unwrap_or_else(|| (number, ThresholdState::default()));
state
} }
fn first_of_the_period(block: u32) -> u32 { fn first_of_the_period(block: u32) -> u32 {
@ -118,7 +143,7 @@ impl<'a> ThresholdConditionIterator<'a> {
} }
impl<'a> Iterator for ThresholdConditionIterator<'a> { impl<'a> Iterator for ThresholdConditionIterator<'a> {
type Item = ThresholdState; type Item = (u32, ThresholdState);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let header = match self.blocks.block_header(BlockRef::Number(self.to_check)) { let header = match self.blocks.block_header(BlockRef::Number(self.to_check)) {
@ -155,7 +180,8 @@ impl<'a> Iterator for ThresholdConditionIterator<'a> {
} }
} }
let block_number = self.to_check;
self.to_check += 2016; self.to_check += 2016;
Some(self.last_state) Some((block_number, self.last_state))
} }
} }