verification: TransactionJointSplitInCoinbase

This commit is contained in:
Svyatoslav Nikolsky 2018-11-14 12:31:26 +03:00
parent fdd78009a2
commit 88c0c3dde0
3 changed files with 96 additions and 3 deletions

View File

@ -33,6 +33,25 @@ impl<'a> TransactionAcceptor<'a> {
transaction_index: usize,
deployments: &'a BlockDeployments<'a>,
) -> Self {
/*
TODO:
Sprout:
reject transactions which are intended for Overwinter and beyond
Overwinter:
tx version
tx version group
reject transactions with valid version but missing overwinter flag
reject transactions intended for Sprout
check that all transactions are unexpired
Sapling:
tx version
tx version group
reject transactions intended for Sprout
check that all transactions are unexpired
block max size changes!!!
*/
trace!(target: "verification", "Tx verification {}", transaction.hash.to_reversed_str());
TransactionAcceptor {
bip30: TransactionBip30::new_for_sync(transaction, meta_store),

View File

@ -103,5 +103,7 @@ pub enum TransactionError {
UnspentTransactionWithTheSameHash,
/// Using output that is surely spent
UsingSpentOutput(H256, u32),
/// A coinbase transaction MUST NOT have any joint split descriptions
CoinbaseWithJointSplit,
}

View File

@ -11,6 +11,7 @@ pub struct TransactionVerifier<'a> {
pub empty: TransactionEmpty<'a>,
pub null_non_coinbase: TransactionNullNonCoinbase<'a>,
pub oversized_coinbase: TransactionOversizedCoinbase<'a>,
pub joint_split_in_coinbase: TransactionJointSplitInCoinbase<'a>,
}
impl<'a> TransactionVerifier<'a> {
@ -20,13 +21,15 @@ impl<'a> TransactionVerifier<'a> {
empty: TransactionEmpty::new(transaction),
null_non_coinbase: TransactionNullNonCoinbase::new(transaction),
oversized_coinbase: TransactionOversizedCoinbase::new(transaction, MIN_COINBASE_SIZE..MAX_COINBASE_SIZE),
joint_split_in_coinbase: TransactionJointSplitInCoinbase::new(transaction),
}
}
pub fn check(&self) -> Result<(), TransactionError> {
try!(self.empty.check());
try!(self.null_non_coinbase.check());
try!(self.oversized_coinbase.check());
self.empty.check()?;
self.null_non_coinbase.check()?;
self.oversized_coinbase.check()?;
self.joint_split_in_coinbase.check()?;
Ok(())
}
}
@ -190,3 +193,72 @@ impl<'a> TransactionSigops<'a> {
}
}
}
pub struct TransactionJointSplitInCoinbase<'a> {
transaction: &'a IndexedTransaction,
}
impl<'a> TransactionJointSplitInCoinbase<'a> {
fn new(transaction: &'a IndexedTransaction) -> Self {
TransactionJointSplitInCoinbase {
transaction,
}
}
fn check(&self) -> Result<(), TransactionError> {
if self.transaction.raw.is_coinbase() && self.transaction.raw.joint_split.is_some() {
return Err(TransactionError::CoinbaseWithJointSplit);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use chain::{Transaction, OutPoint, TransactionInput, IndexedTransaction};
use error::TransactionError;
use super::TransactionJointSplitInCoinbase;
#[test]
fn transaction_joint_split_in_coinbase_works() {
let coinbase_with_joint_split: IndexedTransaction = Transaction {
inputs: vec![TransactionInput {
previous_output: OutPoint::null(),
..Default::default()
}],
joint_split: Some(Default::default()),
..Default::default()
}.into();
assert_eq!(
TransactionJointSplitInCoinbase::new(&coinbase_with_joint_split).check(),
Err(TransactionError::CoinbaseWithJointSplit)
);
let coinbase_without_joint_split: IndexedTransaction = Transaction {
inputs: vec![Default::default()],
..Default::default()
}.into();
assert_eq!(
TransactionJointSplitInCoinbase::new(&coinbase_without_joint_split).check(),
Ok(())
);
let non_coinbase_with_joint_split: IndexedTransaction = Transaction {
joint_split: Some(Default::default()),
..Default::default()
}.into();
assert_eq!(
TransactionJointSplitInCoinbase::new(&non_coinbase_with_joint_split).check(),
Ok(())
);
let non_coinbase_without_joint_split: IndexedTransaction = Transaction {
..Default::default()
}.into();
assert_eq!(
TransactionJointSplitInCoinbase::new(&non_coinbase_without_joint_split).check(),
Ok(())
);
}
}