Allow transaction inputs to be validated individually

This commit is contained in:
Andrew Poelstra 2014-08-23 15:09:50 -07:00
parent 7eadf72a1a
commit 6e6da2a756
1 changed files with 59 additions and 48 deletions

View File

@ -130,18 +130,20 @@ pub struct TransactionTrace {
impl_json!(TransactionTrace, txid, inputs) impl_json!(TransactionTrace, txid, inputs)
impl Transaction { impl TxIn {
/// Check a transaction for validity /// Check an input's script for validity
pub fn validate(&self, utxoset: &UtxoSet) -> Result<(), TransactionError> { pub fn validate(&self,
for (n, input) in self.input.iter().enumerate() { utxoset: &UtxoSet,
let txo = utxoset.get_utxo(input.prev_hash, input.prev_index); txn: &Transaction,
index: uint) -> Result<(), TransactionError> {
let txo = utxoset.get_utxo(self.prev_hash, self.prev_index);
match txo { match txo {
Some(txo) => { Some(txo) => {
let mut p2sh_stack = Vec::new(); let mut p2sh_stack = Vec::new();
let mut p2sh_script = Script::new(); let mut p2sh_script = Script::new();
let mut stack = Vec::with_capacity(6); let mut stack = Vec::with_capacity(6);
match input.script_sig.evaluate(&mut stack, Some((self, n)), None) { match self.script_sig.evaluate(&mut stack, Some((txn, index)), None) {
Ok(_) => {} Ok(_) => {}
Err(e) => { return Err(InputScriptFailure(e)); } Err(e) => { return Err(InputScriptFailure(e)); }
} }
@ -153,7 +155,7 @@ impl Transaction {
None => unreachable!() None => unreachable!()
}; };
} }
match txo.script_pubkey.evaluate(&mut stack, Some((self, n)), None) { match txo.script_pubkey.evaluate(&mut stack, Some((txn, index)), None) {
Ok(_) => {} Ok(_) => {}
Err(e) => { return Err(OutputScriptFailure(e)); } Err(e) => { return Err(OutputScriptFailure(e)); }
} }
@ -166,7 +168,7 @@ impl Transaction {
None => { return Err(ScriptReturnedEmptyStack); } None => { return Err(ScriptReturnedEmptyStack); }
} }
if txo.script_pubkey.is_p2sh() { if txo.script_pubkey.is_p2sh() {
match p2sh_script.evaluate(&mut p2sh_stack, Some((self, n)), None) { match p2sh_script.evaluate(&mut p2sh_stack, Some((txn, index)), None) {
Ok(_) => {} Ok(_) => {}
Err(e) => { return Err(P2shScriptFailure(e)); } Err(e) => { return Err(P2shScriptFailure(e)); }
} }
@ -180,8 +182,17 @@ impl Transaction {
} }
} }
} }
None => { return Err(InputNotFound(input.prev_hash, input.prev_index)); } None => { return Err(InputNotFound(self.prev_hash, self.prev_index)); }
} }
Ok(())
}
}
impl Transaction {
/// Check a transaction for validity
pub fn validate(&self, utxoset: &UtxoSet) -> Result<(), TransactionError> {
for (n, input) in self.input.iter().enumerate() {
try!(input.validate(utxoset, self, n));
} }
Ok(()) Ok(())
} }