segwit: premature witness check
This commit is contained in:
parent
d4a191aec1
commit
b90c8add96
|
@ -39,7 +39,7 @@ impl<'a> ChainAcceptor<'a> {
|
|||
height,
|
||||
block.header.raw.time,
|
||||
tx_index,
|
||||
deployments,
|
||||
active_deployments,
|
||||
headers,
|
||||
))
|
||||
.collect(),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use primitives::hash::H256;
|
||||
use primitives::bytes::Bytes;
|
||||
use db::{TransactionMetaProvider, TransactionOutputProvider, BlockHeaderProvider};
|
||||
use network::{ConsensusParams, ConsensusFork};
|
||||
use network::{ConsensusParams, ConsensusFork, Deployments as NetworkDeployments};
|
||||
use script::{Script, ScriptWitness, verify_script, VerificationFlags, TransactionSignatureChecker, TransactionInputSigner, SignatureVersion};
|
||||
use duplex_store::DuplexTransactionOutputProvider;
|
||||
use deployments::Deployments;
|
||||
use deployments::{Deployments, ActiveDeployments};
|
||||
use script::Builder;
|
||||
use sigops::transaction_sigops;
|
||||
use canon::CanonTransaction;
|
||||
|
@ -13,6 +13,7 @@ use error::TransactionError;
|
|||
use VerificationLevel;
|
||||
|
||||
pub struct TransactionAcceptor<'a> {
|
||||
pub premature_witness: TransactionPrematureWitness<'a>,
|
||||
pub bip30: TransactionBip30<'a>,
|
||||
pub missing_inputs: TransactionMissingInputs<'a>,
|
||||
pub maturity: TransactionMaturity<'a>,
|
||||
|
@ -36,22 +37,24 @@ impl<'a> TransactionAcceptor<'a> {
|
|||
height: u32,
|
||||
time: u32,
|
||||
transaction_index: usize,
|
||||
deployments: &'a Deployments,
|
||||
deployments: ActiveDeployments<'a>,
|
||||
headers: &'a BlockHeaderProvider,
|
||||
) -> Self {
|
||||
trace!(target: "verification", "Tx verification {}", transaction.hash.to_reversed_str());
|
||||
TransactionAcceptor {
|
||||
premature_witness: TransactionPrematureWitness::new(transaction, deployments.is_active("segwit")),
|
||||
bip30: TransactionBip30::new_for_sync(transaction, meta_store, consensus, block_hash, height),
|
||||
missing_inputs: TransactionMissingInputs::new(transaction, output_store, transaction_index),
|
||||
maturity: TransactionMaturity::new(transaction, meta_store, height),
|
||||
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, headers),
|
||||
eval: TransactionEval::new(transaction, output_store, consensus, verification_level, height, time, deployments.deployments, headers),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(&self) -> Result<(), TransactionError> {
|
||||
try!(self.premature_witness.check());
|
||||
try!(self.bip30.check());
|
||||
try!(self.missing_inputs.check());
|
||||
try!(self.maturity.check());
|
||||
|
@ -435,6 +438,28 @@ impl<'a> TransactionReturnReplayProtection<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TransactionPrematureWitness<'a> {
|
||||
transaction: CanonTransaction<'a>,
|
||||
is_segwit_active: bool,
|
||||
}
|
||||
|
||||
impl<'a> TransactionPrematureWitness<'a> {
|
||||
pub fn new(transaction: CanonTransaction<'a>, is_segwit_active: bool) -> Self {
|
||||
TransactionPrematureWitness {
|
||||
transaction: transaction,
|
||||
is_segwit_active: is_segwit_active,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(&self) -> Result<(), TransactionError> {
|
||||
if !self.is_segwit_active && (*self.transaction).raw.has_witness() {
|
||||
Err(TransactionError::PrematureWitness)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chain::{IndexedTransaction, Transaction, TransactionOutput};
|
||||
|
|
|
@ -95,5 +95,7 @@ pub enum TransactionError {
|
|||
UsingSpentOutput(H256, u32),
|
||||
/// Transaction, protected using BitcoinCash OP_RETURN replay protection (REQ-6-1).
|
||||
ReturnReplayProtection,
|
||||
/// Transaction with witness is received before SegWit is activated.
|
||||
PrematureWitness,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops;
|
||||
use ser::Serializable;
|
||||
use chain::IndexedTransaction;
|
||||
use network::{ConsensusParams, ConsensusFork};
|
||||
use network::{ConsensusParams, ConsensusFork, Deployments};
|
||||
use duplex_store::NoopStore;
|
||||
use sigops::transaction_sigops;
|
||||
use error::TransactionError;
|
||||
|
@ -37,6 +37,7 @@ pub struct MemoryPoolTransactionVerifier<'a> {
|
|||
pub null_non_coinbase: TransactionNullNonCoinbase<'a>,
|
||||
pub is_coinbase: TransactionMemoryPoolCoinbase<'a>,
|
||||
pub size: TransactionSize<'a>,
|
||||
pub premature_witness: TransactionPrematureWitness<'a>,
|
||||
pub sigops: TransactionSigops<'a>,
|
||||
}
|
||||
|
||||
|
@ -48,6 +49,7 @@ impl<'a> MemoryPoolTransactionVerifier<'a> {
|
|||
null_non_coinbase: TransactionNullNonCoinbase::new(transaction),
|
||||
is_coinbase: TransactionMemoryPoolCoinbase::new(transaction),
|
||||
size: TransactionSize::new(transaction, deployments, consensus),
|
||||
premature_witness: TransactionPrematureWitness::new(transaction, deployments),
|
||||
sigops: TransactionSigops::new(transaction, ConsensusFork::absolute_maximum_block_sigops()),
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +59,7 @@ impl<'a> MemoryPoolTransactionVerifier<'a> {
|
|||
try!(self.null_non_coinbase.check());
|
||||
try!(self.is_coinbase.check());
|
||||
try!(self.size.check());
|
||||
try!(self.premature_witness.check());
|
||||
try!(self.sigops.check());
|
||||
Ok(())
|
||||
}
|
||||
|
@ -192,3 +195,25 @@ impl<'a> TransactionSigops<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TransactionPrematureWitness<'a> {
|
||||
transaction: &'a IndexedTransaction,
|
||||
deployments: ActiveDeployments<'a>,
|
||||
}
|
||||
|
||||
impl<'a> TransactionPrematureWitness<'a> {
|
||||
pub fn new(transaction: &'a IndexedTransaction, deployments: ActiveDeployments<'a>) -> Self {
|
||||
TransactionPrematureWitness {
|
||||
transaction: transaction,
|
||||
deployments: deployments,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(&self) -> Result<(), TransactionError> {
|
||||
if self.transaction.raw.has_witness() && !self.deployments.is_active("segwit") {
|
||||
Err(TransactionError::PrematureWitness)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue