aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wallet/spend.cpp40
1 files changed, 23 insertions, 17 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index c16b8a9d4f..0a59353052 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -983,6 +983,16 @@ static void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng
}
}
+size_t GetSerializeSizeForRecipient(const CRecipient& recipient)
+{
+ return ::GetSerializeSize(CTxOut(recipient.nAmount, GetScriptForDestination(recipient.dest)));
+}
+
+bool IsDust(const CRecipient& recipient, const CFeeRate& dustRelayFee)
+{
+ return ::IsDust(CTxOut(recipient.nAmount, GetScriptForDestination(recipient.dest)), dustRelayFee);
+}
+
static util::Result<CreatedTransactionResult> CreateTransactionInternal(
CWallet& wallet,
const std::vector<CRecipient>& vecSend,
@@ -1005,12 +1015,20 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
// Set the long term feerate estimate to the wallet's consolidate feerate
coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate;
+ // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
+ coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count
CAmount recipients_sum = 0;
const OutputType change_type = wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : wallet.m_default_change_type, vecSend);
ReserveDestination reservedest(&wallet, change_type);
unsigned int outputs_to_subtract_fee_from = 0; // The number of outputs which we are subtracting the fee from
for (const auto& recipient : vecSend) {
+ if (IsDust(recipient, wallet.chain().relayDustFee())) {
+ return util::Error{_("Transaction amount too small")};
+ }
+
+ // Include the fee cost for outputs.
+ coin_selection_params.tx_noinputs_size += GetSerializeSizeForRecipient(recipient);
recipients_sum += recipient.nAmount;
if (recipient.fSubtractFeeFromAmount) {
@@ -1095,23 +1113,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
- // Static vsize overhead + outputs vsize. 4 version, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
- coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count
-
- // vouts to the payees
- for (const auto& recipient : vecSend)
- {
- CTxOut txout(recipient.nAmount, GetScriptForDestination(recipient.dest));
-
- // Include the fee cost for outputs.
- coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout);
-
- if (IsDust(txout, wallet.chain().relayDustFee())) {
- return util::Error{_("Transaction amount too small")};
- }
- txNew.vout.push_back(txout);
- }
-
// Include the fees for things that aren't inputs, excluding the change output
const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.m_subtract_fee_outputs ? 0 : coin_selection_params.tx_noinputs_size);
CAmount selection_target = recipients_sum + not_input_fees;
@@ -1152,6 +1153,11 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
result.GetWaste(),
result.GetSelectedValue());
+ // vouts to the payees
+ for (const auto& recipient : vecSend)
+ {
+ txNew.vout.emplace_back(recipient.nAmount, GetScriptForDestination(recipient.dest));
+ }
const CAmount change_amount = result.GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
if (change_amount > 0) {
CTxOut newTxOut(change_amount, scriptChange);