@@ -607,14 +607,27 @@ namespace sdk {
607
607
// Add all outputs and compute the total amount of satoshi to be sent
608
608
amount required_total{ 0 };
609
609
610
+ uint32_t explicit_change_index = NO_CHANGE_INDEX;
611
+
610
612
if (num_addressees) {
613
+ size_t addressee_index = 0 ;
611
614
for (auto & addressee : *addressees_p) {
612
615
const auto addressee_asset_tag
613
616
= session.asset_id_from_string (addressee.value (" asset_tag" , std::string{}));
614
617
if (addressee_asset_tag == asset_tag) {
615
- required_total += add_tx_addressee (session, net_params, result, tx, addressee);
618
+ const auto amount = add_tx_addressee (session, net_params, result, tx, addressee);
619
+ if (!json_get_value (addressee, " is_change" , false )) {
620
+ required_total += amount;
621
+ } else {
622
+ if (explicit_change_index != NO_CHANGE_INDEX) {
623
+ set_tx_error (result, " Only one explicit change addressee allowed" );
624
+ break ;
625
+ }
626
+ explicit_change_index = addressee_index;
627
+ }
616
628
reordered_addressees.push_back (addressee);
617
629
}
630
+ ++addressee_index;
618
631
}
619
632
}
620
633
@@ -749,11 +762,7 @@ namespace sdk {
749
762
// so compute what we can send (everything minus the
750
763
// fee) and exit the loop
751
764
required_total = available_total - fee;
752
- if (is_liquid) {
753
- set_tx_output_commitment (net_params, tx, 0 , asset_tag, required_total.value ());
754
- } else {
755
- tx->outputs [0 ].satoshi = required_total.value ();
756
- }
765
+ set_tx_output_value (net_params, tx, 0 , asset_tag, required_total.value ());
757
766
if (num_addressees == 1u ) {
758
767
addressees_p->at (0 )[" satoshi" ] = required_total.value ();
759
768
}
@@ -809,17 +818,30 @@ namespace sdk {
809
818
continue ;
810
819
}
811
820
812
- // We have more than the dust amount of change. Add a change
813
- // output to collect it, then loop again in case the amount
814
- // this increases the fee by requires more UTXOs.
815
- add_tx_output (net_params, result, tx, result.at (" change_address" ).at (asset_tag).at (" address" ),
816
- is_liquid ? 1 : 0 , asset_tag == " btc" ? std::string{} : asset_tag);
817
- have_change_output = true ;
818
- change_index = tx->num_outputs - 1 ;
819
- if (is_liquid && include_fee) {
820
- std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
821
- std::swap (fee_index, change_index);
821
+ // We have more than the dust amount of change. First look for an explicit change
822
+ // output in the addressees and if present send the change there
823
+ amount::value_type change_amount = (total - required_total - fee).value ();
824
+
825
+ if (explicit_change_index == NO_CHANGE_INDEX) {
826
+ // No explicit change output specified, add a change output using the generated change
827
+ // address
828
+ add_tx_output (net_params, result, tx, result.at (" change_address" ).at (asset_tag).at (" address" ),
829
+ is_liquid ? 1 : 0 , asset_tag == " btc" ? std::string{} : asset_tag);
830
+ have_change_output = true ;
831
+ change_index = tx->num_outputs - 1 ;
832
+ if (is_liquid && include_fee) {
833
+ std::swap (tx->outputs [fee_index], tx->outputs [change_index]);
834
+ std::swap (fee_index, change_index);
835
+ }
836
+ } else {
837
+ // Use explicit change output
838
+ set_tx_output_value (net_params, tx, explicit_change_index, asset_tag, change_amount);
839
+ auto addressees = *addressees_p;
840
+ addressees[explicit_change_index][" satoshi" ] = change_amount;
841
+ change_index = explicit_change_index;
842
+ have_change_output = true ;
822
843
}
844
+
823
845
result[" have_change" ][asset_tag] = have_change_output;
824
846
result[" change_index" ][asset_tag] = change_index;
825
847
}
@@ -841,11 +863,13 @@ namespace sdk {
841
863
} else {
842
864
auto & change_output = tx->outputs [change_index];
843
865
change_output.satoshi = change_amount;
844
- const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
845
- // Randomize change output
846
- if (change_index != new_change_index) {
847
- std::swap (tx->outputs [new_change_index], change_output);
848
- change_index = new_change_index;
866
+ if (explicit_change_index == NO_CHANGE_INDEX) {
867
+ // Randomize change output for non-explicit change
868
+ const uint32_t new_change_index = get_uniform_uint32_t (tx->num_outputs );
869
+ if (change_index != new_change_index) {
870
+ std::swap (tx->outputs [new_change_index], change_output);
871
+ change_index = new_change_index;
872
+ }
849
873
}
850
874
}
851
875
}
0 commit comments