diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp index 87d2c4f06..60bce6683 100644 --- a/src/wallet/coincontrol.cpp +++ b/src/wallet/coincontrol.cpp @@ -13,6 +13,7 @@ void CCoinControl::SetNull() fAllowOtherInputs = false; fAllowWatchOnly = false; m_avoid_partial_spends = gArgs.GetBoolArg("-avoidpartialspends", DEFAULT_AVOIDPARTIALSPENDS); + m_avoid_address_reuse = false; setSelected.clear(); m_feerate.reset(); fOverrideFeeRate = false; diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 12ba032df..249c402e4 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -34,6 +34,8 @@ public: boost::optional m_signal_bip125_rbf; //! Avoid partial use of funds sent to a given address bool m_avoid_partial_spends; + //! Forbids inclusion of dirty (previously used) addresses + bool m_avoid_address_reuse; //! Fee estimation mode to control arguments to estimateSmartFee FeeEstimateMode m_fee_mode; //! Minimum chain depth value for coin availability diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 71d62a47d..6ab7d5dde 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -47,6 +47,17 @@ static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; +static inline bool GetAvoidReuseFlag(CWallet * const pwallet, const UniValue& param) { + bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE); + bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool(); + + if (avoid_reuse && !can_avoid_reuse) { + throw JSONRPCError(RPC_WALLET_ERROR, "wallet does not have the \"avoid reuse\" feature enabled"); + } + + return avoid_reuse; +} + bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest& request, std::string& wallet_name) { if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3eab069fb..2c51b6a8b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -41,6 +41,14 @@ #include +const std::map WALLET_FLAG_CAVEATS{ + {WALLET_FLAG_AVOID_REUSE, + "You need to rescan the blockchain in order to correctly mark used " + "destinations in the past. Until this is done, some destinations may " + "be considered unused, even if the opposite is the case." + }, +}; + static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; static CCriticalSection cs_wallets; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index bd3d721dd..4ff347a59 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -120,6 +120,10 @@ enum WalletFlags : uint64_t { // wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown // unknown wallet flags in the lower section <= (1 << 31) will be tolerated + // will categorize coins as clean (not reused) and dirty (reused), and handle + // them with privacy considerations in mind + WALLET_FLAG_AVOID_REUSE = (1ULL << 0), + // Indicates that the metadata has already been upgraded to contain key origins WALLET_FLAG_KEY_ORIGIN_METADATA = (1ULL << 1), @@ -139,7 +143,20 @@ enum WalletFlags : uint64_t { WALLET_FLAG_BLANK_WALLET = (1ULL << 33), }; -static constexpr uint64_t KNOWN_WALLET_FLAGS = WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | WALLET_FLAG_KEY_ORIGIN_METADATA; +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; + +static const std::map WALLET_FLAG_MAP{ + {"avoid_reuse", WALLET_FLAG_AVOID_REUSE}, + {"blank", WALLET_FLAG_BLANK_WALLET}, + {"key_origin_metadata", WALLET_FLAG_KEY_ORIGIN_METADATA}, + {"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS}, +}; + +extern const std::map WALLET_FLAG_CAVEATS; /** A key from a CWallet's keypool *