Skip to content

Commit 20620b2

Browse files
authored
Abstract send::AdditionalFeeContribution to named field struct (payjoin#521)
A struct with named fields replaces the tuple abstraction over sender Params `maxadditionalfeecontribution` and `additionalfeeoutputindex`. Cherry-pick'd off payjoin#434
2 parents 5e402c6 + aa22001 commit 20620b2

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

payjoin/src/send/mod.rs

+32-12
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,19 @@ pub mod v2;
3737

3838
type InternalResult<T> = Result<T, InternalProposalError>;
3939

40+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41+
#[cfg_attr(feature = "v2", derive(serde::Serialize, serde::Deserialize))]
42+
pub(crate) struct AdditionalFeeContribution {
43+
max_amount: Amount,
44+
vout: usize,
45+
}
46+
4047
/// Data required to validate the response against the original PSBT.
4148
#[derive(Debug, Clone)]
4249
pub struct PsbtContext {
4350
original_psbt: Psbt,
4451
disable_output_substitution: bool,
45-
fee_contribution: Option<(bitcoin::Amount, usize)>,
52+
fee_contribution: Option<AdditionalFeeContribution>,
4653
min_fee_rate: FeeRate,
4754
payee: ScriptBuf,
4855
}
@@ -224,7 +231,10 @@ impl PsbtContext {
224231
// fee output
225232
(
226233
Some((original_output_index, original_output)),
227-
Some((max_fee_contrib, fee_contrib_idx)),
234+
Some(AdditionalFeeContribution {
235+
max_amount: max_fee_contrib,
236+
vout: fee_contrib_idx,
237+
}),
228238
) if proposed_txout.script_pubkey == original_output.script_pubkey
229239
&& *original_output_index == fee_contrib_idx =>
230240
{
@@ -338,7 +348,7 @@ fn find_change_index(
338348
payee: &Script,
339349
fee: bitcoin::Amount,
340350
clamp_fee_contribution: bool,
341-
) -> Result<Option<(bitcoin::Amount, usize)>, InternalBuildSenderError> {
351+
) -> Result<Option<AdditionalFeeContribution>, InternalBuildSenderError> {
342352
match (psbt.unsigned_tx.output.len(), clamp_fee_contribution) {
343353
(0, _) => return Err(InternalBuildSenderError::NoOutputs),
344354
(1, false) if psbt.unsigned_tx.output[0].script_pubkey == *payee =>
@@ -356,7 +366,10 @@ fn find_change_index(
356366
.find(|(_, output)| output.script_pubkey != *payee)
357367
.ok_or(InternalBuildSenderError::MultiplePayeeOutputs)?;
358368

359-
Ok(Some((check_fee_output_amount(output, fee, clamp_fee_contribution)?, index)))
369+
Ok(Some(AdditionalFeeContribution {
370+
max_amount: check_fee_output_amount(output, fee, clamp_fee_contribution)?,
371+
vout: index,
372+
}))
360373
}
361374

362375
/// Check that the change output index is not out of bounds
@@ -367,7 +380,7 @@ fn check_change_index(
367380
fee: bitcoin::Amount,
368381
index: usize,
369382
clamp_fee_contribution: bool,
370-
) -> Result<(bitcoin::Amount, usize), InternalBuildSenderError> {
383+
) -> Result<AdditionalFeeContribution, InternalBuildSenderError> {
371384
let output = psbt
372385
.unsigned_tx
373386
.output
@@ -376,15 +389,18 @@ fn check_change_index(
376389
if output.script_pubkey == *payee {
377390
return Err(InternalBuildSenderError::ChangeIndexPointsAtPayee);
378391
}
379-
Ok((check_fee_output_amount(output, fee, clamp_fee_contribution)?, index))
392+
Ok(AdditionalFeeContribution {
393+
max_amount: check_fee_output_amount(output, fee, clamp_fee_contribution)?,
394+
vout: index,
395+
})
380396
}
381397

382398
fn determine_fee_contribution(
383399
psbt: &Psbt,
384400
payee: &Script,
385401
fee_contribution: Option<(bitcoin::Amount, Option<usize>)>,
386402
clamp_fee_contribution: bool,
387-
) -> Result<Option<(bitcoin::Amount, usize)>, InternalBuildSenderError> {
403+
) -> Result<Option<AdditionalFeeContribution>, InternalBuildSenderError> {
388404
Ok(match fee_contribution {
389405
Some((fee, None)) => find_change_index(psbt, payee, fee, clamp_fee_contribution)?,
390406
Some((fee, Some(index))) =>
@@ -396,7 +412,7 @@ fn determine_fee_contribution(
396412
fn serialize_url(
397413
endpoint: Url,
398414
disable_output_substitution: bool,
399-
fee_contribution: Option<(bitcoin::Amount, usize)>,
415+
fee_contribution: Option<AdditionalFeeContribution>,
400416
min_fee_rate: FeeRate,
401417
version: &str,
402418
) -> Result<Url, url::ParseError> {
@@ -405,10 +421,10 @@ fn serialize_url(
405421
if disable_output_substitution {
406422
url.query_pairs_mut().append_pair("disableoutputsubstitution", "true");
407423
}
408-
if let Some((amount, index)) = fee_contribution {
424+
if let Some(AdditionalFeeContribution { max_amount, vout }) = fee_contribution {
409425
url.query_pairs_mut()
410-
.append_pair("additionalfeeoutputindex", &index.to_string())
411-
.append_pair("maxadditionalfeecontribution", &amount.to_sat().to_string());
426+
.append_pair("additionalfeeoutputindex", &vout.to_string())
427+
.append_pair("maxadditionalfeecontribution", &max_amount.to_sat().to_string());
412428
}
413429
if min_fee_rate > FeeRate::ZERO {
414430
// TODO serialize in rust-bitcoin <https://github.com/rust-bitcoin/rust-bitcoin/pull/1787/files#diff-c2ea40075e93ccd068673873166cfa3312ec7439d6bc5a4cbc03e972c7e045c4>
@@ -428,6 +444,7 @@ pub(crate) mod test {
428444

429445
use super::serialize_url;
430446
use crate::psbt::PsbtExt;
447+
use crate::send::AdditionalFeeContribution;
431448

432449
pub(crate) const ORIGINAL_PSBT: &str = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=";
433450
const PAYJOIN_PROPOSAL: &str = "cHNidP8BAJwCAAAAAo8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////jye60aAl3JgZdaIERvjkeh72VYZuTGH/ps2I4l0IO4MBAAAAAP7///8CJpW4BQAAAAAXqRQd6EnwadJ0FQ46/q6NcutaawlEMIcACT0AAAAAABepFHdAltvPSGdDwi9DR+m0af6+i2d6h9MAAAAAAQEgqBvXBQAAAAAXqRTeTh6QYcpZE1sDWtXm1HmQRUNU0IcBBBYAFMeKRXJTVYKNVlgHTdUmDV/LaYUwIgYDFZrAGqDVh1TEtNi300ntHt/PCzYrT2tVEGcjooWPhRYYSFzWUDEAAIABAACAAAAAgAEAAAAAAAAAAAEBIICEHgAAAAAAF6kUyPLL+cphRyyI5GTUazV0hF2R2NWHAQcXFgAUX4BmVeWSTJIEwtUb5TlPS/ntohABCGsCRzBEAiBnu3tA3yWlT0WBClsXXS9j69Bt+waCs9JcjWtNjtv7VgIge2VYAaBeLPDB6HGFlpqOENXMldsJezF9Gs5amvDQRDQBIQJl1jz1tBt8hNx2owTm+4Du4isx0pmdKNMNIjjaMHFfrQABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUIgICygvBWB5prpfx61y1HDAwo37kYP3YRJBvAjtunBAur3wYSFzWUDEAAIABAACAAAAAgAEAAAABAAAAAAA=";
@@ -439,7 +456,10 @@ pub(crate) mod test {
439456
super::PsbtContext {
440457
original_psbt,
441458
disable_output_substitution: false,
442-
fee_contribution: Some((bitcoin::Amount::from_sat(182), 0)),
459+
fee_contribution: Some(AdditionalFeeContribution {
460+
max_amount: bitcoin::Amount::from_sat(182),
461+
vout: 0,
462+
}),
443463
min_fee_rate: FeeRate::ZERO,
444464
payee,
445465
}

payjoin/src/send/v1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ pub struct Sender {
219219
/// Disallow reciever to substitute original outputs.
220220
pub(crate) disable_output_substitution: bool,
221221
/// (maxadditionalfeecontribution, additionalfeeoutputindex)
222-
pub(crate) fee_contribution: Option<(bitcoin::Amount, usize)>,
222+
pub(crate) fee_contribution: Option<AdditionalFeeContribution>,
223223
pub(crate) min_fee_rate: FeeRate,
224224
/// Script of the person being paid
225225
pub(crate) payee: ScriptBuf,

payjoin/src/send/v2/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ impl Sender {
196196
fn serialize_v2_body(
197197
psbt: &Psbt,
198198
disable_output_substitution: bool,
199-
fee_contribution: Option<(bitcoin::Amount, usize)>,
199+
fee_contribution: Option<AdditionalFeeContribution>,
200200
min_fee_rate: FeeRate,
201201
) -> Result<Vec<u8>, CreateRequestError> {
202202
// Grug say localhost base be discarded anyway. no big brain needed.

0 commit comments

Comments
 (0)