From ef0304d3ff79c001c20d7e81294fa7018da8af13 Mon Sep 17 00:00:00 2001 From: Maico Date: Tue, 17 Oct 2023 15:52:22 -0300 Subject: [PATCH] feat: all inputs in UTxO set --- pallas-applying/src/byron.rs | 16 +++++++++++++--- pallas-applying/src/types.rs | 1 + pallas-applying/tests/byron.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/pallas-applying/src/byron.rs b/pallas-applying/src/byron.rs index ef604cdf..67136d89 100644 --- a/pallas-applying/src/byron.rs +++ b/pallas-applying/src/byron.rs @@ -1,18 +1,19 @@ //! 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}; // TODO: implement missing validation rules. pub fn validate_byron_tx( mtxp: &MintedTxPayload, - _utxos: &UTxOs, + utxos: &UTxOs, _prot_pps: &ByronProtParams, ) -> ValidationResult { let tx: &Tx = &mtxp.transaction; 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 { @@ -28,3 +29,12 @@ fn check_outs_not_empty(tx: &Tx) -> ValidationResult { } 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(()) +} diff --git a/pallas-applying/src/types.rs b/pallas-applying/src/types.rs index 017e7df4..a2090086 100644 --- a/pallas-applying/src/types.rs +++ b/pallas-applying/src/types.rs @@ -21,6 +21,7 @@ pub enum MultiEraProtParams<'b> { #[derive(Debug)] #[non_exhaustive] pub enum ValidationError { + InputMissingInUTxO, TxInsEmpty, TxOutsEmpty, } diff --git a/pallas-applying/tests/byron.rs b/pallas-applying/tests/byron.rs index 70afe974..aac041c5 100644 --- a/pallas-applying/tests/byron.rs +++ b/pallas-applying/tests/byron.rs @@ -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.