monolith_height -> monolith_time (until block# is known)

This commit is contained in:
Svyatoslav Nikolsky 2018-04-26 10:49:03 +03:00
parent 9910fce3e2
commit 70b08a7ca0
8 changed files with 48 additions and 23 deletions

View File

@ -38,9 +38,9 @@ pub struct BitcoinCashConsensusParams {
/// Height of difficulty adjustment hardfork.
/// https://reviews.bitcoinabc.org/D601
pub difficulty_adjustion_height: u32,
/// Height of monolith (aka May 2018) hardfork.
/// Time of monolith (aka May 2018) hardfork.
/// https://github.com/bitcoincashorg/spec/blob/4fbb0face661e293bcfafe1a2a4744dcca62e50d/may-2018-hardfork.md
pub monolith_height: u32,
pub monolith_time: u32,
}
#[derive(Debug, Clone)]
@ -191,9 +191,9 @@ impl ConsensusFork {
}
}
pub fn max_block_size(&self, height: u32) -> usize {
pub fn max_block_size(&self, height: u32, median_time_past: u32) -> usize {
match *self {
ConsensusFork::BitcoinCash(ref fork) if height >= fork.monolith_height => 32_000_000,
ConsensusFork::BitcoinCash(ref fork) if median_time_past >= fork.monolith_time => 32_000_000,
ConsensusFork::BitcoinCash(ref fork) if height >= fork.height => 8_000_000,
ConsensusFork::NoFork | ConsensusFork::BitcoinCash(_) => 1_000_000,
}
@ -233,17 +233,17 @@ impl BitcoinCashConsensusParams {
Network::Mainnet | Network::Other(_) => BitcoinCashConsensusParams {
height: 478559,
difficulty_adjustion_height: 504031,
monolith_height: ::std::u32::MAX, // TODO: change me + tests
monolith_time: 1526400000,
},
Network::Testnet => BitcoinCashConsensusParams {
height: 1155876,
difficulty_adjustion_height: 1188697,
monolith_height: ::std::u32::MAX, // TODO: change me
monolith_time: 1526400000,
},
Network::Regtest | Network::Unitest => BitcoinCashConsensusParams {
height: 0,
difficulty_adjustion_height: 0,
monolith_height: ::std::u32::MAX, // TODO: change me
monolith_time: 1526400000,
},
}
}

View File

@ -12,6 +12,7 @@ use synchronization_server::{Server, ServerTask};
use synchronization_verifier::{TransactionVerificationSink};
use primitives::hash::H256;
use miner::BlockTemplate;
use verification::median_timestamp_inclusive;
use synchronization_peers::{TransactionAnnouncementType, BlockAnnouncementType};
use types::{PeerIndex, RequestId, StorageRef, MemoryPoolRef, PeersRef, ExecutorRef,
ClientRef, ServerRef, SynchronizationStateRef, SyncListenerRef};
@ -275,11 +276,14 @@ impl<T, U, V> LocalNode<T, U, V> where T: TaskExecutor, U: Server, V: Client {
/// Get block template for mining
pub fn get_block_template(&self) -> BlockTemplate {
let height = self.storage.best_block().number;
let max_block_size = self.consensus.fork.max_block_size(height);
let previous_block_height = self.storage.best_block().number;
let previous_block_header = self.storage.block_header(previous_block_height.into()).expect("best block is in db; qed");
let median_timestamp = median_timestamp_inclusive(previous_block_header.hash(), self.storage.as_block_header_provider());
let new_block_height = previous_block_height + 1;
let max_block_size = self.consensus.fork.max_block_size(new_block_height, median_timestamp);
let block_assembler = BlockAssembler {
max_block_size: max_block_size as u32,
max_block_sigops: self.consensus.fork.max_block_sigops(height, max_block_size) as u32,
max_block_sigops: self.consensus.fork.max_block_sigops(new_block_height, max_block_size) as u32,
};
let memory_pool = &*self.memory_pool.read();
block_assembler.create_new_block(&self.storage, memory_pool, time::get_time().sec as u32, &self.consensus)

View File

@ -27,12 +27,13 @@ impl<'a> BlockAcceptor<'a> {
consensus: &'a ConsensusParams,
block: CanonBlock<'a>,
height: u32,
median_time_past: u32,
deployments: &'a BlockDeployments<'a>,
headers: &'a BlockHeaderProvider,
) -> Self {
BlockAcceptor {
finality: BlockFinality::new(block, height, deployments, headers),
serialized_size: BlockSerializedSize::new(block, consensus, deployments, height),
serialized_size: BlockSerializedSize::new(block, consensus, deployments, height, median_time_past),
coinbase_script: BlockCoinbaseScript::new(block, consensus, height),
coinbase_claim: BlockCoinbaseClaim::new(block, store, height),
sigops: BlockSigops::new(block, store, consensus, height),
@ -89,17 +90,19 @@ pub struct BlockSerializedSize<'a> {
block: CanonBlock<'a>,
consensus: &'a ConsensusParams,
height: u32,
median_time_past: u32,
segwit_active: bool,
}
impl<'a> BlockSerializedSize<'a> {
fn new(block: CanonBlock<'a>, consensus: &'a ConsensusParams, deployments: &'a BlockDeployments<'a>, height: u32) -> Self {
fn new(block: CanonBlock<'a>, consensus: &'a ConsensusParams, deployments: &'a BlockDeployments<'a>, height: u32, median_time_past: u32) -> Self {
let segwit_active = deployments.segwit();
BlockSerializedSize {
block: block,
consensus: consensus,
height: height,
median_time_past: median_time_past,
segwit_active: segwit_active,
}
}
@ -112,7 +115,7 @@ impl<'a> BlockSerializedSize<'a> {
// after SegWit: without witness data, block size should be <= 1_000_000
// after BitcoinCash fork: block size is increased to 8_000_000
if size < self.consensus.fork.min_block_size(self.height) ||
size > self.consensus.fork.max_block_size(self.height) {
size > self.consensus.fork.max_block_size(self.height, self.median_time_past) {
return Err(Error::Size(size));
}

View File

@ -17,13 +17,13 @@ pub struct ChainAcceptor<'a> {
}
impl<'a> ChainAcceptor<'a> {
pub fn new(store: &'a Store, consensus: &'a ConsensusParams, verification_level: VerificationLevel, block: CanonBlock<'a>, height: u32, deployments: &'a BlockDeployments) -> Self {
pub fn new(store: &'a Store, consensus: &'a ConsensusParams, verification_level: VerificationLevel, block: CanonBlock<'a>, height: u32, median_time_past: u32, deployments: &'a BlockDeployments) -> Self {
trace!(target: "verification", "Block verification {}", block.hash().to_reversed_str());
let output_store = DuplexTransactionOutputProvider::new(store.as_transaction_output_provider(), block.raw());
let headers = store.as_block_header_provider();
ChainAcceptor {
block: BlockAcceptor::new(store.as_transaction_output_provider(), consensus, block, height, deployments, headers),
block: BlockAcceptor::new(store.as_transaction_output_provider(), consensus, block, height, median_time_past, deployments, headers),
header: HeaderAcceptor::new(headers, consensus, block.header(), height, deployments),
transactions: block.transactions()
.into_iter()
@ -37,6 +37,7 @@ impl<'a> ChainAcceptor<'a> {
block.hash(),
height,
block.header.raw.time,
median_time_past,
tx_index,
deployments,
))

View File

@ -36,6 +36,7 @@ impl<'a> TransactionAcceptor<'a> {
block_hash: &'a H256,
height: u32,
time: u32,
median_time_past: u32,
transaction_index: usize,
deployments: &'a BlockDeployments<'a>,
) -> Self {
@ -48,7 +49,7 @@ impl<'a> TransactionAcceptor<'a> {
overspent: TransactionOverspent::new(transaction, output_store),
double_spent: TransactionDoubleSpend::new(transaction, output_store),
return_replay_protection: TransactionReturnReplayProtection::new(transaction, consensus, height),
eval: TransactionEval::new(transaction, output_store, consensus, verification_level, height, time, deployments),
eval: TransactionEval::new(transaction, output_store, consensus, verification_level, height, time, median_time_past, deployments),
}
}
@ -85,11 +86,12 @@ impl<'a> MemoryPoolTransactionAcceptor<'a> {
transaction: CanonTransaction<'a>,
height: u32,
time: u32,
median_time_past: u32,
deployments: &'a BlockDeployments<'a>,
) -> Self {
trace!(target: "verification", "Mempool-Tx verification {}", transaction.hash.to_reversed_str());
let transaction_index = 0;
let max_block_sigops = consensus.fork.max_block_sigops(height, consensus.fork.max_block_size(height));
let max_block_sigops = consensus.fork.max_block_sigops(height, consensus.fork.max_block_size(height, median_time_past));
MemoryPoolTransactionAcceptor {
missing_inputs: TransactionMissingInputs::new(transaction, output_store, transaction_index),
maturity: TransactionMaturity::new(transaction, meta_store, height),
@ -97,7 +99,7 @@ impl<'a> MemoryPoolTransactionAcceptor<'a> {
sigops: TransactionSigops::new(transaction, output_store, consensus, max_block_sigops, time),
double_spent: TransactionDoubleSpend::new(transaction, output_store),
return_replay_protection: TransactionReturnReplayProtection::new(transaction, consensus, height),
eval: TransactionEval::new(transaction, output_store, consensus, VerificationLevel::Full, height, time, deployments),
eval: TransactionEval::new(transaction, output_store, consensus, VerificationLevel::Full, height, time, median_time_past, deployments),
}
}
@ -303,6 +305,7 @@ impl<'a> TransactionEval<'a> {
verification_level: VerificationLevel,
height: u32,
time: u32,
median_timestamp: u32,
deployments: &'a BlockDeployments,
) -> Self {
let verify_p2sh = time >= params.bip16_time;
@ -313,7 +316,7 @@ impl<'a> TransactionEval<'a> {
let verify_locktime = height >= params.bip65_height;
let verify_dersig = height >= params.bip66_height;
let verify_monolith_opcodes = match params.fork {
ConsensusFork::BitcoinCash(ref fork) if height >= fork.monolith_height => true,
ConsensusFork::BitcoinCash(ref fork) if median_timestamp >= fork.monolith_time => true,
_ => false,
};
let signature_version = match params.fork {

View File

@ -13,6 +13,7 @@ use verify_transaction::MemoryPoolTransactionVerifier;
use accept_chain::ChainAcceptor;
use accept_transaction::MemoryPoolTransactionAcceptor;
use deployments::{Deployments, BlockDeployments};
use timestamp::median_timestamp_inclusive;
use {Verify, VerificationLevel};
pub struct BackwardsCompatibleChainVerifier {
@ -43,6 +44,8 @@ impl BackwardsCompatibleChainVerifier {
assert_eq!(Some(self.store.best_block().hash), self.store.block_hash(self.store.best_block().number));
let block_origin = self.store.block_origin(&block.header)?;
trace!(target: "verification", "verify_block: {:?} best_block: {:?} block_origin: {:?}", block.hash().reversed(), self.store.best_block(), block_origin);
let median_time_past = median_timestamp_inclusive(block.header.raw.previous_header_hash.clone(), self.store.as_block_header_provider());
match block_origin {
BlockOrigin::KnownBlock => {
// there should be no known blocks at this point
@ -52,7 +55,8 @@ impl BackwardsCompatibleChainVerifier {
let header_provider = self.store.as_store().as_block_header_provider();
let deployments = BlockDeployments::new(&self.deployments, block_number, header_provider, &self.consensus);
let canon_block = CanonBlock::new(block);
let chain_acceptor = ChainAcceptor::new(self.store.as_store(), &self.consensus, verification_level, canon_block, block_number, &deployments);
let chain_acceptor = ChainAcceptor::new(self.store.as_store(), &self.consensus, verification_level,
canon_block, block_number, median_time_past, &deployments);
chain_acceptor.check()?;
},
BlockOrigin::SideChain(origin) => {
@ -61,7 +65,8 @@ impl BackwardsCompatibleChainVerifier {
let deployments = BlockDeployments::new(&self.deployments, block_number, header_provider, &self.consensus);
let fork = self.store.fork(origin)?;
let canon_block = CanonBlock::new(block);
let chain_acceptor = ChainAcceptor::new(fork.store(), &self.consensus, verification_level, canon_block, block_number, &deployments);
let chain_acceptor = ChainAcceptor::new(fork.store(), &self.consensus, verification_level, canon_block,
block_number, median_time_past, &deployments);
chain_acceptor.check()?;
},
BlockOrigin::SideChainBecomingCanonChain(origin) => {
@ -70,7 +75,8 @@ impl BackwardsCompatibleChainVerifier {
let deployments = BlockDeployments::new(&self.deployments, block_number, header_provider, &self.consensus);
let fork = self.store.fork(origin)?;
let canon_block = CanonBlock::new(block);
let chain_acceptor = ChainAcceptor::new(fork.store(), &self.consensus, verification_level, canon_block, block_number, &deployments);
let chain_acceptor = ChainAcceptor::new(fork.store(), &self.consensus, verification_level, canon_block,
block_number, median_time_past, &deployments);
chain_acceptor.check()?;
},
}
@ -111,6 +117,11 @@ impl BackwardsCompatibleChainVerifier {
// now let's do full verification
let noop = NoopStore;
let output_store = DuplexTransactionOutputProvider::new(prevout_provider, &noop);
let previous_block_number = height.checked_sub(1)
.expect("height is the height of future block of new tx; genesis block can't be in the future; qed");
let previous_block_header = block_header_provider.block_header(previous_block_number.into())
.expect("blocks up to height should be in db; qed");
let median_time_past = median_timestamp_inclusive(previous_block_header.hash(), block_header_provider);
let tx_acceptor = MemoryPoolTransactionAcceptor::new(
self.store.as_transaction_meta_provider(),
output_store,
@ -118,6 +129,7 @@ impl BackwardsCompatibleChainVerifier {
canon_tx,
height,
time,
median_time_past,
&deployments,
);
tx_acceptor.check()

View File

@ -110,7 +110,7 @@ pub use verify_transaction::{TransactionVerifier, MemoryPoolTransactionVerifier}
pub use chain_verifier::BackwardsCompatibleChainVerifier;
pub use error::{Error, TransactionError};
pub use sigops::transaction_sigops;
pub use timestamp::median_timestamp;
pub use timestamp::{median_timestamp, median_timestamp_inclusive};
pub use work::{work_required, is_valid_proof_of_work, is_valid_proof_of_work_hash, block_reward_satoshi};
pub use deployments::Deployments;

View File

@ -217,6 +217,7 @@ mod tests {
let uahf_consensus = ConsensusParams::new(Network::Mainnet, ConsensusFork::BitcoinCash(BitcoinCashConsensusParams {
height: 1000,
difficulty_adjustion_height: 0xffffffff,
monolith_time: 0xffffffff,
}));
let mut header_provider = MemoryBlockHeaderProvider::default();
header_provider.insert(BlockHeader {
@ -269,6 +270,7 @@ mod tests {
let uahf_consensus = ConsensusParams::new(Network::Mainnet, ConsensusFork::BitcoinCash(BitcoinCashConsensusParams {
height: 1000,
difficulty_adjustion_height: 0xffffffff,
monolith_time: 0xffffffff,
}));