aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorAndrew Chow <[email protected]>2019-06-17 17:46:52 -0400
committerAndrew Chow <[email protected]>2019-07-09 16:20:18 -0400
commit93ce4a0b6fb54efb1f424a71dfc09cc33307e5b9 (patch)
tree6c909466c7cc676aa7ec477e89c0c4ab87f65fd3 /src/wallet
parentRemove CCryptoKeyStore and move all of it's functionality into CWallet (diff)
downloaddiscoin-93ce4a0b6fb54efb1f424a71dfc09cc33307e5b9.tar.xz
discoin-93ce4a0b6fb54efb1f424a71dfc09cc33307e5b9.zip
Move WatchOnly stuff from SigningProvider to CWallet
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet.cpp78
-rw-r--r--src/wallet/wallet.h15
2 files changed, 84 insertions, 9 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 0a915ff9a..f4472d5bf 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -455,9 +455,37 @@ bool CWallet::LoadCScript(const CScript& 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)
{
- if (!FillableSigningProvider::AddWatchOnly(dest))
+ if (!AddWatchOnlyInMem(dest))
return false;
const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
UpdateTimeFirstKey(meta.nCreateTime);
@@ -490,8 +518,17 @@ bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
bool CWallet::RemoveWatchOnly(const CScript &dest)
{
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())
NotifyWatchonlyChanged(false);
if (!WalletBatch(*database).EraseWatchOnly(dest))
@@ -502,7 +539,19 @@ bool CWallet::RemoveWatchOnly(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)
@@ -4687,11 +4736,26 @@ bool CWallet::GetKey(const CKeyID &address, CKey& keyOut) const
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
{
LOCK(cs_KeyStore);
- if (!IsCrypted())
- return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
+ if (!IsCrypted()) {
+ if (!FillableSigningProvider::GetPubKey(address, vchPubKeyOut)) {
+ return GetWatchPubKey(address, vchPubKeyOut);
+ }
+ return true;
+ }
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
if (mi != mapCryptedKeys.end())
@@ -4700,7 +4764,7 @@ bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
return true;
}
// Check for watch-only pubkeys
- return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
+ return GetWatchPubKey(address, vchPubKeyOut);
}
std::set<CKeyID> CWallet::GetKeys() const
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index bd92147a5..80fb128f8 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -724,6 +724,8 @@ private:
bool fDecryptionThoroughlyChecked;
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();
@@ -732,6 +734,8 @@ private:
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
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 AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
@@ -818,8 +822,9 @@ private:
* of the other AddWatchOnly which accepts a timestamp and sets
* 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 AddWatchOnlyInMem(const CScript &dest);
/** Add a KeyOriginInfo to the wallet */
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.
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)
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().
int64_t nRelockTime = 0;