aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet.h')
-rw-r--r--src/wallet/wallet.h175
1 files changed, 123 insertions, 52 deletions
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a918bb8833..72b3cf1fb8 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -11,9 +11,12 @@
#include <interfaces/handler.h>
#include <outputtype.h>
#include <policy/feerate.h>
+#include <psbt.h>
#include <tinyformat.h>
#include <ui_interface.h>
+#include <util/message.h>
#include <util/strencodings.h>
+#include <util/string.h>
#include <util/system.h>
#include <validationinterface.h>
#include <wallet/coinselection.h>
@@ -108,7 +111,8 @@ static constexpr uint64_t KNOWN_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE
| WALLET_FLAG_BLANK_WALLET
| WALLET_FLAG_KEY_ORIGIN_METADATA
- | WALLET_FLAG_DISABLE_PRIVATE_KEYS;
+ | WALLET_FLAG_DISABLE_PRIVATE_KEYS
+ | WALLET_FLAG_DESCRIPTORS;
static constexpr uint64_t MUTABLE_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE;
@@ -118,6 +122,7 @@ static const std::map<std::string,WalletFlags> WALLET_FLAG_MAP{
{"blank", WALLET_FLAG_BLANK_WALLET},
{"key_origin_metadata", WALLET_FLAG_KEY_ORIGIN_METADATA},
{"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS},
+ {"descriptor_wallet", WALLET_FLAG_DESCRIPTORS},
};
extern const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS;
@@ -141,7 +146,7 @@ class ReserveDestination
{
protected:
//! The wallet to reserve from
- CWallet* const pwallet;
+ const CWallet* const pwallet;
//! The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called
ScriptPubKeyMan* m_spk_man{nullptr};
OutputType const type;
@@ -178,14 +183,23 @@ public:
/** Address book data */
class CAddressBookData
{
+private:
+ bool m_change{true};
+ std::string m_label;
public:
- std::string name;
std::string purpose;
CAddressBookData() : purpose("unknown") {}
typedef std::map<std::string, std::string> StringMap;
StringMap destdata;
+
+ bool IsChange() const { return m_change; }
+ const std::string& GetLabel() const { return m_label; }
+ void SetLabel(const std::string& label) {
+ m_change = false;
+ m_label = label;
+ }
};
struct CRecipient
@@ -213,7 +227,7 @@ static inline void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
{
if (nOrderPos == -1)
return;
- mapValue["n"] = i64tostr(nOrderPos);
+ mapValue["n"] = ToString(nOrderPos);
}
struct COutputEntry
@@ -485,8 +499,8 @@ public:
bool IsEquivalentTo(const CWalletTx& tx) const;
bool InMempool() const;
- bool IsTrusted(interfaces::Chain::Lock& locked_chain) const;
- bool IsTrusted(interfaces::Chain::Lock& locked_chain, std::set<uint256>& trusted_parents) const;
+ bool IsTrusted() const;
+ bool IsTrusted(std::set<uint256>& trusted_parents) const;
int64_t GetTxTime() const;
@@ -603,7 +617,7 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions
/**
* A CWallet maintains a set of transactions and balances, and provides the ability to create new transactions.
*/
-class CWallet final : public WalletStorage, private interfaces::Chain::Notifications
+class CWallet final : public WalletStorage, public interfaces::Chain::Notifications
{
private:
CKeyingMaterial vMasterKey GUARDED_BY(cs_wallet);
@@ -761,8 +775,8 @@ public:
bool IsLocked() const override;
bool Lock();
- /** Interface to assert chain access and if successful lock it */
- std::unique_ptr<interfaces::Chain::Lock> LockChain() { return m_chain ? m_chain->lock() : nullptr; }
+ /** Interface to assert chain access */
+ bool HaveChain() const { return m_chain ? true : false; }
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
@@ -772,16 +786,14 @@ public:
int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0;
uint64_t nAccountingEntryNumber = 0;
- std::map<CTxDestination, CAddressBookData> mapAddressBook GUARDED_BY(cs_wallet);
+ std::map<CTxDestination, CAddressBookData> m_address_book GUARDED_BY(cs_wallet);
+ const CAddressBookData* FindAddressBookEntry(const CTxDestination&, bool allow_change = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
/** Registered interfaces::Chain::Notifications handler. */
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
- /** Register the wallet for chain notifications */
- void handleNotifications();
-
/** Interface for accessing chain state. */
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
@@ -793,12 +805,12 @@ public:
/**
* populate vCoins with vector of available COutputs.
*/
- void AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<COutput>& vCoins, bool fOnlySafe = true, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe = true, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Return list of available coins and locked coins grouped by non-change output address.
*/
- std::map<CTxDestination, std::vector<COutput>> ListCoins(interfaces::Chain::Lock& locked_chain) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ std::map<CTxDestination, std::vector<COutput>> ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Find non-change parent output.
@@ -817,10 +829,10 @@ public:
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Whether this or any known UTXO with the same single key has been spent.
- bool IsUsedDestination(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void SetUsedDestinationState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool IsSpentKey(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const;
+ std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin, const size_t max_ancestors) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -832,8 +844,8 @@ public:
* Rescan abort properties
*/
void AbortRescan() { fAbortRescan = true; }
- bool IsAbortingRescan() { return fAbortRescan; }
- bool IsScanning() { return fScanningWallet; }
+ bool IsAbortingRescan() const { return fAbortRescan; }
+ bool IsScanning() const { return fScanningWallet; }
int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
@@ -842,7 +854,10 @@ public:
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
- //! Adds a destination data tuple to the store, and saves it to disk
+ /**
+ * Adds a destination data tuple to the store, and saves it to disk
+ * When adding new fields, take care to consider how DelAddressBook should handle it!
+ */
bool AddDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Erases a destination data tuple in the store and on disk
bool EraseDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -860,7 +875,7 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
- void GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
@@ -873,10 +888,10 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
void LoadToWallet(CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void TransactionAddedToMempool(const CTransactionRef& tx) override;
- void BlockConnected(const CBlock& block, const std::vector<CTransactionRef>& vtxConflicted, int height) override;
- void BlockDisconnected(const CBlock& block, int height) override;
- void UpdatedBlockTip() override;
+ void transactionAddedToMempool(const CTransactionRef& tx) override;
+ void blockConnected(const CBlock& block, int height) override;
+ void blockDisconnected(const CBlock& block, int height) override;
+ void updatedBlockTip() override;
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
struct ScanResult {
@@ -894,8 +909,8 @@ public:
//! USER_ABORT.
uint256 last_failed_block;
};
- ScanResult ScanForWalletTransactions(const uint256& first_block, const uint256& last_block, const WalletRescanReserver& reserver, bool fUpdate);
- void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
+ ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, Optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
+ void transactionRemovedFromMempool(const CTransactionRef &ptx) override;
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions();
struct Balance {
@@ -916,15 +931,37 @@ public:
* calling CreateTransaction();
*/
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
- bool SignTransaction(CMutableTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ // Fetch the inputs and sign with SIGHASH_ALL.
+ bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ // Sign the tx given the input coins and sighash.
+ bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
+ SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
+
+ /**
+ * Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
+ * them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
+ * (i.e. has all required signatures or signature-parts, and is ready to
+ * finalize.) Sets `error` and returns false if something goes wrong.
+ *
+ * @param[in] psbtx PartiallySignedTransaction to fill in
+ * @param[out] complete indicates whether the PSBT is now complete
+ * @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
+ * @param[in] sign whether to sign or not
+ * @param[in] bip32derivs whether to fill in bip32 derivation information if available
+ * return error
+ */
+ TransactionError FillPSBT(PartiallySignedTransaction& psbtx,
+ bool& complete,
+ int sighash_type = 1 /* SIGHASH_ALL */,
+ bool sign = true,
+ bool bip32derivs = true) const;
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut,
- std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
+ bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true);
/**
* Submit the transaction to the node's mempool and then relay to peers.
* Should be called after CreateTransaction unless you want to abort
@@ -968,13 +1005,13 @@ public:
/** Absolute maximum transaction fee (in satoshis) used by default for the wallet */
CAmount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
- size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
- int64_t GetOldestKeyPoolTime();
+ int64_t GetOldestKeyPoolTime() const;
- std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- std::map<CTxDestination, CAmount> GetAddressBalances(interfaces::Chain::Lock& locked_chain);
+ std::set<std::set<CTxDestination>> GetAddressGroupings() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ std::map<CTxDestination, CAmount> GetAddressBalances() const;
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
@@ -1008,7 +1045,7 @@ public:
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetChange(const CTransaction& tx) const;
- void ChainStateFlushed(const CBlockLocator& loc) override;
+ void chainStateFlushed(const CBlockLocator& loc) override;
DBErrors LoadWallet(bool& fFirstRunRet);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
@@ -1027,7 +1064,7 @@ public:
bool SetMaxVersion(int nVersion);
//! get the current wallet format (the oldest client version guaranteed to understand this wallet)
- int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
+ int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; }
//! Get wallet transactions that conflict with given transaction (spend same outputs)
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1098,13 +1135,13 @@ public:
*/
void postInitProcess();
- bool BackupWallet(const std::string& strDest);
+ bool BackupWallet(const std::string& strDest) const;
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
/* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
- bool CanGetAddresses(bool internal = false);
+ bool CanGetAddresses(bool internal = false) const;
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
@@ -1112,7 +1149,7 @@ public:
* Obviously holding cs_main/cs_wallet when going into this call may cause
* deadlock
*/
- void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_main, cs_wallet);
+ void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(cs_main, cs_wallet);
/** set a single wallet flag */
void SetWalletFlag(uint64_t flags);
@@ -1127,6 +1164,9 @@ public:
returns false if unknown, non-tolerable flags are present */
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly);
+ /** Determine if we are a legacy wallet */
+ bool IsLegacy() const;
+
/** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
const std::string GetDisplayName() const override {
std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
@@ -1139,6 +1179,9 @@ public:
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
};
+ /** Upgrade the wallet */
+ bool UpgradeWallet(int version, std::string& error, std::vector<std::string>& warnings);
+
//! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers
std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const;
@@ -1153,9 +1196,12 @@ public:
//! Get the ScriptPubKeyMan by id
ScriptPubKeyMan* GetScriptPubKeyMan(const uint256& id) const;
+ //! Get all of the ScriptPubKeyMans for a script given additional information in sigdata (populated by e.g. a psbt)
+ std::set<ScriptPubKeyMan*> GetScriptPubKeyMans(const CScript& script, SignatureData& sigdata) const;
+
//! Get the SigningProvider for a script
- std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const;
- std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script, SignatureData& sigdata) const;
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const;
+ std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script, SignatureData& sigdata) const;
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
@@ -1174,6 +1220,12 @@ public:
assert(m_last_block_processed_height >= 0);
return m_last_block_processed_height;
};
+ uint256 GetLastBlockHash() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
+ {
+ AssertLockHeld(cs_wallet);
+ assert(m_last_block_processed_height >= 0);
+ return m_last_block_processed;
+ }
/** Set last block processed height, currently only use in unit test */
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
{
@@ -1184,6 +1236,25 @@ public:
//! Connect the signals from ScriptPubKeyMans to the signals in CWallet
void ConnectScriptPubKeyManNotifiers();
+
+ //! Instantiate a descriptor ScriptPubKeyMan from the WalletDescriptor and load it
+ void LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc);
+
+ //! Sets the active ScriptPubKeyMan for the specified type and internal
+ //! @param[in] id The unique id for the ScriptPubKeyMan
+ //! @param[in] type The OutputType this ScriptPubKeyMan provides addresses for
+ //! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
+ //! @param[in] memonly Whether to record this update to the database. Set to true for wallet loading, normally false when actually updating the wallet.
+ void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly = false);
+
+ //! Create new DescriptorScriptPubKeyMans and add them to the wallet
+ void SetupDescriptorScriptPubKeyMans();
+
+ //! Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet
+ DescriptorScriptPubKeyMan* GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const;
+
+ //! Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type
+ ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label);
};
/**
@@ -1196,35 +1267,35 @@ void MaybeResendWalletTxs();
class WalletRescanReserver
{
private:
- CWallet* m_wallet;
+ CWallet& m_wallet;
bool m_could_reserve;
public:
- explicit WalletRescanReserver(CWallet* w) : m_wallet(w), m_could_reserve(false) {}
+ explicit WalletRescanReserver(CWallet& w) : m_wallet(w), m_could_reserve(false) {}
bool reserve()
{
assert(!m_could_reserve);
- std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
- if (m_wallet->fScanningWallet) {
+ std::lock_guard<std::mutex> lock(m_wallet.mutexScanning);
+ if (m_wallet.fScanningWallet) {
return false;
}
- m_wallet->m_scanning_start = GetTimeMillis();
- m_wallet->m_scanning_progress = 0;
- m_wallet->fScanningWallet = true;
+ m_wallet.m_scanning_start = GetTimeMillis();
+ m_wallet.m_scanning_progress = 0;
+ m_wallet.fScanningWallet = true;
m_could_reserve = true;
return true;
}
bool isReserved() const
{
- return (m_could_reserve && m_wallet->fScanningWallet);
+ return (m_could_reserve && m_wallet.fScanningWallet);
}
~WalletRescanReserver()
{
- std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
+ std::lock_guard<std::mutex> lock(m_wallet.mutexScanning);
if (m_could_reserve) {
- m_wallet->fScanningWallet = false;
+ m_wallet.fScanningWallet = false;
}
}
};