TransactionEval rule
This commit is contained in:
parent
74817084ab
commit
a4e64c0fec
|
@ -22,7 +22,7 @@ impl<'a> ChainAcceptor<'a> {
|
||||||
header: HeaderAcceptor::new(store.as_block_header_provider(), network, block.header(), height),
|
header: HeaderAcceptor::new(store.as_block_header_provider(), network, block.header(), height),
|
||||||
transactions: block.transactions()
|
transactions: block.transactions()
|
||||||
.into_iter()
|
.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(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use db::{TransactionMetaProvider, PreviousTransactionOutputProvider};
|
use db::{TransactionMetaProvider, PreviousTransactionOutputProvider};
|
||||||
use network::{Magic, ConsensusParams};
|
use network::{Magic, ConsensusParams};
|
||||||
|
use script::{Script, verify_script, VerificationFlags, TransactionSignatureChecker, TransactionInputSigner};
|
||||||
use duplex_store::{DuplexTransactionOutputProvider};
|
use duplex_store::{DuplexTransactionOutputProvider};
|
||||||
use sigops::transaction_sigops;
|
use sigops::transaction_sigops;
|
||||||
use canon::CanonTransaction;
|
use canon::CanonTransaction;
|
||||||
|
@ -12,6 +13,7 @@ pub struct TransactionAcceptor<'a> {
|
||||||
pub missing_inputs: TransactionMissingInputs<'a>,
|
pub missing_inputs: TransactionMissingInputs<'a>,
|
||||||
pub maturity: TransactionMaturity<'a>,
|
pub maturity: TransactionMaturity<'a>,
|
||||||
pub overspent: TransactionOverspent<'a>,
|
pub overspent: TransactionOverspent<'a>,
|
||||||
|
pub eval: TransactionEval<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TransactionAcceptor<'a> {
|
impl<'a> TransactionAcceptor<'a> {
|
||||||
|
@ -24,13 +26,16 @@ impl<'a> TransactionAcceptor<'a> {
|
||||||
network: Magic,
|
network: Magic,
|
||||||
transaction: CanonTransaction<'a>,
|
transaction: CanonTransaction<'a>,
|
||||||
block_hash: &'a H256,
|
block_hash: &'a H256,
|
||||||
height: u32
|
height: u32,
|
||||||
|
time: u32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let params = network.consensus_params();
|
||||||
TransactionAcceptor {
|
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),
|
missing_inputs: TransactionMissingInputs::new(transaction, prevout_store),
|
||||||
maturity: TransactionMaturity::new(transaction, meta_store, height),
|
maturity: TransactionMaturity::new(transaction, meta_store, height),
|
||||||
overspent: TransactionOverspent::new(transaction, prevout_store),
|
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
|
// TODO: double spends
|
||||||
try!(self.maturity.check());
|
try!(self.maturity.check());
|
||||||
try!(self.overspent.check());
|
try!(self.overspent.check());
|
||||||
|
try!(self.eval.check());
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue