Skip to content

Commit c1865a1

Browse files
committed
Move InputPair to the receive module
1 parent e7228a5 commit c1865a1

File tree

6 files changed

+46
-43
lines changed

6 files changed

+46
-43
lines changed

payjoin-cli/src/app/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use bitcoin::TxIn;
77
use bitcoincore_rpc::bitcoin::Amount;
88
use bitcoincore_rpc::RpcApi;
99
use payjoin::bitcoin::psbt::Psbt;
10+
use payjoin::receive::InputPair;
1011
use payjoin::send::Sender;
11-
use payjoin::{bitcoin, InputPair, PjUri};
12+
use payjoin::{bitcoin, PjUri};
1213

1314
pub mod config;
1415
use crate::app::config::AppConfig;

payjoin/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,5 @@ mod uri;
4848

4949
#[cfg(feature = "base64")]
5050
pub use bitcoin::base64;
51-
pub use psbt::InputPair;
5251
pub use uri::{PjParseError, PjUri, PjUriBuilder, Uri, UriExt};
5352
pub use url::{ParseError, Url};

payjoin/src/psbt.rs

-37
Original file line numberDiff line numberDiff line change
@@ -106,49 +106,12 @@ fn redeem_script(script_sig: &Script) -> Option<&Script> {
106106
// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh
107107
const NESTED_P2WPKH_MAX: InputWeightPrediction = InputWeightPrediction::from_slice(23, &[72, 33]);
108108

109-
#[derive(Clone, Debug)]
110-
pub struct InputPair {
111-
pub(crate) txin: TxIn,
112-
pub(crate) psbtin: psbt::Input,
113-
}
114-
115-
impl InputPair {
116-
pub fn new(txin: TxIn, psbtin: psbt::Input) -> Result<Self, PsbtInputError> {
117-
let input_pair = Self { txin, psbtin };
118-
// TODO consider whether or not this should live in receive module since it's a baby of that state machine
119-
let raw = InternalInputPair::from(&input_pair);
120-
raw.validate_utxo(true)?;
121-
let address_type = raw.address_type()?;
122-
if address_type == AddressType::P2sh && input_pair.psbtin.redeem_script.is_none() {
123-
return Err(PsbtInputError::NoRedeemScript);
124-
}
125-
Ok(input_pair)
126-
}
127-
128-
pub(crate) fn address_type(&self) -> AddressType {
129-
InternalInputPair::from(self)
130-
.address_type()
131-
.expect("address type should have been validated in InputPair::new")
132-
}
133-
134-
pub(crate) fn previous_txout(&self) -> TxOut {
135-
InternalInputPair::from(self)
136-
.previous_txout()
137-
.expect("UTXO information should have been validated in InputPair::new")
138-
.clone()
139-
}
140-
}
141-
142109
#[derive(Clone, Debug)]
143110
pub(crate) struct InternalInputPair<'a> {
144111
pub txin: &'a TxIn,
145112
pub psbtin: &'a psbt::Input,
146113
}
147114

148-
impl<'a> From<&'a InputPair> for InternalInputPair<'a> {
149-
fn from(pair: &'a InputPair) -> Self { Self { psbtin: &pair.psbtin, txin: &pair.txin } }
150-
}
151-
152115
impl<'a> InternalInputPair<'a> {
153116
/// Returns TxOut associated with the input
154117
pub fn previous_txout(&self) -> Result<&TxOut, PrevTxOutError> {

payjoin/src/receive/mod.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use std::cmp::{max, min};
2929
use bitcoin::base64::prelude::BASE64_STANDARD;
3030
use bitcoin::base64::Engine;
3131
use bitcoin::psbt::Psbt;
32-
use bitcoin::{Amount, FeeRate, OutPoint, Script, TxIn, TxOut, Weight};
32+
use bitcoin::{psbt, AddressType, Amount, FeeRate, OutPoint, Script, TxIn, TxOut, Weight};
3333

3434
mod error;
3535
mod optional_parameters;
@@ -47,12 +47,50 @@ use error::{
4747
};
4848
use optional_parameters::Params;
4949

50-
use crate::psbt::{InputPair, PsbtExt};
50+
use crate::psbt::{InternalInputPair, PsbtExt, PsbtInputError};
5151

5252
pub trait Headers {
5353
fn get_header(&self, key: &str) -> Option<&str>;
5454
}
5555

56+
/// Helper to construct a pair of (txin, psbtin) with some built-in validation
57+
/// Use with [`InputPair::new`] to contribute receiver inputs.
58+
#[derive(Clone, Debug)]
59+
pub struct InputPair {
60+
pub(crate) txin: TxIn,
61+
pub(crate) psbtin: psbt::Input,
62+
}
63+
64+
impl InputPair {
65+
pub fn new(txin: TxIn, psbtin: psbt::Input) -> Result<Self, PsbtInputError> {
66+
let input_pair = Self { txin, psbtin };
67+
let raw = InternalInputPair::from(&input_pair);
68+
raw.validate_utxo(true)?;
69+
let address_type = raw.address_type()?;
70+
if address_type == AddressType::P2sh && input_pair.psbtin.redeem_script.is_none() {
71+
return Err(PsbtInputError::NoRedeemScript);
72+
}
73+
Ok(input_pair)
74+
}
75+
76+
pub(crate) fn address_type(&self) -> AddressType {
77+
InternalInputPair::from(self)
78+
.address_type()
79+
.expect("address type should have been validated in InputPair::new")
80+
}
81+
82+
pub(crate) fn previous_txout(&self) -> TxOut {
83+
InternalInputPair::from(self)
84+
.previous_txout()
85+
.expect("UTXO information should have been validated in InputPair::new")
86+
.clone()
87+
}
88+
}
89+
90+
impl<'a> From<&'a InputPair> for InternalInputPair<'a> {
91+
fn from(pair: &'a InputPair) -> Self { Self { psbtin: &pair.psbtin, txin: &pair.txin } }
92+
}
93+
5694
/// The sender's original PSBT and optional parameters
5795
///
5896
/// This type is used to process the request. It is returned by

payjoin/src/receive/v2/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use super::{
1616
};
1717
use crate::hpke::{decrypt_message_a, encrypt_message_b, HpkeKeyPair, HpkePublicKey};
1818
use crate::ohttp::{ohttp_decapsulate, ohttp_encapsulate, OhttpEncapsulationError, OhttpKeys};
19-
use crate::psbt::{InputPair, PsbtExt};
19+
use crate::psbt::PsbtExt;
2020
use crate::receive::optional_parameters::Params;
21+
use crate::receive::InputPair;
2122
use crate::{PjUriBuilder, Request};
2223

2324
pub(crate) mod error;

payjoin/tests/integration.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ mod integration {
1212
use bitcoind::bitcoincore_rpc::{self, RpcApi};
1313
use log::{log_enabled, Level};
1414
use once_cell::sync::{Lazy, OnceCell};
15+
use payjoin::receive::InputPair;
1516
use payjoin::send::SenderBuilder;
16-
use payjoin::{InputPair, PjUri, PjUriBuilder, Request, Uri};
17+
use payjoin::{PjUri, PjUriBuilder, Request, Uri};
1718
use tracing_subscriber::{EnvFilter, FmtSubscriber};
1819
use url::Url;
1920

0 commit comments

Comments
 (0)