@@ -61,7 +61,7 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
61
61
}
62
62
63
63
// ! Check if the user provided a valid feeRate
64
- static feebumper::Result CheckFeeRate (const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<bilingual_str>& errors)
64
+ static feebumper::Result CheckFeeRate (const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, CAmount old_fee, std::vector<bilingual_str>& errors)
65
65
{
66
66
// check that fee rate is higher than mempool's minimum fee
67
67
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
@@ -83,8 +83,6 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
83
83
CFeeRate incrementalRelayFee = std::max (wallet.chain ().relayIncrementalFee (), CFeeRate (WALLET_INCREMENTAL_RELAY_FEE));
84
84
85
85
// Given old total fee and transaction size, calculate the old feeRate
86
- isminefilter filter = wallet.GetLegacyScriptPubKeyMan () && wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
87
- CAmount old_fee = CachedTxGetDebit (wallet, wtx, filter) - wtx.tx ->GetValueOut ();
88
86
const int64_t txSize = GetVirtualTransactionSize (*(wtx.tx ));
89
87
CFeeRate nOldFeeRate (old_fee, txSize);
90
88
// Min total fee is old fee + relay fee
@@ -169,13 +167,37 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
169
167
}
170
168
const CWalletTx& wtx = it->second ;
171
169
170
+ // Retrieve all of the UTXOs and add them to coin control
171
+ // While we're here, calculate the input amount
172
+ std::map<COutPoint, Coin> coins;
173
+ CAmount input_value = 0 ;
174
+ for (const CTxIn& txin : wtx.tx ->vin ) {
175
+ coins[txin.prevout ]; // Create empty map entry keyed by prevout.
176
+ }
177
+ wallet.chain ().findCoins (coins);
178
+ for (const CTxIn& txin : wtx.tx ->vin ) {
179
+ const Coin& coin = coins.at (txin.prevout );
180
+ if (coin.out .IsNull ()) {
181
+ errors.push_back (Untranslated (strprintf (" %s:%u is already spent" , txin.prevout .hash .GetHex (), txin.prevout .n )));
182
+ return Result::MISC_ERROR;
183
+ }
184
+ if (wallet.IsMine (txin.prevout )) {
185
+ new_coin_control.Select (txin.prevout );
186
+ } else {
187
+ new_coin_control.SelectExternal (txin.prevout , coin.out );
188
+ }
189
+ input_value += coin.out .nValue ;
190
+ }
191
+
172
192
Result result = PreconditionChecks (wallet, wtx, errors);
173
193
if (result != Result::OK) {
174
194
return result;
175
195
}
176
196
177
197
// Fill in recipients(and preserve a single change key if there is one)
198
+ // While we're here, calculate the output amount
178
199
std::vector<CRecipient> recipients;
200
+ CAmount output_value = 0 ;
179
201
for (const auto & output : wtx.tx ->vout ) {
180
202
if (!OutputIsChange (wallet, output)) {
181
203
CRecipient recipient = {output.scriptPubKey , output.nValue , false };
@@ -185,16 +207,16 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
185
207
ExtractDestination (output.scriptPubKey , change_dest);
186
208
new_coin_control.destChange = change_dest;
187
209
}
210
+ output_value += output.nValue ;
188
211
}
189
212
190
- isminefilter filter = wallet.GetLegacyScriptPubKeyMan () && wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
191
- old_fee = CachedTxGetDebit (wallet, wtx, filter) - wtx.tx ->GetValueOut ();
213
+ old_fee = input_value - output_value;
192
214
193
215
if (coin_control.m_feerate ) {
194
216
// The user provided a feeRate argument.
195
217
// We calculate this here to avoid compiler warning on the cs_wallet lock
196
- const int64_t maxTxSize{CalculateMaximumSignedTxSize (*wtx.tx , &wallet).vsize };
197
- Result res = CheckFeeRate (wallet, wtx, *new_coin_control.m_feerate , maxTxSize, errors);
218
+ const int64_t maxTxSize{CalculateMaximumSignedTxSize (*wtx.tx , &wallet, &new_coin_control ).vsize };
219
+ Result res = CheckFeeRate (wallet, wtx, *new_coin_control.m_feerate , maxTxSize, old_fee, errors);
198
220
if (res != Result::OK) {
199
221
return res;
200
222
}
0 commit comments