Skip to content

Commit

Permalink
Move InputPair to the receive module
Browse files Browse the repository at this point in the history
  • Loading branch information
spacebear21 committed Oct 30, 2024
1 parent e7228a5 commit c1865a1
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 43 deletions.
3 changes: 2 additions & 1 deletion payjoin-cli/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use bitcoin::TxIn;
use bitcoincore_rpc::bitcoin::Amount;
use bitcoincore_rpc::RpcApi;
use payjoin::bitcoin::psbt::Psbt;
use payjoin::receive::InputPair;
use payjoin::send::Sender;
use payjoin::{bitcoin, InputPair, PjUri};
use payjoin::{bitcoin, PjUri};

pub mod config;
use crate::app::config::AppConfig;
Expand Down
1 change: 0 additions & 1 deletion payjoin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,5 @@ mod uri;

#[cfg(feature = "base64")]
pub use bitcoin::base64;
pub use psbt::InputPair;
pub use uri::{PjParseError, PjUri, PjUriBuilder, Uri, UriExt};
pub use url::{ParseError, Url};
37 changes: 0 additions & 37 deletions payjoin/src/psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,49 +106,12 @@ fn redeem_script(script_sig: &Script) -> Option<&Script> {
// https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh
const NESTED_P2WPKH_MAX: InputWeightPrediction = InputWeightPrediction::from_slice(23, &[72, 33]);

#[derive(Clone, Debug)]
pub struct InputPair {
pub(crate) txin: TxIn,
pub(crate) psbtin: psbt::Input,
}

impl InputPair {
pub fn new(txin: TxIn, psbtin: psbt::Input) -> Result<Self, PsbtInputError> {
let input_pair = Self { txin, psbtin };
// TODO consider whether or not this should live in receive module since it's a baby of that state machine
let raw = InternalInputPair::from(&input_pair);
raw.validate_utxo(true)?;
let address_type = raw.address_type()?;
if address_type == AddressType::P2sh && input_pair.psbtin.redeem_script.is_none() {
return Err(PsbtInputError::NoRedeemScript);
}
Ok(input_pair)
}

pub(crate) fn address_type(&self) -> AddressType {
InternalInputPair::from(self)
.address_type()
.expect("address type should have been validated in InputPair::new")
}

pub(crate) fn previous_txout(&self) -> TxOut {
InternalInputPair::from(self)
.previous_txout()
.expect("UTXO information should have been validated in InputPair::new")
.clone()
}
}

#[derive(Clone, Debug)]
pub(crate) struct InternalInputPair<'a> {
pub txin: &'a TxIn,
pub psbtin: &'a psbt::Input,
}

impl<'a> From<&'a InputPair> for InternalInputPair<'a> {
fn from(pair: &'a InputPair) -> Self { Self { psbtin: &pair.psbtin, txin: &pair.txin } }
}

impl<'a> InternalInputPair<'a> {
/// Returns TxOut associated with the input
pub fn previous_txout(&self) -> Result<&TxOut, PrevTxOutError> {
Expand Down
42 changes: 40 additions & 2 deletions payjoin/src/receive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use std::cmp::{max, min};
use bitcoin::base64::prelude::BASE64_STANDARD;
use bitcoin::base64::Engine;
use bitcoin::psbt::Psbt;
use bitcoin::{Amount, FeeRate, OutPoint, Script, TxIn, TxOut, Weight};
use bitcoin::{psbt, AddressType, Amount, FeeRate, OutPoint, Script, TxIn, TxOut, Weight};

mod error;
mod optional_parameters;
Expand All @@ -47,12 +47,50 @@ use error::{
};
use optional_parameters::Params;

use crate::psbt::{InputPair, PsbtExt};
use crate::psbt::{InternalInputPair, PsbtExt, PsbtInputError};

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

/// Helper to construct a pair of (txin, psbtin) with some built-in validation
/// Use with [`InputPair::new`] to contribute receiver inputs.
#[derive(Clone, Debug)]
pub struct InputPair {
pub(crate) txin: TxIn,
pub(crate) psbtin: psbt::Input,
}

impl InputPair {
pub fn new(txin: TxIn, psbtin: psbt::Input) -> Result<Self, PsbtInputError> {
let input_pair = Self { txin, psbtin };
let raw = InternalInputPair::from(&input_pair);
raw.validate_utxo(true)?;
let address_type = raw.address_type()?;
if address_type == AddressType::P2sh && input_pair.psbtin.redeem_script.is_none() {
return Err(PsbtInputError::NoRedeemScript);
}
Ok(input_pair)
}

pub(crate) fn address_type(&self) -> AddressType {
InternalInputPair::from(self)
.address_type()
.expect("address type should have been validated in InputPair::new")
}

pub(crate) fn previous_txout(&self) -> TxOut {
InternalInputPair::from(self)
.previous_txout()
.expect("UTXO information should have been validated in InputPair::new")
.clone()
}
}

impl<'a> From<&'a InputPair> for InternalInputPair<'a> {
fn from(pair: &'a InputPair) -> Self { Self { psbtin: &pair.psbtin, txin: &pair.txin } }
}

/// The sender's original PSBT and optional parameters
///
/// This type is used to process the request. It is returned by
Expand Down
3 changes: 2 additions & 1 deletion payjoin/src/receive/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ use super::{
};
use crate::hpke::{decrypt_message_a, encrypt_message_b, HpkeKeyPair, HpkePublicKey};
use crate::ohttp::{ohttp_decapsulate, ohttp_encapsulate, OhttpEncapsulationError, OhttpKeys};
use crate::psbt::{InputPair, PsbtExt};
use crate::psbt::PsbtExt;
use crate::receive::optional_parameters::Params;
use crate::receive::InputPair;
use crate::{PjUriBuilder, Request};

pub(crate) mod error;
Expand Down
3 changes: 2 additions & 1 deletion payjoin/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ mod integration {
use bitcoind::bitcoincore_rpc::{self, RpcApi};
use log::{log_enabled, Level};
use once_cell::sync::{Lazy, OnceCell};
use payjoin::receive::InputPair;
use payjoin::send::SenderBuilder;
use payjoin::{InputPair, PjUri, PjUriBuilder, Request, Uri};
use payjoin::{PjUri, PjUriBuilder, Request, Uri};
use tracing_subscriber::{EnvFilter, FmtSubscriber};
use url::Url;

Expand Down

0 comments on commit c1865a1

Please sign in to comment.