@@ -614,15 +614,28 @@ namespace sdk {
614
614
// Add all outputs and compute the total amount of satoshi to be sent
615
615
amount required_total{ 0 };
616
616
617
+ uint32_t explicit_change_index = NO_CHANGE_INDEX;
617
618
if (num_addressees) {
619
+ size_t addressee_index = 0 ;
618
620
for (auto & addressee : *addressees_p) {
619
621
const auto addressee_asset_id = asset_id_from_json (net_params, addressee);
620
622
if (addressee_asset_id == asset_id) {
621
- required_total += add_tx_addressee (session, net_params, result, tx, addressee);
623
+ const auto amount = add_tx_addressee (session, net_params, result, tx, addressee);
624
+ if (!json_get_value (addressee, " is_change" , false )) {
625
+ required_total += amount;
626
+ } else {
627
+ if (explicit_change_index != NO_CHANGE_INDEX) {
628
+ set_tx_error (result, " Only one explicit change addressee allowed" );
629
+ break ;
630
+ }
631
+ explicit_change_index = addressee_index;
632
+ }
622
633
reordered_addressees.push_back (addressee);
623
634
}
635
+ ++addressee_index;
624
636
}
625
637
}
638
+ result[" change_type" ][asset_id] = explicit_change_index == NO_CHANGE_INDEX ? " generated" : " explicit" ;
626
639
627
640
// TODO: filter per asset or assume always single asset
628
641
if (manual_selection) {
@@ -758,11 +771,7 @@ namespace sdk {
758
771
// so compute what we can send (everything minus the
759
772
// fee) and exit the loop
760
773
required_total = available_total - fee;
761
- if (is_liquid) {
762
- set_tx_output_commitment (net_params, tx, 0 , asset_id, required_total.value ());
763
- } else {
764
- tx->outputs [0 ].satoshi = required_total.value ();
765
- }
774
+ set_tx_output_value (net_params, tx, 0 , asset_id, required_total.value ());
766
775
if (num_addressees == 1u ) {
767
776
addressees_p->at (0 )[" satoshi" ] = required_total.value ();
768
777
}
@@ -818,17 +827,30 @@ namespace sdk {
818
827
continue ;
819
828
}
820
829
821
- // We have more than the dust amount of change. Add a change
822
- // output to collect it, then loop again in case the amount
823
- // this increases the fee by requires more UTXOs.
824
- add_tx_output (net_params, result, tx, result.at (" change_address" ).at (asset_id).at (" address" ),
825
- is_liquid ? 1 : 0 , asset_id == " btc" ? std::string{} : asset_id);
826
- have_change_output = true ;
827
- change_index = tx->num_outputs - 1 ;
828
- if (is_liquid && include_fee) {
829
- std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
830
- std::swap (fee_index, change_index);
830
+ // We have more than the dust amount of change. First look for an explicit change
831
+ // output in the addressees and if present send the change there
832
+ amount::value_type change_amount = (total - required_total - fee).value ();
833
+
834
+ if (explicit_change_index == NO_CHANGE_INDEX) {
835
+ // No explicit change output specified, add a change output using the generated change
836
+ // address
837
+ add_tx_output (net_params, result, tx, result.at (" change_address" ).at (asset_id).at (" address" ),
838
+ is_liquid ? 1 : 0 , asset_id == " btc" ? std::string{} : asset_id);
839
+ have_change_output = true ;
840
+ change_index = tx->num_outputs - 1 ;
841
+ if (is_liquid && include_fee) {
842
+ std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
843
+ std::swap (fee_index, change_index);
844
+ }
845
+ } else {
846
+ // Use explicit change output
847
+ set_tx_output_value (net_params, tx, explicit_change_index, asset_id, change_amount);
848
+ auto addressees = *addressees_p;
849
+ addressees[explicit_change_index][" satoshi" ] = change_amount;
850
+ change_index = explicit_change_index;
851
+ have_change_output = true ;
831
852
}
853
+
832
854
result[" have_change" ][asset_id] = have_change_output;
833
855
result[" change_index" ][asset_id] = change_index;
834
856
}
@@ -850,11 +872,13 @@ namespace sdk {
850
872
} else {
851
873
auto & change_output = tx->outputs [change_index];
852
874
change_output.satoshi = change_amount;
853
- const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
854
- // Randomize change output
855
- if (change_index != new_change_index) {
856
- std::swap (tx->outputs [new_change_index], change_output);
857
- change_index = new_change_index;
875
+ if (explicit_change_index == NO_CHANGE_INDEX) {
876
+ // Randomize change output for non-explicit change
877
+ const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
878
+ if (change_index != new_change_index) {
879
+ std::swap (tx->outputs [new_change_index], change_output);
880
+ change_index = new_change_index;
881
+ }
858
882
}
859
883
}
860
884
}
0 commit comments