@@ -37,12 +37,19 @@ pub mod v2;
37
37
38
38
type InternalResult < T > = Result < T , InternalProposalError > ;
39
39
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
+
40
47
/// Data required to validate the response against the original PSBT.
41
48
#[ derive( Debug , Clone ) ]
42
49
pub struct PsbtContext {
43
50
original_psbt : Psbt ,
44
51
disable_output_substitution : bool ,
45
- fee_contribution : Option < ( bitcoin :: Amount , usize ) > ,
52
+ fee_contribution : Option < AdditionalFeeContribution > ,
46
53
min_fee_rate : FeeRate ,
47
54
payee : ScriptBuf ,
48
55
}
@@ -224,7 +231,10 @@ impl PsbtContext {
224
231
// fee output
225
232
(
226
233
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
+ } ) ,
228
238
) if proposed_txout. script_pubkey == original_output. script_pubkey
229
239
&& * original_output_index == fee_contrib_idx =>
230
240
{
@@ -338,7 +348,7 @@ fn find_change_index(
338
348
payee : & Script ,
339
349
fee : bitcoin:: Amount ,
340
350
clamp_fee_contribution : bool ,
341
- ) -> Result < Option < ( bitcoin :: Amount , usize ) > , InternalBuildSenderError > {
351
+ ) -> Result < Option < AdditionalFeeContribution > , InternalBuildSenderError > {
342
352
match ( psbt. unsigned_tx . output . len ( ) , clamp_fee_contribution) {
343
353
( 0 , _) => return Err ( InternalBuildSenderError :: NoOutputs ) ,
344
354
( 1 , false ) if psbt. unsigned_tx . output [ 0 ] . script_pubkey == * payee =>
@@ -356,7 +366,10 @@ fn find_change_index(
356
366
. find ( |( _, output) | output. script_pubkey != * payee)
357
367
. ok_or ( InternalBuildSenderError :: MultiplePayeeOutputs ) ?;
358
368
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
+ } ) )
360
373
}
361
374
362
375
/// Check that the change output index is not out of bounds
@@ -367,7 +380,7 @@ fn check_change_index(
367
380
fee : bitcoin:: Amount ,
368
381
index : usize ,
369
382
clamp_fee_contribution : bool ,
370
- ) -> Result < ( bitcoin :: Amount , usize ) , InternalBuildSenderError > {
383
+ ) -> Result < AdditionalFeeContribution , InternalBuildSenderError > {
371
384
let output = psbt
372
385
. unsigned_tx
373
386
. output
@@ -376,15 +389,18 @@ fn check_change_index(
376
389
if output. script_pubkey == * payee {
377
390
return Err ( InternalBuildSenderError :: ChangeIndexPointsAtPayee ) ;
378
391
}
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
+ } )
380
396
}
381
397
382
398
fn determine_fee_contribution (
383
399
psbt : & Psbt ,
384
400
payee : & Script ,
385
401
fee_contribution : Option < ( bitcoin:: Amount , Option < usize > ) > ,
386
402
clamp_fee_contribution : bool ,
387
- ) -> Result < Option < ( bitcoin :: Amount , usize ) > , InternalBuildSenderError > {
403
+ ) -> Result < Option < AdditionalFeeContribution > , InternalBuildSenderError > {
388
404
Ok ( match fee_contribution {
389
405
Some ( ( fee, None ) ) => find_change_index ( psbt, payee, fee, clamp_fee_contribution) ?,
390
406
Some ( ( fee, Some ( index) ) ) =>
@@ -396,7 +412,7 @@ fn determine_fee_contribution(
396
412
fn serialize_url (
397
413
endpoint : Url ,
398
414
disable_output_substitution : bool ,
399
- fee_contribution : Option < ( bitcoin :: Amount , usize ) > ,
415
+ fee_contribution : Option < AdditionalFeeContribution > ,
400
416
min_fee_rate : FeeRate ,
401
417
version : & str ,
402
418
) -> Result < Url , url:: ParseError > {
@@ -405,10 +421,10 @@ fn serialize_url(
405
421
if disable_output_substitution {
406
422
url. query_pairs_mut ( ) . append_pair ( "disableoutputsubstitution" , "true" ) ;
407
423
}
408
- if let Some ( ( amount , index ) ) = fee_contribution {
424
+ if let Some ( AdditionalFeeContribution { max_amount , vout } ) = fee_contribution {
409
425
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 ( ) ) ;
412
428
}
413
429
if min_fee_rate > FeeRate :: ZERO {
414
430
// 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 {
428
444
429
445
use super :: serialize_url;
430
446
use crate :: psbt:: PsbtExt ;
447
+ use crate :: send:: AdditionalFeeContribution ;
431
448
432
449
pub ( crate ) const ORIGINAL_PSBT : & str = "cHNidP8BAHMCAAAAAY8nutGgJdyYGXWiBEb45Hoe9lWGbkxh/6bNiOJdCDuDAAAAAAD+////AtyVuAUAAAAAF6kUHehJ8GnSdBUOOv6ujXLrWmsJRDCHgIQeAAAAAAAXqRR3QJbbz0hnQ8IvQ0fptGn+votneofTAAAAAAEBIKgb1wUAAAAAF6kU3k4ekGHKWRNbA1rV5tR5kEVDVNCHAQcXFgAUx4pFclNVgo1WWAdN1SYNX8tphTABCGsCRzBEAiB8Q+A6dep+Rz92vhy26lT0AjZn4PRLi8Bf9qoB/CMk0wIgP/Rj2PWZ3gEjUkTlhDRNAQ0gXwTO7t9n+V14pZ6oljUBIQMVmsAaoNWHVMS02LfTSe0e388LNitPa1UQZyOihY+FFgABABYAFEb2Giu6c4KO5YW0pfw3lGp9jMUUAAA=" ;
433
450
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 {
439
456
super :: PsbtContext {
440
457
original_psbt,
441
458
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
+ } ) ,
443
463
min_fee_rate : FeeRate :: ZERO ,
444
464
payee,
445
465
}
0 commit comments