v30.3-roots.1 · Commit 49: [PATCH 49/68] wallet: snapshot sweep fee settings under lock
src/wallet/spend.cpp
Before: src/wallet/spend.cpp · After: src/wallet/spend.cpp
File metadata
index 587575b2d2c582aef54b8a865918fe32995bdc5d..8e1788be94d3e4f523ee61092f0a07afc05d5d0b 100644
Download original patch · Release notes
Diff rows 1–31 of 31. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/wallet/spend.cpp
CHANGED
|
@@ -45,7 +45,7 @@ TRACEPOINT_SEMAPHORE(coin_selection, attempting_aps_create_tx);
|
|
| 45 |
TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
|
| 46 |
|
| 47 |
namespace wallet {
|
| 48 |
-
util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, FlatSigningProvider& provider,
|
| 49 |
const std::map<COutPoint, Coin>& coins,
|
| 50 |
const CScript& destination, const SweepBroadcastFn& broadcast,
|
| 51 |
interfaces::SweepAuthorization& authorization)
|
|
@@ -61,16 +61,20 @@ util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, Fla
|
|
| 61 |
tx.vout.emplace_back(amount, destination);
|
| 62 |
std::map<int, bilingual_str> errors;
|
| 63 |
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
CAmount fee{0};
|
| 65 |
for (int attempts{0}; attempts < 10; ++attempts) {
|
| 66 |
-
fee = GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr);
|
| 67 |
if (fee >= amount) return util::Error{Untranslated("Fee exceeds swept value")};
|
| 68 |
tx.vout[0].nValue = amount - fee;
|
| 69 |
errors.clear();
|
| 70 |
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
| 71 |
-
if (fee >= GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr)) break;
|
| 72 |
}
|
| 73 |
-
if (fee < GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr)) {
|
| 74 |
return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
|
| 75 |
}
|
| 76 |
if (IsDust(tx.vout[0], wallet.chain().relayMinFee())) return util::Error{Untranslated("Swept output would be dust")};
|
|
|
|
| 45 |
TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
|
| 46 |
|
| 47 |
namespace wallet {
|
| 48 |
+
util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, const SigningProvider& provider,
|
| 49 |
const std::map<COutPoint, Coin>& coins,
|
| 50 |
const CScript& destination, const SweepBroadcastFn& broadcast,
|
| 51 |
interfaces::SweepAuthorization& authorization)
|
|
|
|
| 61 |
tx.vout.emplace_back(amount, destination);
|
| 62 |
std::map<int, bilingual_str> errors;
|
| 63 |
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
| 64 |
+
// Fee settings can change while the UTXO scan runs. Take one synchronized
|
| 65 |
+
// snapshot for every signing iteration without holding the wallet lock
|
| 66 |
+
// during signing or broadcast.
|
| 67 |
+
const CFeeRate fee_rate{WITH_LOCK(wallet.cs_wallet, return GetMinimumFeeRate(wallet, CCoinControl{}, nullptr))};
|
| 68 |
CAmount fee{0};
|
| 69 |
for (int attempts{0}; attempts < 10; ++attempts) {
|
| 70 |
+
fee = fee_rate.GetFee(GetVirtualTransactionSize(CTransaction{tx}));
|
| 71 |
if (fee >= amount) return util::Error{Untranslated("Fee exceeds swept value")};
|
| 72 |
tx.vout[0].nValue = amount - fee;
|
| 73 |
errors.clear();
|
| 74 |
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
| 75 |
+
if (fee >= fee_rate.GetFee(GetVirtualTransactionSize(CTransaction{tx}))) break;
|
| 76 |
}
|
| 77 |
+
if (fee < fee_rate.GetFee(GetVirtualTransactionSize(CTransaction{tx}))) {
|
| 78 |
return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
|
| 79 |
}
|
| 80 |
if (IsDust(tx.vout[0], wallet.chain().relayMinFee())) return util::Error{Untranslated("Swept output would be dust")};
|