Skip to content

Commit

Permalink
Use a builder pattern in WantsOutputs and WantsInputs
Browse files Browse the repository at this point in the history
- Output substitution functions return a modified WantsOutputs instead
  of a WantsInputs. `freeze_outputs` is used to proceed to the
  WantsInputs step.
- Similarly, contribute_witness_inputs returns a modified WantsInputs
  and `freeze_inputs` returns the ProvisionalProposal
- One change output (aka drain script) must be identified if outputs are
  replaced. The change output receives all excess input amount from the
  receiver, and will be responsible for paying receiver fees if
  applicable.
  • Loading branch information
spacebear21 committed Aug 26, 2024
1 parent 77be359 commit c21d563
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 143 deletions.
33 changes: 20 additions & 13 deletions payjoin-cli/src/app/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ impl App {
})?;
log::trace!("check4");

let provisional_payjoin = payjoin.identify_receiver_outputs(|output_script| {
let payjoin = payjoin.identify_receiver_outputs(|output_script| {
if let Ok(address) = bitcoin::Address::from_script(output_script, network) {
bitcoind
.get_address_info(&address)
Expand All @@ -340,17 +340,22 @@ impl App {
}
})?;

let provisional_payjoin = provisional_payjoin.try_substitute_receiver_output(|| {
Ok(bitcoind
.get_new_address(None, None)
.map_err(|e| Error::Server(e.into()))?
.require_network(network)
.map_err(|e| Error::Server(e.into()))?
.script_pubkey())
})?;

let provisional_payjoin = try_contributing_inputs(provisional_payjoin, &bitcoind)
.map_err(|e| Error::Server(e.into()))?;
let payjoin = payjoin
.substitute_receiver_script(
&bitcoind
.get_new_address(None, None)
.map_err(|e| Error::Server(e.into()))?
.require_network(network)
.map_err(|e| Error::Server(e.into()))?
.script_pubkey(),
)?
.commit_outputs();

let provisional_payjoin = try_contributing_inputs(payjoin.clone(), &bitcoind)
.unwrap_or_else(|e| {
log::warn!("Failed to contribute inputs: {}", e);
payjoin.commit_inputs()
});

let payjoin_proposal = provisional_payjoin.finalize_proposal(
|psbt: &Psbt| {
Expand Down Expand Up @@ -390,7 +395,9 @@ fn try_contributing_inputs(
script_pubkey: selected_utxo.script_pub_key.clone(),
};

Ok(payjoin.contribute_witness_inputs(vec![(selected_outpoint, txo_to_contribute)]))
Ok(payjoin
.contribute_witness_inputs(vec![(selected_outpoint, txo_to_contribute)])
.commit_inputs())
}

fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, hyper::Error> {
Expand Down
35 changes: 20 additions & 15 deletions payjoin-cli/src/app/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,21 +316,24 @@ impl App {
})?;
log::trace!("check4");

let provisional_payjoin = payjoin.identify_receiver_outputs(|output_script| {
if let Ok(address) = bitcoin::Address::from_script(output_script, network) {
bitcoind
.get_address_info(&address)
.map(|info| info.is_mine.unwrap_or(false))
.map_err(|e| Error::Server(e.into()))
} else {
Ok(false)
}
})?;

let provisional_payjoin = provisional_payjoin.try_substitute_receiver_outputs(None)?;
let payjoin = payjoin
.identify_receiver_outputs(|output_script| {
if let Ok(address) = bitcoin::Address::from_script(output_script, network) {
bitcoind
.get_address_info(&address)
.map(|info| info.is_mine.unwrap_or(false))
.map_err(|e| Error::Server(e.into()))
} else {
Ok(false)
}
})?
.commit_outputs();

let provisional_payjoin = try_contributing_inputs(provisional_payjoin, &bitcoind)
.map_err(|e| Error::Server(e.into()))?;
let provisional_payjoin = try_contributing_inputs(payjoin.clone(), &bitcoind)
.unwrap_or_else(|e| {
log::warn!("Failed to contribute inputs: {}", e);
payjoin.commit_inputs()
});

let payjoin_proposal = provisional_payjoin.finalize_proposal(
|psbt: &Psbt| {
Expand Down Expand Up @@ -372,7 +375,9 @@ fn try_contributing_inputs(
script_pubkey: selected_utxo.script_pub_key.clone(),
};

Ok(payjoin.contribute_witness_inputs(vec![(selected_outpoint, txo_to_contribute)]))
Ok(payjoin
.contribute_witness_inputs(vec![(selected_outpoint, txo_to_contribute)])
.commit_inputs())
}

async fn unwrap_ohttp_keys_or_else_fetch(config: &AppConfig) -> Result<payjoin::OhttpKeys> {
Expand Down
Loading

0 comments on commit c21d563

Please sign in to comment.