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