From 3a1156fb7d6a52df55588600d4c2b05ff9f7bf46 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 1 Nov 2021 13:27:40 +0000 Subject: [PATCH 1/2] Refactor set_tx_output_value --- src/ga_tx.cpp | 6 +----- src/transaction_utils.cpp | 10 ++++++++++ src/transaction_utils.hpp | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ga_tx.cpp b/src/ga_tx.cpp index 472ded521..c7d578d48 100644 --- a/src/ga_tx.cpp +++ b/src/ga_tx.cpp @@ -716,11 +716,7 @@ namespace sdk { // so compute what we can send (everything minus the // fee) and exit the loop required_total = available_total - fee; - if (is_liquid) { - set_tx_output_commitment(tx, 0, asset_id, required_total.value()); - } else { - tx->outputs[0].satoshi = required_total.value(); - } + set_tx_output_value(net_params, tx, 0, asset_id, required_total.value()); if (num_addressees == 1u) { addressees_p->at(0)["satoshi"] = required_total.value(); } diff --git a/src/transaction_utils.cpp b/src/transaction_utils.cpp index 35252b3cc..78095f821 100644 --- a/src/transaction_utils.cpp +++ b/src/transaction_utils.cpp @@ -435,6 +435,16 @@ namespace sdk { asset_id_from_json(net_params, addressee)); } + void set_tx_output_value(const network_parameters& net_params, wally_tx_ptr& tx, uint32_t index, + const std::string& asset_id, amount::value_type satoshi) + { + if (net_params.is_liquid()) { + set_tx_output_commitment(tx, index, asset_id, satoshi); + } else { + tx->outputs[index].satoshi = satoshi; + } + } + void update_tx_size_info(const network_parameters& net_params, const wally_tx_ptr& tx, nlohmann::json& result) { const bool valid = tx->num_inputs != 0u && tx->num_outputs != 0u; diff --git a/src/transaction_utils.hpp b/src/transaction_utils.hpp index 7108af937..fbca5f210 100644 --- a/src/transaction_utils.hpp +++ b/src/transaction_utils.hpp @@ -92,6 +92,9 @@ namespace sdk { amount add_tx_addressee(ga_session& session, const network_parameters& net_params, nlohmann::json& result, wally_tx_ptr& tx, nlohmann::json& addressee); + void set_tx_output_value(const network_parameters& net_params, wally_tx_ptr& tx, uint32_t index, + const std::string& asset_id, amount::value_type satoshi); + vbf_t generate_final_vbf(byte_span_t input_abfs, byte_span_t input_vbfs, uint64_span_t input_values, const std::vector& output_abfs, const std::vector& output_vbfs, uint32_t num_inputs); From d74f723d76ec687853c46e6d8d36d5614c7407cf Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 15 Apr 2021 12:43:53 +0000 Subject: [PATCH 2/2] Support greedy addressees Setting the 'greedy' flag on an addressee means it will consume any change instead of it going to a change output. --- src/ga_tx.cpp | 14 ++++++++++++++ src/transaction_utils.cpp | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ga_tx.cpp b/src/ga_tx.cpp index c7d578d48..a5c82f5b9 100644 --- a/src/ga_tx.cpp +++ b/src/ga_tx.cpp @@ -572,14 +572,20 @@ namespace sdk { // Add all outputs and compute the total amount of satoshi to be sent amount required_total{ 0 }; + uint32_t greedy_index = NO_CHANGE_INDEX; if (num_addressees) { + int addressee_index = 0; for (auto& addressee : *addressees_p) { const auto addressee_asset_id = asset_id_from_json(net_params, addressee); if (addressee_asset_id == asset_id) { required_total += add_tx_addressee(session, net_params, result, tx, addressee); reordered_addressees.push_back(addressee); + if (addressee.value("is_greedy", false)) { + greedy_index = addressee_index; + } } + ++addressee_index; } } @@ -745,6 +751,14 @@ namespace sdk { change = total - required_with_fee; + if (change != 0 && greedy_index != NO_CHANGE_INDEX) { + // If a 'greedy' addressee exists send change there + set_tx_output_value(net_params, tx, greedy_index, asset_id, change.value()); + addressees_p->at(greedy_index)["satoshi"] = change.value(); + required_total += change; + continue; + } + if ((!have_change_output && change < dust_threshold) || (have_change_output && change >= dust_threshold)) { // We don't have a change output, and have only dust left over, or diff --git a/src/transaction_utils.cpp b/src/transaction_utils.cpp index 78095f821..509caf57b 100644 --- a/src/transaction_utils.cpp +++ b/src/transaction_utils.cpp @@ -424,7 +424,10 @@ namespace sdk { // Transactions with outputs below the dust threshold (except OP_RETURN) // are not relayed by network nodes - if (!result.value("send_all", false) && satoshi.value() < session.get_dust_threshold()) { + // This check only applies when the amount has been set explicitly, so send all + // and greedy outputs are ignored as the amount is calculated later + if (!result.value("send_all", false) && !addressee.value("is_greedy", false) + && satoshi.value() < session.get_dust_threshold()) { set_tx_error(result, res::id_invalid_amount); }