TransactionEval rule

This commit is contained in:
debris 2016-12-11 23:26:22 +01:00
parent 74817084ab
commit a4e64c0fec
2 changed files with 69 additions and 3 deletions

View File

@ -22,7 +22,7 @@ impl<'a> ChainAcceptor<'a> {
header: HeaderAcceptor::new(store.as_block_header_provider(), network, block.header(), height),
transactions: block.transactions()
.into_iter()
.map(|tx| TransactionAcceptor::new(store.as_transaction_meta_provider(), prevouts, network, tx, block.hash(), height))
.map(|tx| TransactionAcceptor::new(store.as_transaction_meta_provider(), prevouts, network, tx, block.hash(), height, block.header.raw.time))
.collect(),
}
}

View File

@ -1,6 +1,7 @@
use primitives::hash::H256;
use db::{TransactionMetaProvider, PreviousTransactionOutputProvider};
use network::{Magic, ConsensusParams};
use script::{Script, verify_script, VerificationFlags, TransactionSignatureChecker, TransactionInputSigner};
use duplex_store::{DuplexTransactionOutputProvider};
use sigops::transaction_sigops;
use canon::CanonTransaction;
@ -12,6 +13,7 @@ pub struct TransactionAcceptor<'a> {
pub missing_inputs: TransactionMissingInputs<'a>,
pub maturity: TransactionMaturity<'a>,
pub overspent: TransactionOverspent<'a>,
pub eval: TransactionEval<'a>,
}
impl<'a> TransactionAcceptor<'a> {
@ -24,13 +26,16 @@ impl<'a> TransactionAcceptor<'a> {
network: Magic,
transaction: CanonTransaction<'a>,
block_hash: &'a H256,
height: u32
height: u32,
time: u32,
) -> Self {
let params = network.consensus_params();
TransactionAcceptor {
bip30: TransactionBip30::new_for_sync(transaction, meta_store, network.consensus_params(), block_hash, height),
bip30: TransactionBip30::new_for_sync(transaction, meta_store, params.clone(), block_hash, height),
missing_inputs: TransactionMissingInputs::new(transaction, prevout_store),
maturity: TransactionMaturity::new(transaction, meta_store, height),
overspent: TransactionOverspent::new(transaction, prevout_store),
eval: TransactionEval::new(transaction, prevout_store, params, height, time),
}
}
@ -40,6 +45,7 @@ impl<'a> TransactionAcceptor<'a> {
// TODO: double spends
try!(self.maturity.check());
try!(self.overspent.check());
try!(self.eval.check());
Ok(())
}
}
@ -270,3 +276,63 @@ impl<'a> TransactionRule for TransactionSigops<'a> {
}
}
}
pub struct TransactionEval<'a> {
transaction: CanonTransaction<'a>,
store: DuplexTransactionOutputProvider<'a>,
verify_p2sh: bool,
verify_clocktime: bool,
}
impl<'a> TransactionEval<'a> {
fn new(
transaction: CanonTransaction<'a>,
store: DuplexTransactionOutputProvider<'a>,
params: ConsensusParams,
height: u32,
time: u32,
) -> Self {
let verify_p2sh = time >= params.bip16_time;
let verify_clocktime = height >= params.bip65_height;
TransactionEval {
transaction: transaction,
store: store,
verify_p2sh: verify_p2sh,
verify_clocktime: verify_clocktime,
}
}
}
impl<'a> TransactionRule for TransactionEval<'a> {
fn check(&self) -> Result<(), TransactionError> {
if self.transaction.raw.is_coinbase() {
return Ok(());
}
let signer: TransactionInputSigner = self.transaction.raw.clone().into();
let mut checker = TransactionSignatureChecker {
signer: signer,
input_index: 0,
};
for (index, input) in self.transaction.raw.inputs.iter().enumerate() {
let output = self.store.previous_transaction_output(&input.previous_output)
.ok_or_else(|| TransactionError::UnknownReference(input.previous_output.hash.clone()))?;
checker.input_index = index;
let input: Script = input.script_sig.clone().into();
let output: Script = output.script_pubkey.into();
let flags = VerificationFlags::default()
.verify_p2sh(self.verify_p2sh)
.verify_clocktimeverify(self.verify_clocktime);
try!(verify_script(&input, &output, &flags, &checker).map_err(|_| TransactionError::Signature(index)));
}
Ok(())
}
}