feat(applying): validate all inputs in UTxO set (#324)
This commit is contained in:
parent
eb4f39d78c
commit
ac4aef4eaa
3 changed files with 45 additions and 3 deletions
|
|
@ -1,18 +1,19 @@
|
||||||
//! Utilities required for Byron-era transaction validation.
|
//! Utilities required for Byron-era transaction validation.
|
||||||
|
|
||||||
use crate::types::{ByronProtParams, UTxOs, ValidationError, ValidationResult};
|
use crate::types::{ByronProtParams, MultiEraInput, UTxOs, ValidationError, ValidationResult};
|
||||||
|
|
||||||
use pallas_primitives::byron::{MintedTxPayload, Tx};
|
use pallas_primitives::byron::{MintedTxPayload, Tx};
|
||||||
|
|
||||||
// TODO: implement missing validation rules.
|
// TODO: implement missing validation rules.
|
||||||
pub fn validate_byron_tx(
|
pub fn validate_byron_tx(
|
||||||
mtxp: &MintedTxPayload,
|
mtxp: &MintedTxPayload,
|
||||||
_utxos: &UTxOs,
|
utxos: &UTxOs,
|
||||||
_prot_pps: &ByronProtParams,
|
_prot_pps: &ByronProtParams,
|
||||||
) -> ValidationResult {
|
) -> ValidationResult {
|
||||||
let tx: &Tx = &mtxp.transaction;
|
let tx: &Tx = &mtxp.transaction;
|
||||||
check_ins_not_empty(tx)?;
|
check_ins_not_empty(tx)?;
|
||||||
check_outs_not_empty(tx)
|
check_outs_not_empty(tx)?;
|
||||||
|
check_ins_in_utxos(tx, utxos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ins_not_empty(tx: &Tx) -> ValidationResult {
|
fn check_ins_not_empty(tx: &Tx) -> ValidationResult {
|
||||||
|
|
@ -28,3 +29,12 @@ fn check_outs_not_empty(tx: &Tx) -> ValidationResult {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_ins_in_utxos(tx: &Tx, utxos: &UTxOs) -> ValidationResult {
|
||||||
|
for input in tx.inputs.iter() {
|
||||||
|
if !(utxos.contains_key(&MultiEraInput::from_byron(input))) {
|
||||||
|
return Err(ValidationError::InputMissingInUTxO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ pub enum MultiEraProtParams<'b> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
|
InputMissingInUTxO,
|
||||||
TxInsEmpty,
|
TxInsEmpty,
|
||||||
TxOutsEmpty,
|
TxOutsEmpty,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,37 @@ mod byron_tests {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// The UTxO set does not contain an entry for the single input to this transaction. This
|
||||||
|
// represents the situation where a transaction tries to spend a non-existent UTxO (e.g., one
|
||||||
|
// which has already been spent).
|
||||||
|
fn unfound_utxo() {
|
||||||
|
let protocol_params: ByronProtParams = ByronProtParams;
|
||||||
|
let mut tx_ins: ByronTxIns = empty_tx_ins();
|
||||||
|
let tx_in: ByronTxIn = new_tx_in(rand_tx_id(), 3);
|
||||||
|
add_byron_tx_in(&mut tx_ins, &tx_in);
|
||||||
|
let mut tx_outs: ByronTxOuts = new_tx_outs();
|
||||||
|
let tx_out_addr: Address = new_addr(rand_addr_payload(), 0);
|
||||||
|
let tx_out: ByronTxOut = new_tx_out(tx_out_addr, 99091);
|
||||||
|
add_tx_out(&mut tx_outs, &tx_out);
|
||||||
|
// Note: utxos is empty, hence the only input to this transaction will not be found, for
|
||||||
|
// which an error should be raised.
|
||||||
|
let utxos: UTxOs = new_utxos();
|
||||||
|
let validation_result = mk_byron_tx_and_validate(
|
||||||
|
&new_tx(tx_ins, tx_outs, empty_attributes()),
|
||||||
|
&empty_witnesses(),
|
||||||
|
&utxos,
|
||||||
|
&protocol_params,
|
||||||
|
);
|
||||||
|
match validation_result {
|
||||||
|
Ok(()) => assert!(false, "All inputs must be within the UTxO set."),
|
||||||
|
Err(err) => match err {
|
||||||
|
ValidationError::InputMissingInUTxO => (),
|
||||||
|
_ => assert!(false, "Unexpected error ({:?}).", err),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types aliases.
|
// Types aliases.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue