v30.3-roots.1 · Commit 24: [PATCH 24/68] feat(qt): add guarded private key sweep dialog
src/wallet/interfaces.cpp
Before: src/wallet/interfaces.cpp · After: src/wallet/interfaces.cpp
File metadata
index 2f5ce24e3bba68a2da0a00578fdbbf6dedc51664..fe27c0b897c33dd2f5b51857fd891cacd66c0c4e 100644
Download original patch · Release notes
Diff rows 1–65 of 65. 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/interfaces.cpp
CHANGED
|
@@ -29,6 +29,10 @@
|
|
| 29 |
#include <wallet/spend.h>
|
| 30 |
#include <wallet/wallet.h>
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
#include <memory>
|
| 33 |
#include <string>
|
| 34 |
#include <utility>
|
|
@@ -45,6 +49,7 @@ using interfaces::WalletBalances;
|
|
| 45 |
using interfaces::WalletLoader;
|
| 46 |
using interfaces::WalletMigrationResult;
|
| 47 |
using interfaces::WalletOrderForm;
|
|
|
|
| 48 |
using interfaces::WalletTx;
|
| 49 |
using interfaces::WalletTxOut;
|
| 50 |
using interfaces::WalletTxStatus;
|
|
@@ -174,6 +179,48 @@ public:
|
|
| 174 |
LOCK(m_wallet->cs_wallet);
|
| 175 |
return m_wallet->IsMine(dest);
|
| 176 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
|
| 178 |
{
|
| 179 |
return m_wallet->SetAddressBook(dest, name, purpose);
|
|
|
|
| 29 |
#include <wallet/spend.h>
|
| 30 |
#include <wallet/wallet.h>
|
| 31 |
|
| 32 |
+
#include <key_io.h>
|
| 33 |
+
#include <script/solver.h>
|
| 34 |
+
#include <policy/policy.h>
|
| 35 |
+
|
| 36 |
#include <memory>
|
| 37 |
#include <string>
|
| 38 |
#include <utility>
|
|
|
|
| 49 |
using interfaces::WalletLoader;
|
| 50 |
using interfaces::WalletMigrationResult;
|
| 51 |
using interfaces::WalletOrderForm;
|
| 52 |
+
using interfaces::WalletSweepResult;
|
| 53 |
using interfaces::WalletTx;
|
| 54 |
using interfaces::WalletTxOut;
|
| 55 |
using interfaces::WalletTxStatus;
|
|
|
|
| 179 |
LOCK(m_wallet->cs_wallet);
|
| 180 |
return m_wallet->IsMine(dest);
|
| 181 |
}
|
| 182 |
+
util::Result<WalletSweepResult> sweepPrivateKey(const SecureString& private_key,
|
| 183 |
+
const CTxDestination& destination,
|
| 184 |
+
bool broadcast,
|
| 185 |
+
const std::optional<Txid>& expected_txid) override
|
| 186 |
+
{
|
| 187 |
+
CKey key{DecodeSecret(std::string{private_key.begin(), private_key.end()})};
|
| 188 |
+
if (!key.IsValid()) return util::Error{Untranslated("Invalid private key or wrong network")};
|
| 189 |
+
const CPubKey pubkey{key.GetPubKey()};
|
| 190 |
+
FlatSigningProvider provider;
|
| 191 |
+
provider.keys.emplace(pubkey.GetID(), key);
|
| 192 |
+
provider.pubkeys.emplace(pubkey.GetID(), pubkey);
|
| 193 |
+
std::set<CScript> scan_objects{GetScriptForDestination(PKHash(pubkey))};
|
| 194 |
+
if (pubkey.IsCompressed()) {
|
| 195 |
+
const CScript witness{GetScriptForDestination(WitnessV0KeyHash(pubkey))};
|
| 196 |
+
scan_objects.insert(witness);
|
| 197 |
+
provider.scripts.emplace(CScriptID(witness), witness);
|
| 198 |
+
scan_objects.insert(GetScriptForDestination(ScriptHash(witness)));
|
| 199 |
+
}
|
| 200 |
+
const CScript destination_script{GetScriptForDestination(destination)};
|
| 201 |
+
{
|
| 202 |
+
LOCK(m_wallet->cs_wallet);
|
| 203 |
+
if (m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) || !m_wallet->IsMine(destination_script)) {
|
| 204 |
+
return util::Error{Untranslated("Destination is not controlled by this wallet")};
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
std::map<COutPoint, Coin> coins;
|
| 208 |
+
switch (m_wallet->chain().findScriptPubKeys(scan_objects, coins)) {
|
| 209 |
+
case interfaces::ScanResult::SUCCESS: break;
|
| 210 |
+
case interfaces::ScanResult::BUSY: return util::Error{Untranslated("UTXO scan already in progress")};
|
| 211 |
+
case interfaces::ScanResult::ABORTED: return util::Error{Untranslated("UTXO scan aborted")};
|
| 212 |
+
case interfaces::ScanResult::UNAVAILABLE: return util::Error{Untranslated("UTXO scan unavailable")};
|
| 213 |
+
}
|
| 214 |
+
auto swept{CreateSweepTransaction(*m_wallet, provider, coins, destination_script, broadcast ? SweepBroadcastFn{[&, expected_txid](const CTransactionRef& tx, std::string& error) {
|
| 215 |
+
if (expected_txid && tx->GetHash() != *expected_txid) {
|
| 216 |
+
error = "Sweep preview is stale; create a fresh preview";
|
| 217 |
+
return false;
|
| 218 |
+
}
|
| 219 |
+
return m_wallet->chain().broadcastTransaction(tx, m_wallet->m_default_max_tx_fee, /*relay=*/true, error);
|
| 220 |
+
}} : SweepBroadcastFn{})};
|
| 221 |
+
if (!swept) return util::Error{util::ErrorString(swept)};
|
| 222 |
+
return WalletSweepResult{swept->tx, swept->amount, swept->fee, coins.size(), GetVirtualTransactionSize(*swept->tx), broadcast};
|
| 223 |
+
}
|
| 224 |
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
|
| 225 |
{
|
| 226 |
return m_wallet->SetAddressBook(dest, name, purpose);
|