Move WatchOnly stuff from SigningProvider to CWallet
This commit is contained in:
parent
8f5b81e6ed
commit
93ce4a0b6f
4 changed files with 84 additions and 79 deletions
|
@ -73,8 +73,6 @@ void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pu
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_KeyStore);
|
AssertLockHeld(cs_KeyStore);
|
||||||
CKeyID key_id = pubkey.GetID();
|
CKeyID key_id = pubkey.GetID();
|
||||||
// We must actually know about this key already.
|
|
||||||
assert(HaveKey(key_id) || mapWatchKeys.count(key_id));
|
|
||||||
// This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
|
// This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
|
||||||
// outputs. Technically P2WPKH outputs don't have a redeemscript to be
|
// outputs. Technically P2WPKH outputs don't have a redeemscript to be
|
||||||
// spent. However, our current IsMine logic requires the corresponding
|
// spent. However, our current IsMine logic requires the corresponding
|
||||||
|
@ -98,12 +96,6 @@ bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKe
|
||||||
{
|
{
|
||||||
CKey key;
|
CKey key;
|
||||||
if (!GetKey(address, key)) {
|
if (!GetKey(address, key)) {
|
||||||
LOCK(cs_KeyStore);
|
|
||||||
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
|
|
||||||
if (it != mapWatchKeys.end()) {
|
|
||||||
vchPubKeyOut = it->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vchPubKeyOut = key.GetPubKey();
|
vchPubKeyOut = key.GetPubKey();
|
||||||
|
@ -183,59 +175,6 @@ bool FillableSigningProvider::GetCScript(const CScriptID &hash, CScript& redeemS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
|
|
||||||
{
|
|
||||||
//TODO: Use Solver to extract this?
|
|
||||||
CScript::const_iterator pc = dest.begin();
|
|
||||||
opcodetype opcode;
|
|
||||||
std::vector<unsigned char> vch;
|
|
||||||
if (!dest.GetOp(pc, opcode, vch) || !CPubKey::ValidSize(vch))
|
|
||||||
return false;
|
|
||||||
pubKeyOut = CPubKey(vch);
|
|
||||||
if (!pubKeyOut.IsFullyValid())
|
|
||||||
return false;
|
|
||||||
if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || dest.GetOp(pc, opcode, vch))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FillableSigningProvider::AddWatchOnly(const CScript &dest)
|
|
||||||
{
|
|
||||||
LOCK(cs_KeyStore);
|
|
||||||
setWatchOnly.insert(dest);
|
|
||||||
CPubKey pubKey;
|
|
||||||
if (ExtractPubKey(dest, pubKey)) {
|
|
||||||
mapWatchKeys[pubKey.GetID()] = pubKey;
|
|
||||||
ImplicitlyLearnRelatedKeyScripts(pubKey);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FillableSigningProvider::RemoveWatchOnly(const CScript &dest)
|
|
||||||
{
|
|
||||||
LOCK(cs_KeyStore);
|
|
||||||
setWatchOnly.erase(dest);
|
|
||||||
CPubKey pubKey;
|
|
||||||
if (ExtractPubKey(dest, pubKey)) {
|
|
||||||
mapWatchKeys.erase(pubKey.GetID());
|
|
||||||
}
|
|
||||||
// Related CScripts are not removed; having superfluous scripts around is
|
|
||||||
// harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FillableSigningProvider::HaveWatchOnly(const CScript &dest) const
|
|
||||||
{
|
|
||||||
LOCK(cs_KeyStore);
|
|
||||||
return setWatchOnly.count(dest) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FillableSigningProvider::HaveWatchOnly() const
|
|
||||||
{
|
|
||||||
LOCK(cs_KeyStore);
|
|
||||||
return (!setWatchOnly.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest)
|
CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest)
|
||||||
{
|
{
|
||||||
// Only supports destinations which map to single public keys, i.e. P2PKH,
|
// Only supports destinations which map to single public keys, i.e. P2PKH,
|
||||||
|
|
|
@ -66,14 +66,10 @@ protected:
|
||||||
mutable CCriticalSection cs_KeyStore;
|
mutable CCriticalSection cs_KeyStore;
|
||||||
|
|
||||||
using KeyMap = std::map<CKeyID, CKey>;
|
using KeyMap = std::map<CKeyID, CKey>;
|
||||||
using WatchKeyMap = std::map<CKeyID, CPubKey>;
|
|
||||||
using ScriptMap = std::map<CScriptID, CScript>;
|
using ScriptMap = std::map<CScriptID, CScript>;
|
||||||
using WatchOnlySet = std::set<CScript>;
|
|
||||||
|
|
||||||
KeyMap mapKeys GUARDED_BY(cs_KeyStore);
|
KeyMap mapKeys GUARDED_BY(cs_KeyStore);
|
||||||
WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
|
|
||||||
ScriptMap mapScripts GUARDED_BY(cs_KeyStore);
|
ScriptMap mapScripts GUARDED_BY(cs_KeyStore);
|
||||||
WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
|
|
||||||
|
|
||||||
void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
|
||||||
|
|
||||||
|
@ -88,11 +84,6 @@ public:
|
||||||
virtual bool HaveCScript(const CScriptID &hash) const override;
|
virtual bool HaveCScript(const CScriptID &hash) const override;
|
||||||
virtual std::set<CScriptID> GetCScripts() const;
|
virtual std::set<CScriptID> GetCScripts() const;
|
||||||
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
|
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override;
|
||||||
|
|
||||||
virtual bool AddWatchOnly(const CScript &dest);
|
|
||||||
virtual bool RemoveWatchOnly(const CScript &dest);
|
|
||||||
virtual bool HaveWatchOnly(const CScript &dest) const;
|
|
||||||
virtual bool HaveWatchOnly() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Return the CKeyID of the key involved in a script (if there is a unique one). */
|
/** Return the CKeyID of the key involved in a script (if there is a unique one). */
|
||||||
|
|
|
@ -455,9 +455,37 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
|
||||||
return FillableSigningProvider::AddCScript(redeemScript);
|
return FillableSigningProvider::AddCScript(redeemScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
|
||||||
|
{
|
||||||
|
//TODO: Use Solver to extract this?
|
||||||
|
CScript::const_iterator pc = dest.begin();
|
||||||
|
opcodetype opcode;
|
||||||
|
std::vector<unsigned char> vch;
|
||||||
|
if (!dest.GetOp(pc, opcode, vch) || !CPubKey::ValidSize(vch))
|
||||||
|
return false;
|
||||||
|
pubKeyOut = CPubKey(vch);
|
||||||
|
if (!pubKeyOut.IsFullyValid())
|
||||||
|
return false;
|
||||||
|
if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || dest.GetOp(pc, opcode, vch))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddWatchOnlyInMem(const CScript &dest)
|
||||||
|
{
|
||||||
|
LOCK(cs_KeyStore);
|
||||||
|
setWatchOnly.insert(dest);
|
||||||
|
CPubKey pubKey;
|
||||||
|
if (ExtractPubKey(dest, pubKey)) {
|
||||||
|
mapWatchKeys[pubKey.GetID()] = pubKey;
|
||||||
|
ImplicitlyLearnRelatedKeyScripts(pubKey);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CWallet::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest)
|
bool CWallet::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest)
|
||||||
{
|
{
|
||||||
if (!FillableSigningProvider::AddWatchOnly(dest))
|
if (!AddWatchOnlyInMem(dest))
|
||||||
return false;
|
return false;
|
||||||
const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
|
const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
|
||||||
UpdateTimeFirstKey(meta.nCreateTime);
|
UpdateTimeFirstKey(meta.nCreateTime);
|
||||||
|
@ -490,8 +518,17 @@ bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
|
||||||
bool CWallet::RemoveWatchOnly(const CScript &dest)
|
bool CWallet::RemoveWatchOnly(const CScript &dest)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
if (!FillableSigningProvider::RemoveWatchOnly(dest))
|
{
|
||||||
return false;
|
LOCK(cs_KeyStore);
|
||||||
|
setWatchOnly.erase(dest);
|
||||||
|
CPubKey pubKey;
|
||||||
|
if (ExtractPubKey(dest, pubKey)) {
|
||||||
|
mapWatchKeys.erase(pubKey.GetID());
|
||||||
|
}
|
||||||
|
// Related CScripts are not removed; having superfluous scripts around is
|
||||||
|
// harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
|
||||||
|
}
|
||||||
|
|
||||||
if (!HaveWatchOnly())
|
if (!HaveWatchOnly())
|
||||||
NotifyWatchonlyChanged(false);
|
NotifyWatchonlyChanged(false);
|
||||||
if (!WalletBatch(*database).EraseWatchOnly(dest))
|
if (!WalletBatch(*database).EraseWatchOnly(dest))
|
||||||
|
@ -502,7 +539,19 @@ bool CWallet::RemoveWatchOnly(const CScript &dest)
|
||||||
|
|
||||||
bool CWallet::LoadWatchOnly(const CScript &dest)
|
bool CWallet::LoadWatchOnly(const CScript &dest)
|
||||||
{
|
{
|
||||||
return FillableSigningProvider::AddWatchOnly(dest);
|
return AddWatchOnlyInMem(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::HaveWatchOnly(const CScript &dest) const
|
||||||
|
{
|
||||||
|
LOCK(cs_KeyStore);
|
||||||
|
return setWatchOnly.count(dest) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::HaveWatchOnly() const
|
||||||
|
{
|
||||||
|
LOCK(cs_KeyStore);
|
||||||
|
return (!setWatchOnly.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
|
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
|
||||||
|
@ -4687,11 +4736,26 @@ bool CWallet::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CWallet::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
|
||||||
|
{
|
||||||
|
LOCK(cs_KeyStore);
|
||||||
|
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
|
||||||
|
if (it != mapWatchKeys.end()) {
|
||||||
|
pubkey_out = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||||
{
|
{
|
||||||
LOCK(cs_KeyStore);
|
LOCK(cs_KeyStore);
|
||||||
if (!IsCrypted())
|
if (!IsCrypted()) {
|
||||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
|
||||||
|
return GetWatchPubKey(address, vchPubKeyOut);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||||
if (mi != mapCryptedKeys.end())
|
if (mi != mapCryptedKeys.end())
|
||||||
|
@ -4700,7 +4764,7 @@ bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Check for watch-only pubkeys
|
// Check for watch-only pubkeys
|
||||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
return GetWatchPubKey(address, vchPubKeyOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<CKeyID> CWallet::GetKeys() const
|
std::set<CKeyID> CWallet::GetKeys() const
|
||||||
|
|
|
@ -724,6 +724,8 @@ private:
|
||||||
bool fDecryptionThoroughlyChecked;
|
bool fDecryptionThoroughlyChecked;
|
||||||
|
|
||||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||||
|
using WatchOnlySet = std::set<CScript>;
|
||||||
|
using WatchKeyMap = std::map<CKeyID, CPubKey>;
|
||||||
|
|
||||||
bool SetCrypted();
|
bool SetCrypted();
|
||||||
|
|
||||||
|
@ -732,6 +734,8 @@ private:
|
||||||
|
|
||||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
|
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
|
||||||
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
|
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
|
||||||
|
WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
|
||||||
|
WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
|
||||||
|
|
||||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||||
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
|
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
|
||||||
|
@ -818,8 +822,9 @@ private:
|
||||||
* of the other AddWatchOnly which accepts a timestamp and sets
|
* of the other AddWatchOnly which accepts a timestamp and sets
|
||||||
* nTimeFirstKey more intelligently for more efficient rescans.
|
* nTimeFirstKey more intelligently for more efficient rescans.
|
||||||
*/
|
*/
|
||||||
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool AddWatchOnly(const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
bool AddWatchOnlyInMem(const CScript &dest);
|
||||||
|
|
||||||
/** Add a KeyOriginInfo to the wallet */
|
/** Add a KeyOriginInfo to the wallet */
|
||||||
bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
|
bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
|
||||||
|
@ -1039,9 +1044,15 @@ public:
|
||||||
|
|
||||||
//! Adds a watch-only address to the store, and saves it to disk.
|
//! Adds a watch-only address to the store, and saves it to disk.
|
||||||
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
bool RemoveWatchOnly(const CScript &dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
bool RemoveWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
|
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
|
||||||
bool LoadWatchOnly(const CScript &dest);
|
bool LoadWatchOnly(const CScript &dest);
|
||||||
|
//! Returns whether the watch-only script is in the wallet
|
||||||
|
bool HaveWatchOnly(const CScript &dest) const;
|
||||||
|
//! Returns whether there are any watch-only things in the wallet
|
||||||
|
bool HaveWatchOnly() const;
|
||||||
|
//! Fetches a pubkey from mapWatchKeys if it exists there
|
||||||
|
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
|
||||||
|
|
||||||
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
|
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
|
||||||
int64_t nRelockTime = 0;
|
int64_t nRelockTime = 0;
|
||||||
|
|
Loading…
Reference in a new issue