From 9f4237dae46f32dc8b350b0dd66535c55c46bd5c Mon Sep 17 00:00:00 2001 From: chavic Date: Wed, 17 Jun 2026 21:35:22 +0200 Subject: [PATCH 1/2] Expose InputPair outpoint over FFI --- payjoin-ffi/csharp/UnitTests.cs | 24 ++++++++++++++++++++++++ payjoin-ffi/src/receive/mod.rs | 3 +++ payjoin/src/core/receive/mod.rs | 15 +++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/payjoin-ffi/csharp/UnitTests.cs b/payjoin-ffi/csharp/UnitTests.cs index 655286fa5..87899e371 100644 --- a/payjoin-ffi/csharp/UnitTests.cs +++ b/payjoin-ffi/csharp/UnitTests.cs @@ -305,6 +305,30 @@ public void InputPairRejectsInvalidOutpoint() }); } + [Fact] + public void InputPairExposesPreviousOutpoint() + { + const string txid = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const uint vout = 7; + var txin = new TxIn( + new OutPoint(txid, vout), + new byte[] {}, + uint.MaxValue, + new byte[][] {} + ); + var psbtIn = new PsbtInput( + new TxOut(12345, Convert.FromHexString("00140000000000000000000000000000000000000000")), + null, + null + ); + using var inputPair = new InputPair(txin, psbtIn, null); + + var outpoint = inputPair.PreviousOutpoint(); + + Assert.Equal(txid, outpoint.txid); + Assert.Equal(vout, outpoint.vout); + } + [Fact] public void SenderBuilderRejectsBadPsbt() { diff --git a/payjoin-ffi/src/receive/mod.rs b/payjoin-ffi/src/receive/mod.rs index e560c1806..3393e29f9 100644 --- a/payjoin-ffi/src/receive/mod.rs +++ b/payjoin-ffi/src/receive/mod.rs @@ -1114,6 +1114,9 @@ impl InputPair { .map(Self) .map_err(|err| InputPairError::InvalidPsbtInput(Arc::new(err.into()))) } + + /// Returns the outpoint spent by this input pair. + pub fn previous_outpoint(&self) -> OutPoint { self.0.previous_outpoint().into() } } impl From for payjoin::receive::InputPair { diff --git a/payjoin/src/core/receive/mod.rs b/payjoin/src/core/receive/mod.rs index 259e91422..4c78bd61d 100644 --- a/payjoin/src/core/receive/mod.rs +++ b/payjoin/src/core/receive/mod.rs @@ -216,6 +216,9 @@ impl InputPair { Self::new_segwit_input_pair(txout, outpoint, Some(expected_weight)) } + /// Returns the outpoint spent by this input pair. + pub fn previous_outpoint(&self) -> OutPoint { self.txin.previous_output } + pub(crate) fn previous_txout(&self) -> TxOut { InternalInputPair::from(self) .previous_txout() @@ -541,6 +544,18 @@ pub(crate) mod tests { assert_eq!(input_pair.expected_weight, expected_satifiability_weight); } + #[test] + fn input_pair_previous_outpoint_returns_previous_output() { + let txout = TxOut { + value: Amount::from_sat(123), + script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array(DUMMY20)), + }; + let outpoint = OutPoint { txid: Txid::from_byte_array(DUMMY32), vout: 31 }; + let input_pair = InputPair::new_p2wpkh(txout, outpoint).unwrap(); + + assert_eq!(input_pair.previous_outpoint(), outpoint); + } + #[test] fn create_p2pkh_input_pair() { let p2sh_txout = TxOut { From 2032babe6c3dbc9d6419c128ee4863291f3e5e52 Mon Sep 17 00:00:00 2001 From: chavic Date: Wed, 24 Jun 2026 15:09:22 +0200 Subject: [PATCH 2/2] Rename InputPair outpoint accessor Use outpoint() instead of previous_outpoint() for the InputPair accessor exposed to FFI. The shorter name matches the data returned: the txid and vout reference for the UTXO spent by the input pair. --- payjoin-ffi/csharp/UnitTests.cs | 4 ++-- payjoin-ffi/src/receive/mod.rs | 2 +- payjoin/src/core/receive/mod.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/payjoin-ffi/csharp/UnitTests.cs b/payjoin-ffi/csharp/UnitTests.cs index 87899e371..01592395f 100644 --- a/payjoin-ffi/csharp/UnitTests.cs +++ b/payjoin-ffi/csharp/UnitTests.cs @@ -306,7 +306,7 @@ public void InputPairRejectsInvalidOutpoint() } [Fact] - public void InputPairExposesPreviousOutpoint() + public void InputPairExposesOutpoint() { const string txid = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; const uint vout = 7; @@ -323,7 +323,7 @@ public void InputPairExposesPreviousOutpoint() ); using var inputPair = new InputPair(txin, psbtIn, null); - var outpoint = inputPair.PreviousOutpoint(); + var outpoint = inputPair.Outpoint(); Assert.Equal(txid, outpoint.txid); Assert.Equal(vout, outpoint.vout); diff --git a/payjoin-ffi/src/receive/mod.rs b/payjoin-ffi/src/receive/mod.rs index 3393e29f9..3295c7779 100644 --- a/payjoin-ffi/src/receive/mod.rs +++ b/payjoin-ffi/src/receive/mod.rs @@ -1116,7 +1116,7 @@ impl InputPair { } /// Returns the outpoint spent by this input pair. - pub fn previous_outpoint(&self) -> OutPoint { self.0.previous_outpoint().into() } + pub fn outpoint(&self) -> OutPoint { self.0.outpoint().into() } } impl From for payjoin::receive::InputPair { diff --git a/payjoin/src/core/receive/mod.rs b/payjoin/src/core/receive/mod.rs index 4c78bd61d..b665856b7 100644 --- a/payjoin/src/core/receive/mod.rs +++ b/payjoin/src/core/receive/mod.rs @@ -217,7 +217,7 @@ impl InputPair { } /// Returns the outpoint spent by this input pair. - pub fn previous_outpoint(&self) -> OutPoint { self.txin.previous_output } + pub fn outpoint(&self) -> OutPoint { self.txin.previous_output } pub(crate) fn previous_txout(&self) -> TxOut { InternalInputPair::from(self) @@ -545,7 +545,7 @@ pub(crate) mod tests { } #[test] - fn input_pair_previous_outpoint_returns_previous_output() { + fn input_pair_outpoint_returns_previous_output() { let txout = TxOut { value: Amount::from_sat(123), script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array(DUMMY20)), @@ -553,7 +553,7 @@ pub(crate) mod tests { let outpoint = OutPoint { txid: Txid::from_byte_array(DUMMY32), vout: 31 }; let input_pair = InputPair::new_p2wpkh(txout, outpoint).unwrap(); - assert_eq!(input_pair.previous_outpoint(), outpoint); + assert_eq!(input_pair.outpoint(), outpoint); } #[test]