v29.4-roots.3 · Commit 23: [PATCH 23/30] feat(wallet): add transient private-key sweep RPC
src/wallet/spend.cpp
Before: src/wallet/spend.cpp · After: src/wallet/spend.cpp
File metadata
index 665e6c92a5b067eb381ba4a0cfd3a55ef5b2abbf..8d77de3cc7fcde543d596ea40a31e9cda8b4182a 100644
Download original patch · Release notes
Diff rows 1–47 of 47. 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
|
@@ -13,6 +13,7 @@
|
|
| 13 |
#include <numeric>
|
| 14 |
#include <policy/policy.h>
|
| 15 |
#include <primitives/transaction.h>
|
|
|
|
| 16 |
#include <script/script.h>
|
| 17 |
#include <script/signingprovider.h>
|
| 18 |
#include <script/solver.h>
|
|
@@ -41,6 +42,40 @@ TRACEPOINT_SEMAPHORE(coin_selection, attempting_aps_create_tx);
|
|
| 41 |
TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
|
| 42 |
|
| 43 |
namespace wallet {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
|
| 45 |
|
| 46 |
/** Whether the descriptor represents, directly or not, a witness program. */
|
|
|
|
| 13 |
#include <numeric>
|
| 14 |
#include <policy/policy.h>
|
| 15 |
#include <primitives/transaction.h>
|
| 16 |
+
#include <rpc/rawtransaction_util.h>
|
| 17 |
#include <script/script.h>
|
| 18 |
#include <script/signingprovider.h>
|
| 19 |
#include <script/solver.h>
|
|
|
|
| 42 |
TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);
|
| 43 |
|
| 44 |
namespace wallet {
|
| 45 |
+
util::Result<SweepTransactionResult> CreateSweepTransaction(CWallet& wallet, FlatSigningProvider& provider,
|
| 46 |
+
const std::map<COutPoint, Coin>& coins,
|
| 47 |
+
const CScript& destination, const SweepBroadcastFn& broadcast)
|
| 48 |
+
{
|
| 49 |
+
CAmount amount{0};
|
| 50 |
+
CMutableTransaction tx;
|
| 51 |
+
for (const auto& [outpoint, coin] : coins) {
|
| 52 |
+
amount += coin.out.nValue;
|
| 53 |
+
tx.vin.emplace_back(outpoint);
|
| 54 |
+
}
|
| 55 |
+
if (coins.empty()) return util::Error{Untranslated("No spendable UTXOs found")};
|
| 56 |
+
tx.vout.emplace_back(amount, destination);
|
| 57 |
+
std::map<int, bilingual_str> errors;
|
| 58 |
+
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
| 59 |
+
CAmount fee{0};
|
| 60 |
+
for (int attempts{0}; attempts < 10; ++attempts) {
|
| 61 |
+
fee = GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr);
|
| 62 |
+
if (fee >= amount) return util::Error{Untranslated("Fee exceeds swept value")};
|
| 63 |
+
tx.vout[0].nValue = amount - fee;
|
| 64 |
+
errors.clear();
|
| 65 |
+
if (!::SignTransaction(tx, &provider, coins, SIGHASH_DEFAULT, errors)) return util::Error{Untranslated("Unable to sign all swept inputs")};
|
| 66 |
+
if (fee >= GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr)) break;
|
| 67 |
+
}
|
| 68 |
+
if (fee < GetMinimumFee(wallet, GetVirtualTransactionSize(CTransaction{tx}), CCoinControl{}, nullptr)) {
|
| 69 |
+
return util::Error{Untranslated("Unable to calculate a stable sweep fee")};
|
| 70 |
+
}
|
| 71 |
+
if (IsDust(tx.vout[0], wallet.chain().relayMinFee())) return util::Error{Untranslated("Swept output would be dust")};
|
| 72 |
+
CTransactionRef final_tx{MakeTransactionRef(tx)};
|
| 73 |
+
if (broadcast) {
|
| 74 |
+
std::string error;
|
| 75 |
+
if (!broadcast(final_tx, error)) return util::Error{Untranslated("Sweep transaction broadcast failed: " + error)};
|
| 76 |
+
}
|
| 77 |
+
return SweepTransactionResult{final_tx, amount, fee};
|
| 78 |
+
}
|
| 79 |
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
|
| 80 |
|
| 81 |
/** Whether the descriptor represents, directly or not, a witness program. */
|