@@ -589,15 +589,28 @@ namespace sdk {
589
589
// Add all outputs and compute the total amount of satoshi to be sent
590
590
amount required_total{ 0 };
591
591
592
+ uint32_t explicit_change_index = NO_CHANGE_INDEX;
592
593
if (num_addressees) {
594
+ size_t addressee_index = 0 ;
593
595
for (auto & addressee : *addressees_p) {
594
596
const auto addressee_asset_id = asset_id_from_json (net_params, addressee);
595
597
if (addressee_asset_id == asset_id) {
596
- required_total += add_tx_addressee (session, net_params, result, tx, addressee);
598
+ const auto amount = add_tx_addressee (session, net_params, result, tx, addressee);
599
+ if (!json_get_value (addressee, " is_change" , false )) {
600
+ required_total += amount;
601
+ } else {
602
+ if (explicit_change_index != NO_CHANGE_INDEX) {
603
+ set_tx_error (result, " Only one explicit change addressee allowed" );
604
+ break ;
605
+ }
606
+ explicit_change_index = addressee_index;
607
+ }
597
608
reordered_addressees.push_back (addressee);
598
609
}
610
+ ++addressee_index;
599
611
}
600
612
}
613
+ result[" change_type" ][asset_id] = explicit_change_index == NO_CHANGE_INDEX ? " generated" : " explicit" ;
601
614
602
615
// TODO: filter per asset or assume always single asset
603
616
if (manual_selection) {
@@ -734,11 +747,7 @@ namespace sdk {
734
747
// so compute what we can send (everything minus the
735
748
// fee) and exit the loop
736
749
required_total = available_total - fee;
737
- if (is_liquid) {
738
- set_tx_output_commitment (tx, 0 , asset_id, required_total.value ());
739
- } else {
740
- tx->outputs [0 ].satoshi = required_total.value ();
741
- }
750
+ set_tx_output_value (net_params, tx, 0 , asset_id, required_total.value ());
742
751
if (num_addressees == 1u ) {
743
752
addressees_p->at (0 )[" satoshi" ] = required_total.value ();
744
753
}
@@ -794,17 +803,30 @@ namespace sdk {
794
803
continue ;
795
804
}
796
805
797
- // We have more than the dust amount of change. Add a change
798
- // output to collect it, then loop again in case the amount
799
- // this increases the fee by requires more UTXOs.
800
- const auto change_address = result.at (" change_address" ).at (asset_id).at (" address" );
801
- add_tx_output (net_params, result, tx, change_address, is_liquid ? 1 : 0 , asset_id);
802
- have_change_output = true ;
803
- change_index = tx->num_outputs - 1 ;
804
- if (is_liquid && include_fee) {
805
- std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
806
- std::swap (fee_index, change_index);
806
+ // We have more than the dust amount of change. First look for an explicit change
807
+ // output in the addressees and if present send the change there
808
+ amount::value_type change_amount = (total - required_total - fee).value ();
809
+
810
+ if (explicit_change_index == NO_CHANGE_INDEX) {
811
+ // No explicit change output specified, add a change output using the generated change
812
+ // address
813
+ add_tx_output (net_params, result, tx, result.at (" change_address" ).at (asset_id).at (" address" ),
814
+ is_liquid ? 1 : 0 , asset_id == " btc" ? std::string{} : asset_id);
815
+ have_change_output = true ;
816
+ change_index = tx->num_outputs - 1 ;
817
+ if (is_liquid && include_fee) {
818
+ std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
819
+ std::swap (fee_index, change_index);
820
+ }
821
+ } else {
822
+ // Use explicit change output
823
+ set_tx_output_value (net_params, tx, explicit_change_index, asset_id, change_amount);
824
+ auto addressees = *addressees_p;
825
+ addressees[explicit_change_index][" satoshi" ] = change_amount;
826
+ change_index = explicit_change_index;
827
+ have_change_output = true ;
807
828
}
829
+
808
830
result[" have_change" ][asset_id] = have_change_output;
809
831
result[" change_index" ][asset_id] = change_index;
810
832
}
@@ -826,11 +848,13 @@ namespace sdk {
826
848
} else {
827
849
auto & change_output = tx->outputs [change_index];
828
850
change_output.satoshi = change_amount;
829
- const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
830
- // Randomize change output
831
- if (change_index != new_change_index) {
832
- std::swap (tx->outputs [new_change_index], change_output);
833
- change_index = new_change_index;
851
+ if (explicit_change_index == NO_CHANGE_INDEX) {
852
+ // Randomize change output for non-explicit change
853
+ const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
854
+ if (change_index != new_change_index) {
855
+ std::swap (tx->outputs [new_change_index], change_output);
856
+ change_index = new_change_index;
857
+ }
834
858
}
835
859
}
836
860
}
0 commit comments