Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/pset/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,14 @@ impl PartiallySignedTransaction {
let mut outputs = vec![];

for psetin in &self.inputs {
let prev_index = if psetin.previous_output_index == 0xffff_ffff {
// special-case coinbase inputs, which do not have flags
psetin.previous_output_index
} else {
psetin.previous_output_index & !((1u32 << 30) | (1 << 31))
};
let txin = TxIn {
previous_output: OutPoint::new(psetin.previous_txid, psetin.previous_output_index),
previous_output: OutPoint::new(psetin.previous_txid, dbg!(prev_index)),
is_pegin: psetin.is_pegin(),
script_sig: psetin.final_script_sig.clone().unwrap_or_default(),
sequence: psetin.sequence.unwrap_or(Sequence::MAX),
Expand Down Expand Up @@ -781,6 +787,7 @@ mod tests {
use super::*;
use crate::hex::{FromHex, ToHex};

#[track_caller]
fn tx_pset_rtt(tx_hex: &str) {
let tx: Transaction =
encode::deserialize(&Vec::<u8>::from_hex(tx_hex).unwrap()[..]).unwrap();
Expand Down
68 changes: 67 additions & 1 deletion src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ impl ::std::error::Error for SighashTypeParseError {}
mod tests {
use std::str::FromStr;

use crate::encode::serialize;
use crate::{encode::serialize, pset::PartiallySignedTransaction};
use crate::confidential;
use crate::hex::FromHex;
use secp256k1_zkp::{self, ZERO_TWEAK};
Expand Down Expand Up @@ -2531,4 +2531,70 @@ mod tests {
assert!(tx3.input[0].asset_issuance.amount.explicit().unwrap() > max_money);
assert!(tx4.input[0].asset_issuance.inflation_keys.explicit().unwrap() > max_money);
}

#[test]
fn pset_pegin_witnesses_encoding_round_trip() {
use crate::encode::{serialize, deserialize};

// Start with a transaction that has a pegin.
let base_tx: Transaction = hex_deserialize!(include_str!("../tests/data/1in2out_pegin.hex"));

// Test case (a): input witnesses but no output witnesses
let mut tx_input_only = base_tx.clone();
for output in &mut tx_input_only.output {
output.witness = TxOutWitness::empty();
}

// Test case (b): output witnesses but no input witnesses
let mut tx_output_only = base_tx.clone();
for input in &mut tx_output_only.input {
input.witness = TxInWitness::empty();
}

// Test case (c): no witnesses at all
let mut tx_no_witnesses = base_tx.clone();
for input in &mut tx_no_witnesses.input {
input.witness = TxInWitness::empty();
}
for output in &mut tx_no_witnesses.output {
output.witness = TxOutWitness::empty();
}

// Test all cases: serialize then deserialize and verify they match
let test_cases = vec![
("input_witnesses_only", tx_input_only),
("output_witnesses_only", tx_output_only),
("no_witnesses", tx_no_witnesses),
("both_witnesses", base_tx),
];

for (name, original_tx) in test_cases {
let psbt = PartiallySignedTransaction::from_tx(original_tx.clone());
let psbt_tx = psbt.extract_tx().unwrap();
assert_eq!(original_tx, psbt_tx);

// Serialize the transaction
let serialized = serialize(&original_tx);
let serialized_psbt = serialize(&psbt_tx);

// Deserialize it back
let deserialized_tx: Transaction = deserialize(&serialized)
.unwrap_or_else(|e| panic!("Failed to deserialize {} transaction: {}", name, e));
let deserialized_psbt_tx: Transaction = deserialize(&serialized_psbt)
.unwrap_or_else(|e| panic!("Failed to deserialize {} transaction: {}", name, e));

// Verify they match exactly
assert_eq!(original_tx, deserialized_tx,
"Roundtrip failed for {} transaction", name);
assert_eq!(original_tx, deserialized_psbt_tx,
"Roundtrip failed for {} transaction", name);

// Verify reserialization is consistent
let reserialized = serialize(&deserialized_tx);
assert_eq!(serialized.len(), reserialized.len(),
"Serialized length changed for {} transaction", name);
assert_eq!(serialized, reserialized,
"Serialized bytes changed for {} transaction", name);
}
}
}