diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs index df1bef8a8..ca7e63524 100644 --- a/primitives/src/transaction.rs +++ b/primitives/src/transaction.rs @@ -598,3 +598,83 @@ impl<'a> Arbitrary<'a> for Txid { Ok(Txid(t)) } } + +#[cfg(feature = "alloc")] +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn transaction_functions() { + let txin = TxIn { + previous_output: OutPoint { + txid: Txid::from_byte_array([0xAA; 32]), // Arbitrary invalid dummy value. + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::new(), + }; + + let txout = TxOut { + value: Amount::from_sat(123456789), + script_pubkey: ScriptBuf::new(), + }; + + let tx_orig = Transaction { + version: Version::ONE, + lock_time: absolute::LockTime::from_consensus(1738968231), // The time this was written + input: vec![txin.clone()], + output: vec![txout.clone()], + }; + + // Test changing the transaction + let mut tx = tx_orig.clone(); + tx.inputs_mut()[0].previous_output.txid = Txid::from_byte_array([0xFF; 32]); + tx.outputs_mut()[0].value = Amount::from_sat(987654321); + assert_eq!(tx.inputs()[0].previous_output.txid.to_byte_array(), [0xFF; 32]); + assert_eq!(tx.outputs()[0].value.to_sat(), 987654321); + + // Test uses_segwit_serialization + assert!(!tx.uses_segwit_serialization()); + tx.input[0].witness.push(vec![0xAB, 0xCD, 0xEF]); + assert!(tx.uses_segwit_serialization()); + + // Test partial ord + assert!(tx > tx_orig); + } + + #[test] + fn outpoint_from_str() { + // Check format errors + let mut outpoint_str = "0".repeat(64); // No ":" + let outpoint: Result = outpoint_str.parse(); + assert_eq!(outpoint, Err(ParseOutPointError::Format)); + + outpoint_str.push(':'); // Empty vout + let outpoint: Result = outpoint_str.parse(); + assert_eq!(outpoint, Err(ParseOutPointError::Format)); + + outpoint_str.push('0'); // Correct format + let outpoint: OutPoint = outpoint_str.parse().unwrap(); + assert_eq!(outpoint.txid, Txid::from_byte_array([0; 32])); + assert_eq!(outpoint.vout, 0); + + // Check the number of bytes OutPoint contributes to the transaction is equal to SIZE + let outpoint_size = outpoint.txid.as_byte_array().len() + outpoint.vout.to_le_bytes().len(); + assert_eq!(outpoint_size, OutPoint::SIZE); + + // Check TooLong error + outpoint_str.push_str("0000000000"); + let outpoint: Result = outpoint_str.parse(); + assert_eq!(outpoint, Err(ParseOutPointError::TooLong)); + } + + #[test] + fn canonical_vout() { + assert_eq!(parse_vout("0").unwrap(), 0); + assert_eq!(parse_vout("1").unwrap(), 1); + assert!(parse_vout("01").is_err()); // Leading zero not allowed + assert!(parse_vout("+1").is_err()); // Non digits not allowed + } +}