mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-12 19:20:42 +02:00
wallet: Delete LegacySPKM
Deletes LegacyScriptPubKeyMan and related tests Best reviewed with `git diff --patience` or `git diff --histogram`
This commit is contained in:
parent
8ede6dea0c
commit
83af1a3cca
@ -107,9 +107,6 @@ public:
|
||||
//! Return whether wallet has private key.
|
||||
virtual bool isSpendable(const CTxDestination& dest) = 0;
|
||||
|
||||
//! Return whether wallet has watch only keys.
|
||||
virtual bool haveWatchOnly() = 0;
|
||||
|
||||
//! Add or update address.
|
||||
virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;
|
||||
|
||||
@ -282,9 +279,6 @@ public:
|
||||
// Remove wallet.
|
||||
virtual void remove() = 0;
|
||||
|
||||
//! Return whether is a legacy wallet
|
||||
virtual bool isLegacy() = 0;
|
||||
|
||||
//! Register handler for unload message.
|
||||
using UnloadFn = std::function<void()>;
|
||||
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
|
||||
|
@ -195,28 +195,10 @@ OverviewPage::~OverviewPage()
|
||||
void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
|
||||
{
|
||||
BitcoinUnit unit = walletModel->getOptionsModel()->getDisplayUnit();
|
||||
if (walletModel->wallet().isLegacy()) {
|
||||
if (walletModel->wallet().privateKeysDisabled()) {
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
} else {
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelWatchAvailable->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelWatchPending->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelWatchImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelWatchTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
}
|
||||
} else {
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
}
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
|
||||
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
|
||||
// for the non-mining users
|
||||
bool showImmature = balances.immature_balance != 0;
|
||||
@ -281,11 +263,7 @@ void OverviewPage::setWalletModel(WalletModel *model)
|
||||
|
||||
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
|
||||
|
||||
interfaces::Wallet& wallet = model->wallet();
|
||||
updateWatchOnlyLabels(wallet.haveWatchOnly() && !wallet.privateKeysDisabled());
|
||||
connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
|
||||
updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
|
||||
});
|
||||
updateWatchOnlyLabels(false);
|
||||
}
|
||||
|
||||
// update the display unit, to not use the default ("BTC")
|
||||
|
@ -711,9 +711,6 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances)
|
||||
CAmount balance = balances.balance;
|
||||
if (model->wallet().hasExternalSigner()) {
|
||||
ui->labelBalanceName->setText(tr("External balance:"));
|
||||
} else if (model->wallet().isLegacy() && model->wallet().privateKeysDisabled()) {
|
||||
balance = balances.watch_only_balance;
|
||||
ui->labelBalanceName->setText(tr("Watch-only balance:"));
|
||||
}
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), balance));
|
||||
}
|
||||
|
@ -241,8 +241,8 @@ void TransactionView::setModel(WalletModel *_model)
|
||||
}
|
||||
}
|
||||
|
||||
// show/hide column Watch-only
|
||||
updateWatchOnlyColumn(_model->wallet().haveWatchOnly());
|
||||
// hide column Watch-only
|
||||
updateWatchOnlyColumn(false);
|
||||
|
||||
// Watch-only signal
|
||||
connect(_model, &WalletModel::notifyWatchonlyChanged, this, &TransactionView::updateWatchOnlyColumn);
|
||||
@ -368,8 +368,6 @@ void TransactionView::exportClicked()
|
||||
// name, column, role
|
||||
writer.setModel(transactionProxyModel);
|
||||
writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
|
||||
if (model->wallet().haveWatchOnly())
|
||||
writer.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly);
|
||||
writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
|
||||
writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
|
||||
writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
|
||||
|
@ -45,7 +45,7 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel
|
||||
optionsModel(client_model.getOptionsModel()),
|
||||
timer(new QTimer(this))
|
||||
{
|
||||
fHaveWatchOnly = m_wallet->haveWatchOnly();
|
||||
fHaveWatchOnly = false;
|
||||
addressTableModel = new AddressTableModel(this);
|
||||
transactionTableModel = new TransactionTableModel(platformStyle, this);
|
||||
recentRequestsTableModel = new RecentRequestsTableModel(this);
|
||||
|
@ -48,7 +48,7 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
|
||||
if (require_mine) {
|
||||
// check that original tx consists entirely of our inputs
|
||||
// if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
|
||||
isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
|
||||
isminefilter filter = ISMINE_SPENDABLE;
|
||||
if (!AllInputsMine(wallet, *wtx.tx, filter)) {
|
||||
errors.emplace_back(Untranslated("Transaction contains inputs that don't belong to this wallet"));
|
||||
return feebumper::Result::WALLET_ERROR;
|
||||
|
@ -175,14 +175,6 @@ public:
|
||||
LOCK(m_wallet->cs_wallet);
|
||||
return m_wallet->IsMine(dest) & ISMINE_SPENDABLE;
|
||||
}
|
||||
bool haveWatchOnly() override
|
||||
{
|
||||
auto spk_man = m_wallet->GetLegacyScriptPubKeyMan();
|
||||
if (spk_man) {
|
||||
return spk_man->HaveWatchOnly();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<AddressPurpose>& purpose) override
|
||||
{
|
||||
return m_wallet->SetAddressBook(dest, name, purpose);
|
||||
@ -407,12 +399,7 @@ public:
|
||||
result.balance = bal.m_mine_trusted;
|
||||
result.unconfirmed_balance = bal.m_mine_untrusted_pending;
|
||||
result.immature_balance = bal.m_mine_immature;
|
||||
result.have_watch_only = haveWatchOnly();
|
||||
if (result.have_watch_only) {
|
||||
result.watch_only_balance = bal.m_watchonly_trusted;
|
||||
result.unconfirmed_watch_only_balance = bal.m_watchonly_untrusted_pending;
|
||||
result.immature_watch_only_balance = bal.m_watchonly_immature;
|
||||
}
|
||||
result.have_watch_only = false;
|
||||
return result;
|
||||
}
|
||||
bool tryGetBalances(WalletBalances& balances, uint256& block_hash) override
|
||||
@ -516,7 +503,6 @@ public:
|
||||
bool hasExternalSigner() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER); }
|
||||
bool privateKeysDisabled() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); }
|
||||
bool taprootEnabled() override {
|
||||
if (m_wallet->IsLegacy()) return false;
|
||||
auto spk_man = m_wallet->GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/false);
|
||||
return spk_man != nullptr;
|
||||
}
|
||||
@ -526,7 +512,6 @@ public:
|
||||
{
|
||||
RemoveWallet(m_context, m_wallet, /*load_on_start=*/false);
|
||||
}
|
||||
bool isLegacy() override { return m_wallet->IsLegacy(); }
|
||||
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
|
||||
{
|
||||
return MakeSignalHandler(m_wallet->NotifyUnload.connect(fn));
|
||||
|
@ -54,8 +54,6 @@ RPCHelpMan getnewaddress()
|
||||
std::optional<OutputType> parsed = ParseOutputType(request.params[1].get_str());
|
||||
if (!parsed) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
|
||||
} else if (parsed.value() == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
|
||||
}
|
||||
output_type = parsed.value();
|
||||
}
|
||||
@ -101,8 +99,6 @@ RPCHelpMan getrawchangeaddress()
|
||||
std::optional<OutputType> parsed = ParseOutputType(request.params[0].get_str());
|
||||
if (!parsed) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
|
||||
} else if (parsed.value() == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
|
||||
}
|
||||
output_type = parsed.value();
|
||||
}
|
||||
@ -233,10 +229,6 @@ RPCHelpMan keypoolrefill()
|
||||
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!pwallet) return UniValue::VNULL;
|
||||
|
||||
if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
|
||||
}
|
||||
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
|
||||
|
@ -440,12 +440,6 @@ RPCHelpMan getbalances()
|
||||
{RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
|
||||
{RPCResult::Type::STR_AMOUNT, "used", /*optional=*/true, "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"},
|
||||
}},
|
||||
{RPCResult::Type::OBJ, "watchonly", /*optional=*/true, "watchonly balances (not present if wallet does not watch anything)",
|
||||
{
|
||||
{RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"},
|
||||
{RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
|
||||
{RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
|
||||
}},
|
||||
RESULT_LAST_PROCESSED_BLOCK,
|
||||
}
|
||||
},
|
||||
@ -479,15 +473,6 @@ RPCHelpMan getbalances()
|
||||
}
|
||||
balances.pushKV("mine", std::move(balances_mine));
|
||||
}
|
||||
auto spk_man = wallet.GetLegacyScriptPubKeyMan();
|
||||
if (spk_man && spk_man->HaveWatchOnly()) {
|
||||
UniValue balances_watchonly{UniValue::VOBJ};
|
||||
balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
|
||||
balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
|
||||
balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
|
||||
balances.pushKV("watchonly", std::move(balances_watchonly));
|
||||
}
|
||||
|
||||
AppendLastProcessedBlock(balances, wallet);
|
||||
return balances;
|
||||
},
|
||||
|
@ -60,7 +60,6 @@ static RPCHelpMan getwalletinfo()
|
||||
{RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
|
||||
{RPCResult::Type::NUM_TIME, "unlocked_until", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
|
||||
{RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
|
||||
{RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "the Hash160 of the HD seed (only present when HD is enabled)"},
|
||||
{RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
|
||||
{RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
|
||||
{RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
|
||||
@ -107,14 +106,6 @@ static RPCHelpMan getwalletinfo()
|
||||
}
|
||||
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
|
||||
|
||||
LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
|
||||
if (spk_man) {
|
||||
CKeyID seed_id = spk_man->GetHDChain().seed_id;
|
||||
if (!seed_id.IsNull()) {
|
||||
obj.pushKV("hdseedid", seed_id.GetHex());
|
||||
}
|
||||
}
|
||||
|
||||
if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
|
||||
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -65,99 +65,6 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
|
||||
|
||||
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
|
||||
|
||||
/** A key from a CWallet's keypool
|
||||
*
|
||||
* The wallet holds one (for pre HD-split wallets) or several keypools. These
|
||||
* are sets of keys that have not yet been used to provide addresses or receive
|
||||
* change.
|
||||
*
|
||||
* The Bitcoin Core wallet was originally a collection of unrelated private
|
||||
* keys with their associated addresses. If a non-HD wallet generated a
|
||||
* key/address, gave that address out and then restored a backup from before
|
||||
* that key's generation, then any funds sent to that address would be
|
||||
* lost definitively.
|
||||
*
|
||||
* The keypool was implemented to avoid this scenario (commit: 10384941). The
|
||||
* wallet would generate a set of keys (100 by default). When a new public key
|
||||
* was required, either to give out as an address or to use in a change output,
|
||||
* it would be drawn from the keypool. The keypool would then be topped up to
|
||||
* maintain 100 keys. This ensured that as long as the wallet hadn't used more
|
||||
* than 100 keys since the previous backup, all funds would be safe, since a
|
||||
* restored wallet would be able to scan for all owned addresses.
|
||||
*
|
||||
* A keypool also allowed encrypted wallets to give out addresses without
|
||||
* having to be decrypted to generate a new private key.
|
||||
*
|
||||
* With the introduction of HD wallets (commit: f1902510), the keypool
|
||||
* essentially became an address look-ahead pool. Restoring old backups can no
|
||||
* longer definitively lose funds as long as the addresses used were from the
|
||||
* wallet's HD seed (since all private keys can be rederived from the seed).
|
||||
* However, if many addresses were used since the backup, then the wallet may
|
||||
* not know how far ahead in the HD chain to look for its addresses. The
|
||||
* keypool is used to implement a 'gap limit'. The keypool maintains a set of
|
||||
* keys (by default 1000) ahead of the last used key and scans for the
|
||||
* addresses of those keys. This avoids the risk of not seeing transactions
|
||||
* involving the wallet's addresses, or of re-using the same address.
|
||||
* In the unlikely case where none of the addresses in the `gap limit` are
|
||||
* used on-chain, the look-ahead will not be incremented to keep
|
||||
* a constant size and addresses beyond this range will not be detected by an
|
||||
* old backup. For this reason, it is not recommended to decrease keypool size
|
||||
* lower than default value.
|
||||
*
|
||||
* The HD-split wallet feature added a second keypool (commit: 02592f4c). There
|
||||
* is an external keypool (for addresses to hand out) and an internal keypool
|
||||
* (for change addresses).
|
||||
*
|
||||
* Keypool keys are stored in the wallet/keystore's keymap. The keypool data is
|
||||
* stored as sets of indexes in the wallet (setInternalKeyPool,
|
||||
* setExternalKeyPool and set_pre_split_keypool), and a map from the key to the
|
||||
* index (m_pool_key_to_index). The CKeyPool object is used to
|
||||
* serialize/deserialize the pool data to/from the database.
|
||||
*/
|
||||
class CKeyPool
|
||||
{
|
||||
public:
|
||||
//! The time at which the key was generated. Set in AddKeypoolPubKeyWithDB
|
||||
int64_t nTime;
|
||||
//! The public key
|
||||
CPubKey vchPubKey;
|
||||
//! Whether this keypool entry is in the internal keypool (for change outputs)
|
||||
bool fInternal;
|
||||
//! Whether this key was generated for a keypool before the wallet was upgraded to HD-split
|
||||
bool m_pre_split;
|
||||
|
||||
CKeyPool();
|
||||
CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn);
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
{
|
||||
s << int{259900}; // Unused field, writes the highest client version ever written
|
||||
s << nTime << vchPubKey << fInternal << m_pre_split;
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
{
|
||||
s >> int{}; // Discard unused field
|
||||
s >> nTime >> vchPubKey;
|
||||
try {
|
||||
s >> fInternal;
|
||||
} catch (std::ios_base::failure&) {
|
||||
/* flag as external address if we can't read the internal boolean
|
||||
(this will be the case for any wallet before the HD chain split version) */
|
||||
fInternal = false;
|
||||
}
|
||||
try {
|
||||
s >> m_pre_split;
|
||||
} catch (std::ios_base::failure&) {
|
||||
/* flag as postsplit address if we can't read the m_pre_split boolean
|
||||
(this will be the case for any wallet that upgrades to HD chain split) */
|
||||
m_pre_split = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct WalletDestination
|
||||
{
|
||||
CTxDestination dest;
|
||||
@ -186,7 +93,7 @@ public:
|
||||
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key) { return false; }
|
||||
virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
|
||||
|
||||
virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; }
|
||||
virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index) { return util::Error{Untranslated("Not supported")}; }
|
||||
virtual void KeepDestination(int64_t index, const OutputType& type) {}
|
||||
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
|
||||
|
||||
@ -277,8 +184,6 @@ static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
|
||||
OutputType::BECH32,
|
||||
};
|
||||
|
||||
class DescriptorScriptPubKeyMan;
|
||||
|
||||
// Manages the data for a LegacyScriptPubKeyMan.
|
||||
// This is the minimum necessary to load a legacy wallet so that it can be migrated.
|
||||
class LegacyDataSPKM : public ScriptPubKeyMan, public FillableSigningProvider
|
||||
@ -331,12 +236,6 @@ public:
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
|
||||
|
||||
std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_KeyStore);
|
||||
std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_KeyStore);
|
||||
std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_KeyStore);
|
||||
int64_t m_max_keypool_index GUARDED_BY(cs_KeyStore) = 0;
|
||||
std::map<CKeyID, int64_t> m_pool_key_to_index;
|
||||
|
||||
//! Load metadata (used by LoadWallet)
|
||||
virtual void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
|
||||
virtual void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
|
||||
@ -357,8 +256,6 @@ public:
|
||||
void LoadHDChain(const CHDChain& chain);
|
||||
void AddInactiveHDChain(const CHDChain& chain);
|
||||
const CHDChain& GetHDChain() const { return m_hd_chain; }
|
||||
//! Load a keypool entry
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
|
||||
|
||||
//! Fetches a pubkey from mapWatchKeys if it exists there
|
||||
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
|
||||
@ -377,199 +274,6 @@ public:
|
||||
bool DeleteRecordsWithDB(WalletBatch& batch);
|
||||
};
|
||||
|
||||
// Implements the full legacy wallet behavior
|
||||
class LegacyScriptPubKeyMan : public LegacyDataSPKM
|
||||
{
|
||||
private:
|
||||
WalletBatch *encrypted_batch GUARDED_BY(cs_KeyStore) = nullptr;
|
||||
|
||||
// By default, do not scan any block until keys/scripts are generated/imported
|
||||
int64_t nTimeFirstKey GUARDED_BY(cs_KeyStore) = UNKNOWN_TIME;
|
||||
|
||||
//! Number of pre-generated keys/scripts (part of the look-ahead process, used to detect payments)
|
||||
int64_t m_keypool_size GUARDED_BY(cs_KeyStore){DEFAULT_KEYPOOL_SIZE};
|
||||
|
||||
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey) override;
|
||||
|
||||
/**
|
||||
* Private version of AddWatchOnly method which does not accept a
|
||||
* timestamp, and which will reset the wallet's nTimeFirstKey value to 1 if
|
||||
* the watch key did not previously have a timestamp associated with it.
|
||||
* Because this is an inherited virtual method, it is accessible despite
|
||||
* being marked private, but it is marked private anyway to encourage use
|
||||
* of the other AddWatchOnly which accepts a timestamp and sets
|
||||
* nTimeFirstKey more intelligently for more efficient rescans.
|
||||
*/
|
||||
bool AddWatchOnly(const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
//! Adds a watch-only address to the store, and saves it to disk.
|
||||
bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
|
||||
|
||||
//! Adds a script to the store and saves it to disk
|
||||
bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
|
||||
|
||||
/** Add a KeyOriginInfo to the wallet */
|
||||
bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||
|
||||
/* HD derive new child key (on internal or external chain) */
|
||||
void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
// Tracks keypool indexes to CKeyIDs of keys that have been taken out of the keypool but may be returned to it
|
||||
std::map<int64_t, CKeyID> m_index_to_reserved_key;
|
||||
|
||||
//! Fetches a key from the keypool
|
||||
bool GetKeyFromPool(CPubKey &key, const OutputType type);
|
||||
|
||||
/**
|
||||
* Reserves a key from the keypool and sets nIndex to its index
|
||||
*
|
||||
* @param[out] nIndex the index of the key in keypool
|
||||
* @param[out] keypool the keypool the key was drawn from, which could be the
|
||||
* the pre-split pool if present, or the internal or external pool
|
||||
* @param fRequestedInternal true if the caller would like the key drawn
|
||||
* from the internal keypool, false if external is preferred
|
||||
*
|
||||
* @return true if succeeded, false if failed due to empty keypool
|
||||
* @throws std::runtime_error if keypool read failed, key was invalid,
|
||||
* was not found in the wallet, or was misclassified in the internal
|
||||
* or external keypool
|
||||
*/
|
||||
bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
|
||||
|
||||
/**
|
||||
* Like TopUp() but adds keys for inactive HD chains.
|
||||
* Ensures that there are at least -keypool number of keys derived after the given index.
|
||||
*
|
||||
* @param seed_id the CKeyID for the HD seed.
|
||||
* @param index the index to start generating keys from
|
||||
* @param internal whether the internal chain should be used. true for internal chain, false for external chain.
|
||||
*
|
||||
* @return true if seed was found and keys were derived. false if unable to derive seeds
|
||||
*/
|
||||
bool TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal);
|
||||
|
||||
bool TopUpChain(WalletBatch& batch, CHDChain& chain, unsigned int size);
|
||||
public:
|
||||
LegacyScriptPubKeyMan(WalletStorage& storage, int64_t keypool_size) : LegacyDataSPKM(storage), m_keypool_size(keypool_size) {}
|
||||
|
||||
util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
|
||||
|
||||
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
||||
|
||||
util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
|
||||
void KeepDestination(int64_t index, const OutputType& type) override;
|
||||
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
|
||||
|
||||
bool TopUp(unsigned int size = 0) override;
|
||||
|
||||
std::vector<WalletDestination> MarkUnusedAddresses(const CScript& script) override;
|
||||
|
||||
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
|
||||
void UpgradeKeyMetadata();
|
||||
|
||||
bool IsHDEnabled() const override;
|
||||
|
||||
bool SetupGeneration(bool force = false) override;
|
||||
|
||||
bool Upgrade(int prev_version, int new_version, bilingual_str& error) override;
|
||||
|
||||
bool HavePrivateKeys() const override;
|
||||
bool HaveCryptedKeys() const override;
|
||||
|
||||
void RewriteDB() override;
|
||||
|
||||
std::optional<int64_t> GetOldestKeyPoolTime() const override;
|
||||
size_t KeypoolCountExternalKeys() const;
|
||||
unsigned int GetKeyPoolSize() const override;
|
||||
|
||||
int64_t GetTimeFirstKey() const override;
|
||||
|
||||
std::unique_ptr<CKeyMetadata> GetMetadata(const CTxDestination& dest) const override;
|
||||
|
||||
bool CanGetAddresses(bool internal = false) const override;
|
||||
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
|
||||
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
|
||||
std::optional<common::PSBTError> FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = SIGHASH_DEFAULT, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr, bool finalize = true) const override;
|
||||
|
||||
uint256 GetID() const override;
|
||||
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
|
||||
//! Adds an encrypted key to the store, and saves it to disk.
|
||||
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
//! Load metadata (used by LoadWallet)
|
||||
void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) override;
|
||||
void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) override;
|
||||
//! Generate a new key
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, CHDChain& hd_chain, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
/* Set the HD chain model (chain child index counters) and writes it to the database */
|
||||
void AddHDChain(const CHDChain& chain);
|
||||
|
||||
//! Remove a watch only script from the keystore
|
||||
bool RemoveWatchOnly(const CScript &dest);
|
||||
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
/* SigningProvider overrides */
|
||||
bool AddCScript(const CScript& redeemScript) override;
|
||||
|
||||
bool NewKeyPool();
|
||||
void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
bool ImportPubKeys(const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
bool ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
|
||||
/* Returns true if the wallet can generate new keys */
|
||||
bool CanGenerateKeys() const;
|
||||
|
||||
/* Generates a new HD seed (will not be activated) */
|
||||
CPubKey GenerateNewSeed();
|
||||
|
||||
/* Derives a new HD seed (will not be activated) */
|
||||
CPubKey DeriveNewSeed(const CKey& key);
|
||||
|
||||
/* Set the current HD seed (will reset the chain child index counters)
|
||||
Sets the seed's version based on the current wallet version (so the
|
||||
caller must ensure the current wallet version is correct before calling
|
||||
this function). */
|
||||
void SetHDSeed(const CPubKey& key);
|
||||
|
||||
/**
|
||||
* Explicitly make the wallet learn the related scripts for outputs to the
|
||||
* given key. This is purely to make the wallet file compatible with older
|
||||
* software, as FillableSigningProvider automatically does this implicitly for all
|
||||
* keys now.
|
||||
*/
|
||||
void LearnRelatedScripts(const CPubKey& key, OutputType);
|
||||
|
||||
/**
|
||||
* Same as LearnRelatedScripts, but when the OutputType is not known (and could
|
||||
* be anything).
|
||||
*/
|
||||
void LearnAllRelatedScripts(const CPubKey& key);
|
||||
|
||||
/**
|
||||
* Marks all keys in the keypool up to and including the provided key as used.
|
||||
*
|
||||
* @param keypool_id determines the last key to mark as used
|
||||
*
|
||||
* @return All affected keys
|
||||
*/
|
||||
std::vector<CKeyPool> MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
|
||||
|
||||
std::set<CKeyID> GetKeys() const override;
|
||||
};
|
||||
|
||||
/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr. Does not provide privkeys */
|
||||
class LegacySigningProvider : public SigningProvider
|
||||
{
|
||||
@ -644,7 +348,7 @@ public:
|
||||
bool CheckDecryptionKey(const CKeyingMaterial& master_key) override;
|
||||
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
||||
|
||||
util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
|
||||
util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index) override;
|
||||
void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
|
||||
|
||||
// Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
|
||||
|
@ -508,8 +508,6 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
|
||||
std::map<CTxDestination, std::vector<COutput>> result;
|
||||
|
||||
CCoinControl coin_control;
|
||||
// Include watch-only for LegacyScriptPubKeyMan wallets without private keys
|
||||
coin_control.fAllowWatchOnly = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
|
||||
CoinFilterParams coins_params;
|
||||
coins_params.only_spendable = false;
|
||||
coins_params.skip_locked = false;
|
||||
|
@ -36,25 +36,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
CScript scriptPubKey;
|
||||
isminetype result;
|
||||
|
||||
// P2PK compressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
|
||||
|
||||
// Keystore does not have key
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2PK compressed - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -67,25 +48,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2PK uncompressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
|
||||
|
||||
// Keystore does not have key
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2PK uncompressed - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -98,25 +60,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2PKH compressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||
|
||||
// Keystore does not have key
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2PKH compressed - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -129,25 +72,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2PKH uncompressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey));
|
||||
|
||||
// Keystore does not have key
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2PKH uncompressed - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -160,33 +84,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2SH - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||
|
||||
// Keystore does not have redeemScript or key
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has redeemScript but no key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has redeemScript and key
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2SH - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -200,25 +97,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2SH inside P2SH (invalid) - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||
CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner));
|
||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript));
|
||||
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript_inner));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -228,25 +106,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2SH inside P2WSH (invalid) - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||
CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript));
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemscript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -256,23 +115,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// P2WPKH inside P2WSH (invalid) - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// P2WPKH inside P2WSH (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -282,25 +124,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2WSH inside P2WSH (invalid) - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0]));
|
||||
CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript_inner));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessscript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -310,22 +133,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// P2WPKH compressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0]));
|
||||
|
||||
// Keystore implicitly has key and P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2WPKH compressed - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -338,27 +145,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2WPKH uncompressed - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey));
|
||||
|
||||
// Keystore has key, but no P2SH redeemScript
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has key and P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// P2WPKH uncompressed (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -368,41 +154,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// scriptPubKey multisig - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||
|
||||
// Keystore does not have any keys
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has 1/2 keys
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has 2/2 keys
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has 2/2 keys and the script
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// scriptPubKey multisig - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -415,29 +166,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2SH multisig - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
|
||||
|
||||
CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||
|
||||
// Keystore has no redeemScript
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2SH multisig - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -452,35 +180,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2WSH multisig with compressed keys - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
|
||||
|
||||
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||
|
||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has keys and witnessScript, but no P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2WSH multisig with compressed keys - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -495,35 +194,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// P2WSH multisig with uncompressed key - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
|
||||
|
||||
CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||
|
||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has keys and witnessScript, but no P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// P2WSH multisig with uncompressed key (invalid) - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -534,36 +204,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
BOOST_CHECK_EQUAL(spk_manager, nullptr);
|
||||
}
|
||||
|
||||
// P2WSH multisig wrapped in P2SH - Legacy
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
|
||||
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
||||
CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||
scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript));
|
||||
|
||||
// Keystore has no witnessScript, P2SH redeemScript, or keys
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has witnessScript and P2SH redeemScript, but no keys
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
|
||||
// Keystore has keys, witnessScript, P2SH redeemScript
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
|
||||
}
|
||||
|
||||
// P2WSH multisig wrapped in P2SH - Descriptor
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
@ -640,66 +280,6 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
result = spk_manager->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
|
||||
}
|
||||
|
||||
// OP_RETURN
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
|
||||
scriptPubKey.clear();
|
||||
scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// witness unspendable
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
|
||||
scriptPubKey.clear();
|
||||
scriptPubKey << OP_0 << "aabb"_hex;
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// witness unknown
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
|
||||
scriptPubKey.clear();
|
||||
scriptPubKey << OP_16 << "aabb"_hex;
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
|
||||
// Nonstandard
|
||||
{
|
||||
CWallet keystore(chain.get(), "", CreateMockableWalletDatabase());
|
||||
keystore.SetupLegacyScriptPubKeyMan();
|
||||
LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
|
||||
|
||||
scriptPubKey.clear();
|
||||
scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
|
||||
|
||||
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
|
||||
BOOST_CHECK_EQUAL(result, ISMINE_NO);
|
||||
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -15,32 +15,6 @@
|
||||
namespace wallet {
|
||||
BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
|
||||
|
||||
// Test LegacyScriptPubKeyMan::CanProvide behavior, making sure it returns true
|
||||
// for recognized scripts even when keys may not be available for signing.
|
||||
BOOST_AUTO_TEST_CASE(CanProvide)
|
||||
{
|
||||
// Set up wallet and keyman variables.
|
||||
CWallet wallet(m_node.chain.get(), "", CreateMockableWalletDatabase());
|
||||
LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
|
||||
|
||||
// Make a 1 of 2 multisig script
|
||||
std::vector<CKey> keys(2);
|
||||
std::vector<CPubKey> pubkeys;
|
||||
for (CKey& key : keys) {
|
||||
key.MakeNewKey(true);
|
||||
pubkeys.emplace_back(key.GetPubKey());
|
||||
}
|
||||
CScript multisig_script = GetScriptForMultisig(1, pubkeys);
|
||||
CScript p2sh_script = GetScriptForDestination(ScriptHash(multisig_script));
|
||||
SignatureData data;
|
||||
|
||||
// Verify the p2sh(multisig) script is not recognized until the multisig
|
||||
// script is added to the keystore to make it solvable
|
||||
BOOST_CHECK(!keyman.CanProvide(p2sh_script, data));
|
||||
keyman.AddCScript(multisig_script);
|
||||
BOOST_CHECK(keyman.CanProvide(p2sh_script, data));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DescriptorScriptPubKeyManTests)
|
||||
{
|
||||
std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
|
||||
|
@ -29,34 +29,5 @@ BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue)
|
||||
BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(walletdb_read_write_deadlock)
|
||||
{
|
||||
// Exercises a db read write operation that shouldn't deadlock.
|
||||
for (const DatabaseFormat& db_format : DATABASE_FORMATS) {
|
||||
// Context setup
|
||||
DatabaseOptions options;
|
||||
options.require_format = db_format;
|
||||
DatabaseStatus status;
|
||||
bilingual_str error_string;
|
||||
std::unique_ptr<WalletDatabase> db = MakeDatabase(m_path_root / strprintf("wallet_%d_.dat", db_format).c_str(), options, status, error_string);
|
||||
BOOST_CHECK_EQUAL(status, DatabaseStatus::SUCCESS);
|
||||
|
||||
std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(db)));
|
||||
wallet->m_keypool_size = 4;
|
||||
|
||||
// Create legacy spkm
|
||||
LOCK(wallet->cs_wallet);
|
||||
auto legacy_spkm = wallet->GetOrCreateLegacyScriptPubKeyMan();
|
||||
BOOST_CHECK(!HasLegacyRecords(*wallet));
|
||||
BOOST_CHECK(legacy_spkm->SetupGeneration(true));
|
||||
BOOST_CHECK(HasLegacyRecords(*wallet));
|
||||
wallet->Flush();
|
||||
|
||||
// Now delete all records, which performs a read write operation.
|
||||
BOOST_CHECK(wallet->GetLegacyScriptPubKeyMan()->DeleteRecords());
|
||||
BOOST_CHECK(!HasLegacyRecords(*wallet));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
} // namespace wallet
|
||||
|
@ -313,9 +313,6 @@ class FastWalletRescanFilter
|
||||
public:
|
||||
FastWalletRescanFilter(const CWallet& wallet) : m_wallet(wallet)
|
||||
{
|
||||
// fast rescanning via block filters is only supported by descriptor wallets right now
|
||||
assert(!m_wallet.IsLegacy());
|
||||
|
||||
// create initial filter with scripts from all ScriptPubKeyMans
|
||||
for (auto spkm : m_wallet.GetAllScriptPubKeyMans()) {
|
||||
auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
|
||||
@ -548,21 +545,6 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
return &(it->second);
|
||||
}
|
||||
|
||||
void CWallet::UpgradeKeyMetadata()
|
||||
{
|
||||
if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (!spk_man) {
|
||||
return;
|
||||
}
|
||||
|
||||
spk_man->UpgradeKeyMetadata();
|
||||
SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
|
||||
}
|
||||
|
||||
void CWallet::UpgradeDescriptorCache()
|
||||
{
|
||||
if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) || IsLocked() || IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
|
||||
@ -630,8 +612,6 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
|
||||
continue; // try another master key
|
||||
}
|
||||
if (Unlock(plain_master_key)) {
|
||||
// Now that we've unlocked, upgrade the key metadata
|
||||
UpgradeKeyMetadata();
|
||||
// Now that we've unlocked, upgrade the descriptor cache
|
||||
UpgradeDescriptorCache();
|
||||
return true;
|
||||
@ -895,13 +875,6 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
// If we are using descriptors, make new descriptors with a new seed
|
||||
if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)) {
|
||||
SetupDescriptorScriptPubKeyMans();
|
||||
} else if (auto spk_man = GetLegacyScriptPubKeyMan()) {
|
||||
// if we are using HD, replace the HD seed with a new one
|
||||
if (spk_man->IsHDEnabled()) {
|
||||
if (!spk_man->SetupGeneration(true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Lock();
|
||||
|
||||
@ -1059,23 +1032,6 @@ bool CWallet::IsSpentKey(const CScript& scriptPubKey) const
|
||||
if (IsAddressPreviouslySpent(dest)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan()) {
|
||||
for (const auto& keyid : GetAffectedKeys(scriptPubKey, *spk_man)) {
|
||||
WitnessV0KeyHash wpkh_dest(keyid);
|
||||
if (IsAddressPreviouslySpent(wpkh_dest)) {
|
||||
return true;
|
||||
}
|
||||
ScriptHash sh_wpkh_dest(GetScriptForDestination(wpkh_dest));
|
||||
if (IsAddressPreviouslySpent(sh_wpkh_dest)) {
|
||||
return true;
|
||||
}
|
||||
PKHash pkh_dest(keyid);
|
||||
if (IsAddressPreviouslySpent(pkh_dest)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1651,11 +1607,6 @@ isminetype CWallet::IsMine(const CScript& script) const
|
||||
return res;
|
||||
}
|
||||
|
||||
// Legacy wallet
|
||||
if (LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan()) {
|
||||
return spkm->IsMine(script);
|
||||
}
|
||||
|
||||
return ISMINE_NO;
|
||||
}
|
||||
|
||||
@ -1788,59 +1739,6 @@ void CWallet::InitWalletFlags(uint64_t flags)
|
||||
if (!LoadWalletFlags(flags)) assert(false);
|
||||
}
|
||||
|
||||
bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
|
||||
{
|
||||
auto spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (!spk_man) {
|
||||
return false;
|
||||
}
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
return spk_man->ImportScripts(scripts, timestamp);
|
||||
}
|
||||
|
||||
bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp)
|
||||
{
|
||||
auto spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (!spk_man) {
|
||||
return false;
|
||||
}
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
return spk_man->ImportPrivKeys(privkey_map, timestamp);
|
||||
}
|
||||
|
||||
bool CWallet::ImportPubKeys(const std::vector<std::pair<CKeyID, bool>>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const int64_t timestamp)
|
||||
{
|
||||
auto spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (!spk_man) {
|
||||
return false;
|
||||
}
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
return spk_man->ImportPubKeys(ordered_pubkeys, pubkey_map, key_origins, add_keypool, timestamp);
|
||||
}
|
||||
|
||||
bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
|
||||
{
|
||||
auto spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (!spk_man) {
|
||||
return false;
|
||||
}
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
if (!spk_man->ImportScriptPubKeys(script_pub_keys, have_solving_data, timestamp)) {
|
||||
return false;
|
||||
}
|
||||
if (apply_label) {
|
||||
WalletBatch batch(GetDatabase());
|
||||
for (const CScript& script : script_pub_keys) {
|
||||
CTxDestination dest;
|
||||
ExtractDestination(script, dest);
|
||||
if (IsValidDestination(dest)) {
|
||||
SetAddressBookWithDB(batch, dest, label, AddressPurpose::RECEIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::MaybeUpdateBirthTime(int64_t time)
|
||||
{
|
||||
int64_t birthtime = m_birth_time.load();
|
||||
@ -1913,7 +1811,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
|
||||
ScanResult result;
|
||||
|
||||
std::unique_ptr<FastWalletRescanFilter> fast_rescan_filter;
|
||||
if (!IsLegacy() && chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
|
||||
if (chain().hasBlockFilterIndex(BlockFilterType::BASIC)) fast_rescan_filter = std::make_unique<FastWalletRescanFilter>(*this);
|
||||
|
||||
WalletLogPrintf("Rescan started from block %s... (%s)\n", start_block.ToString(),
|
||||
fast_rescan_filter ? "fast variant using block filters" : "slow variant inspecting all blocks");
|
||||
@ -2182,11 +2080,6 @@ void MaybeResendWalletTxs(WalletContext& context)
|
||||
}
|
||||
|
||||
|
||||
/** @defgroup Actions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
bool CWallet::SignTransaction(CMutableTransaction& tx) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
@ -2559,11 +2452,6 @@ size_t CWallet::KeypoolCountExternalKeys() const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
auto legacy_spk_man = GetLegacyScriptPubKeyMan();
|
||||
if (legacy_spk_man) {
|
||||
return legacy_spk_man->KeypoolCountExternalKeys();
|
||||
}
|
||||
|
||||
unsigned int count = 0;
|
||||
for (auto spk_man : m_external_spk_managers) {
|
||||
count += spk_man.second->GetKeyPoolSize();
|
||||
@ -2695,13 +2583,11 @@ util::Result<CTxDestination> ReserveDestination::GetReservedDestination(bool int
|
||||
}
|
||||
|
||||
if (nIndex == -1) {
|
||||
CKeyPool keypool;
|
||||
int64_t index;
|
||||
auto op_address = m_spk_man->GetReservedDestination(type, internal, index, keypool);
|
||||
auto op_address = m_spk_man->GetReservedDestination(type, internal, index);
|
||||
if (!op_address) return op_address;
|
||||
nIndex = index;
|
||||
address = *op_address;
|
||||
fInternal = keypool.fInternal;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
@ -2786,68 +2672,6 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */ // end of Actions
|
||||
|
||||
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
|
||||
AssertLockHeld(cs_wallet);
|
||||
mapKeyBirth.clear();
|
||||
|
||||
// map in which we'll infer heights of other keys
|
||||
std::map<CKeyID, const TxStateConfirmed*> mapKeyFirstBlock;
|
||||
TxStateConfirmed max_confirm{uint256{}, /*height=*/-1, /*index=*/-1};
|
||||
max_confirm.confirmed_block_height = GetLastBlockHeight() > 144 ? GetLastBlockHeight() - 144 : 0; // the tip can be reorganized; use a 144-block safety margin
|
||||
CHECK_NONFATAL(chain().findAncestorByHeight(GetLastBlockHash(), max_confirm.confirmed_block_height, FoundBlock().hash(max_confirm.confirmed_block_hash)));
|
||||
|
||||
{
|
||||
LegacyScriptPubKeyMan* spk_man = GetLegacyScriptPubKeyMan();
|
||||
assert(spk_man != nullptr);
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
|
||||
// get birth times for keys with metadata
|
||||
for (const auto& entry : spk_man->mapKeyMetadata) {
|
||||
if (entry.second.nCreateTime) {
|
||||
mapKeyBirth[entry.first] = entry.second.nCreateTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare to infer birth heights for keys without metadata
|
||||
for (const CKeyID &keyid : spk_man->GetKeys()) {
|
||||
if (mapKeyBirth.count(keyid) == 0)
|
||||
mapKeyFirstBlock[keyid] = &max_confirm;
|
||||
}
|
||||
|
||||
// if there are no such keys, we're done
|
||||
if (mapKeyFirstBlock.empty())
|
||||
return;
|
||||
|
||||
// find first block that affects those keys, if there are any left
|
||||
for (const auto& entry : mapWallet) {
|
||||
// iterate over all wallet transactions...
|
||||
const CWalletTx &wtx = entry.second;
|
||||
if (auto* conf = wtx.state<TxStateConfirmed>()) {
|
||||
// ... which are already in a block
|
||||
for (const CTxOut &txout : wtx.tx->vout) {
|
||||
// iterate over all their outputs
|
||||
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *spk_man)) {
|
||||
// ... and all their affected keys
|
||||
auto rit = mapKeyFirstBlock.find(keyid);
|
||||
if (rit != mapKeyFirstBlock.end() && conf->confirmed_block_height < rit->second->confirmed_block_height) {
|
||||
rit->second = conf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract block timestamps for those keys
|
||||
for (const auto& entry : mapKeyFirstBlock) {
|
||||
int64_t block_time;
|
||||
CHECK_NONFATAL(chain().findBlock(entry.second->confirmed_block_hash, FoundBlock().time(block_time)));
|
||||
mapKeyBirth[entry.first] = block_time - TIMESTAMP_WINDOW; // block times can be 2h off
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute smart timestamp for a transaction being added to the wallet.
|
||||
*
|
||||
@ -3465,21 +3289,6 @@ bool CWallet::BackupWallet(const std::string& strDest) const
|
||||
return GetDatabase().Backup(strDest);
|
||||
}
|
||||
|
||||
CKeyPool::CKeyPool()
|
||||
{
|
||||
nTime = GetTime();
|
||||
fInternal = false;
|
||||
m_pre_split = false;
|
||||
}
|
||||
|
||||
CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn)
|
||||
{
|
||||
nTime = GetTime();
|
||||
vchPubKey = vchPubKeyIn;
|
||||
fInternal = internalIn;
|
||||
m_pre_split = false;
|
||||
}
|
||||
|
||||
int CWallet::GetTxDepthInMainChain(const CWalletTx& wtx) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
@ -3616,10 +3425,6 @@ std::set<ScriptPubKeyMan*> CWallet::GetScriptPubKeyMans(const CScript& script) c
|
||||
SignatureData sigdata;
|
||||
Assume(std::all_of(spk_mans.begin(), spk_mans.end(), [&script, &sigdata](ScriptPubKeyMan* spkm) { return spkm->CanProvide(script, sigdata); }));
|
||||
|
||||
// Legacy wallet
|
||||
LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan();
|
||||
if (spkm && spkm->CanProvide(script, sigdata)) spk_mans.insert(spkm);
|
||||
|
||||
return spk_mans;
|
||||
}
|
||||
|
||||
@ -3647,10 +3452,6 @@ std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& scri
|
||||
return it->second.at(0)->GetSolvingProvider(script);
|
||||
}
|
||||
|
||||
// Legacy wallet
|
||||
LegacyScriptPubKeyMan* spkm = GetLegacyScriptPubKeyMan();
|
||||
if (spkm && spkm->CanProvide(script, sigdata)) return spkm->GetSolvingProvider(script);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -3666,18 +3467,6 @@ std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& scrip
|
||||
return descs;
|
||||
}
|
||||
|
||||
LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
|
||||
{
|
||||
if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
return nullptr;
|
||||
}
|
||||
// Legacy wallets only have one ScriptPubKeyMan which is a LegacyScriptPubKeyMan.
|
||||
// Everything in m_internal_spk_managers and m_external_spk_managers point to the same legacyScriptPubKeyMan.
|
||||
auto it = m_internal_spk_managers.find(OutputType::LEGACY);
|
||||
if (it == m_internal_spk_managers.end()) return nullptr;
|
||||
return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
|
||||
}
|
||||
|
||||
LegacyDataSPKM* CWallet::GetLegacyDataSPKM() const
|
||||
{
|
||||
if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
@ -3688,12 +3477,6 @@ LegacyDataSPKM* CWallet::GetLegacyDataSPKM() const
|
||||
return dynamic_cast<LegacyDataSPKM*>(it->second);
|
||||
}
|
||||
|
||||
LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
|
||||
{
|
||||
SetupLegacyScriptPubKeyMan();
|
||||
return GetLegacyScriptPubKeyMan();
|
||||
}
|
||||
|
||||
void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKeyMan> spkm_man)
|
||||
{
|
||||
// Add spkm_man to m_spk_managers before calling any method
|
||||
@ -3716,9 +3499,8 @@ void CWallet::SetupLegacyScriptPubKeyMan()
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<ScriptPubKeyMan> spk_manager = m_database->Format() == "bdb_ro" ?
|
||||
std::make_unique<LegacyDataSPKM>(*this) :
|
||||
std::make_unique<LegacyScriptPubKeyMan>(*this, m_keypool_size);
|
||||
Assert(m_database->Format() == "bdb_ro" || m_database->Format() == "mock");
|
||||
std::unique_ptr<ScriptPubKeyMan> spk_manager = std::make_unique<LegacyDataSPKM>(*this);
|
||||
|
||||
for (const auto& type : LEGACY_OUTPUT_TYPES) {
|
||||
m_internal_spk_managers[type] = spk_manager.get();
|
||||
@ -3915,11 +3697,6 @@ void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool intern
|
||||
NotifyCanGetAddressesChanged();
|
||||
}
|
||||
|
||||
bool CWallet::IsLegacy() const
|
||||
{
|
||||
return !IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS);
|
||||
}
|
||||
|
||||
DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const
|
||||
{
|
||||
auto spk_man_pair = m_spk_managers.find(desc.id);
|
||||
@ -3937,11 +3714,6 @@ DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDes
|
||||
|
||||
std::optional<bool> CWallet::IsInternalScriptPubKeyMan(ScriptPubKeyMan* spk_man) const
|
||||
{
|
||||
// Legacy script pubkey man can't be either external or internal
|
||||
if (IsLegacy()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// only active ScriptPubKeyMan can be internal
|
||||
if (!GetActiveScriptPubKeyMans().count(spk_man)) {
|
||||
return std::nullopt;
|
||||
|
@ -558,9 +558,6 @@ public:
|
||||
SteadyClock::duration ScanningDuration() const { return fScanningWallet ? SteadyClock::now() - m_scanning_start.load() : SteadyClock::duration{}; }
|
||||
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
|
||||
|
||||
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
|
||||
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Upgrade DescriptorCaches
|
||||
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
@ -583,7 +580,6 @@ public:
|
||||
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
|
||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||
|
||||
void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
unsigned int ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const;
|
||||
|
||||
/**
|
||||
@ -920,9 +916,6 @@ public:
|
||||
/** Loads the flags into the wallet. (used by LoadWallet) */
|
||||
bool LoadWalletFlags(uint64_t flags);
|
||||
|
||||
/** 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 */
|
||||
std::string GetDisplayName() const override
|
||||
{
|
||||
@ -963,8 +956,6 @@ public:
|
||||
std::vector<WalletDescriptor> GetWalletDescriptors(const CScript& script) const;
|
||||
|
||||
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
|
||||
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
|
||||
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
|
||||
LegacyDataSPKM* GetLegacyDataSPKM() const;
|
||||
LegacyDataSPKM* GetOrCreateLegacyDataSPKM();
|
||||
|
||||
|
@ -154,11 +154,6 @@ bool WalletBatch::EraseMasterKey(unsigned int id)
|
||||
return EraseIC(std::make_pair(DBKeys::MASTER_KEY, id));
|
||||
}
|
||||
|
||||
bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
|
||||
}
|
||||
|
||||
bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta)
|
||||
{
|
||||
if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) {
|
||||
@ -203,21 +198,6 @@ bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
|
||||
return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);
|
||||
}
|
||||
|
||||
bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool)
|
||||
{
|
||||
return m_batch->Read(std::make_pair(DBKeys::POOL, nPool), keypool);
|
||||
}
|
||||
|
||||
bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool)
|
||||
{
|
||||
return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool);
|
||||
}
|
||||
|
||||
bool WalletBatch::ErasePool(int64_t nPool)
|
||||
{
|
||||
return EraseIC(std::make_pair(DBKeys::POOL, nPool));
|
||||
}
|
||||
|
||||
bool WalletBatch::WriteMinVersion(int nVersion)
|
||||
{
|
||||
return WriteIC(DBKeys::MINVERSION, nVersion);
|
||||
@ -744,18 +724,6 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
|
||||
});
|
||||
result = std::max(result, watch_meta_res.m_result);
|
||||
|
||||
// Load keypool
|
||||
LoadResult pool_res = LoadRecords(pwallet, batch, DBKeys::POOL,
|
||||
[] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) {
|
||||
int64_t nIndex;
|
||||
key >> nIndex;
|
||||
CKeyPool keypool;
|
||||
value >> keypool;
|
||||
pwallet->GetOrCreateLegacyDataSPKM()->LoadKeyPool(nIndex, keypool);
|
||||
return DBErrors::LOAD_OK;
|
||||
});
|
||||
result = std::max(result, pool_res.m_result);
|
||||
|
||||
// Deal with old "wkey" and "defaultkey" records.
|
||||
// These are not actually loaded, but we need to check for them
|
||||
|
||||
@ -791,15 +759,6 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
|
||||
// Only do logging and time first key update if there were no critical errors
|
||||
pwallet->WalletLogPrintf("Legacy Wallet Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total.\n",
|
||||
key_res.m_records, ckey_res.m_records, keymeta_res.m_records, key_res.m_records + ckey_res.m_records);
|
||||
|
||||
// nTimeFirstKey is only reliable if all keys have metadata
|
||||
if (pwallet->IsLegacy() && (key_res.m_records + ckey_res.m_records + watch_script_res.m_records) != (keymeta_res.m_records + watch_meta_res.m_records)) {
|
||||
auto spk_man = pwallet->GetLegacyScriptPubKeyMan();
|
||||
if (spk_man) {
|
||||
LOCK(spk_man->cs_KeyStore);
|
||||
spk_man->UpdateTimeFirstKey(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1253,14 +1212,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
|
||||
if (any_unordered)
|
||||
result = pwallet->ReorderTransactions();
|
||||
|
||||
// Upgrade all of the wallet keymetadata to have the hd master key id
|
||||
// This operation is not atomic, but if it fails, updated entries are still backwards compatible with older software
|
||||
try {
|
||||
pwallet->UpgradeKeyMetadata();
|
||||
} catch (...) {
|
||||
result = DBErrors::CORRUPT;
|
||||
}
|
||||
|
||||
// Upgrade all of the descriptor caches to cache the last hardened xpub
|
||||
// This operation is not atomic, but if it fails, only new entries are added so it is backwards compatible
|
||||
try {
|
||||
@ -1366,11 +1317,6 @@ bool WalletBatch::EraseAddressData(const CTxDestination& dest)
|
||||
return m_batch->ErasePrefix(prefix);
|
||||
}
|
||||
|
||||
bool WalletBatch::WriteHDChain(const CHDChain& chain)
|
||||
{
|
||||
return WriteIC(DBKeys::HDCHAIN, chain);
|
||||
}
|
||||
|
||||
bool WalletBatch::WriteWalletFlags(const uint64_t flags)
|
||||
{
|
||||
return WriteIC(DBKeys::FLAGS, flags);
|
||||
|
@ -21,7 +21,6 @@ class uint256;
|
||||
struct CBlockLocator;
|
||||
|
||||
namespace wallet {
|
||||
class CKeyPool;
|
||||
class CMasterKey;
|
||||
class CWallet;
|
||||
class CWalletTx;
|
||||
@ -239,8 +238,6 @@ public:
|
||||
bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey);
|
||||
bool EraseMasterKey(unsigned int id);
|
||||
|
||||
bool WriteCScript(const uint160& hash, const CScript& redeemScript);
|
||||
|
||||
bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta);
|
||||
bool EraseWatchOnly(const CScript &script);
|
||||
|
||||
@ -252,10 +249,6 @@ public:
|
||||
|
||||
bool WriteOrderPosNext(int64_t nOrderPosNext);
|
||||
|
||||
bool ReadPool(int64_t nPool, CKeyPool& keypool);
|
||||
bool WritePool(int64_t nPool, const CKeyPool& keypool);
|
||||
bool ErasePool(int64_t nPool);
|
||||
|
||||
bool WriteMinVersion(int nVersion);
|
||||
|
||||
bool WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey);
|
||||
@ -279,9 +272,6 @@ public:
|
||||
|
||||
DBErrors LoadWallet(CWallet* pwallet);
|
||||
|
||||
//! write the hdchain model (external chain child index counter)
|
||||
bool WriteHDChain(const CHDChain& chain);
|
||||
|
||||
//! Delete records of the given types
|
||||
bool EraseRecords(const std::unordered_set<std::string>& types);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <wallet/wallettool.h>
|
||||
|
||||
#include <common/args.h>
|
||||
#include <util/check.h>
|
||||
#include <util/fs.h>
|
||||
#include <util/translation.h>
|
||||
#include <wallet/dump.h>
|
||||
@ -33,12 +34,8 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag
|
||||
wallet_instance->SetMinVersion(FEATURE_LATEST);
|
||||
wallet_instance->InitWalletFlags(wallet_creation_flags);
|
||||
|
||||
if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
|
||||
spk_man->SetupGeneration(false);
|
||||
} else {
|
||||
wallet_instance->SetupDescriptorScriptPubKeyMans();
|
||||
}
|
||||
Assert(wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
|
||||
wallet_instance->SetupDescriptorScriptPubKeyMans();
|
||||
|
||||
tfm::format(std::cout, "Topping up keypool...\n");
|
||||
wallet_instance->TopUpKeyPool();
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
# race (TODO fix)
|
||||
race:LoadWallet
|
||||
race:WalletBatch::WriteHDChain
|
||||
race:BerkeleyBatch
|
||||
race:DatabaseBatch
|
||||
race:zmq::*
|
||||
race:bitcoin-qt
|
||||
|
Loading…
Reference in New Issue
Block a user