Skip to content

Commit a9c7300

Browse files
committed
move-only: refactor CreateTransactionInternal
Move the output serialization size and dust calculation into the loop where the outputs are iterated over to calculate the total sum. Move the code for adding the the txoutputs to the transaction to after coin selection. While this code structure generally follows a more logical flow, the primary motivation for moving the code for adding outputs to the transaction sets us up nicely for silent payments (in a future PR): we need to know the input set before generating the final output scriptPubKeys.
1 parent adc6ab2 commit a9c7300

File tree

1 file changed

+13
-17
lines changed

1 file changed

+13
-17
lines changed

src/wallet/spend.cpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,12 +1008,20 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
10081008

10091009
// Set the long term feerate estimate to the wallet's consolidate feerate
10101010
coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate;
1011+
// Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
1012+
coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count
10111013

10121014
CAmount recipients_sum = 0;
10131015
const OutputType change_type = wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : wallet.m_default_change_type, vecSend);
10141016
ReserveDestination reservedest(&wallet, change_type);
10151017
unsigned int outputs_to_subtract_fee_from = 0; // The number of outputs which we are subtracting the fee from
10161018
for (const auto& recipient : vecSend) {
1019+
if (IsDust(recipient, wallet.chain().relayDustFee())) {
1020+
return util::Error{_("Transaction amount too small")};
1021+
}
1022+
1023+
// Include the fee cost for outputs.
1024+
coin_selection_params.tx_noinputs_size += GetSerializeSizeForRecipient(recipient);
10171025
recipients_sum += recipient.nAmount;
10181026

10191027
if (recipient.fSubtractFeeFromAmount) {
@@ -1098,23 +1106,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
10981106
const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
10991107
coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
11001108

1101-
// Static vsize overhead + outputs vsize. 4 version, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
1102-
coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count
1103-
1104-
// vouts to the payees
1105-
for (const auto& recipient : vecSend)
1106-
{
1107-
CTxOut txout(recipient.nAmount, GetScriptForDestination(recipient.dest));
1108-
1109-
// Include the fee cost for outputs.
1110-
coin_selection_params.tx_noinputs_size += GetSerializeSizeForRecipient(recipient);
1111-
1112-
if (IsDust(recipient, wallet.chain().relayDustFee())) {
1113-
return util::Error{_("Transaction amount too small")};
1114-
}
1115-
txNew.vout.push_back(txout);
1116-
}
1117-
11181109
// Include the fees for things that aren't inputs, excluding the change output
11191110
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);
11201111
CAmount selection_target = recipients_sum + not_input_fees;
@@ -1155,6 +1146,11 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
11551146
result.GetWaste(),
11561147
result.GetSelectedValue());
11571148

1149+
// vouts to the payees
1150+
for (const auto& recipient : vecSend)
1151+
{
1152+
txNew.vout.emplace_back(recipient.nAmount, GetScriptForDestination(recipient.dest));
1153+
}
11581154
const CAmount change_amount = result.GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
11591155
if (change_amount > 0) {
11601156
CTxOut newTxOut(change_amount, scriptChange);

0 commit comments

Comments
 (0)