Skip to content

Commit f5813bd

Browse files
committed
Add logic to track pubkeys as watch-only, not just scripts
1 parent d3354c5 commit f5813bd

File tree

6 files changed

+49
-10
lines changed

6 files changed

+49
-10
lines changed

src/keystore.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,30 @@
66
#include "keystore.h"
77

88
#include "key.h"
9+
#include "pubkey.h"
910
#include "util.h"
1011

1112
#include <boost/foreach.hpp>
1213

13-
bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
14+
bool CKeyStore::AddKey(const CKey &key) {
15+
return AddKeyPubKey(key, key.GetPubKey());
16+
}
17+
18+
bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
1419
{
1520
CKey key;
16-
if (!GetKey(address, key))
21+
if (!GetKey(address, key)) {
22+
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
23+
if (it != mapWatchKeys.end()) {
24+
vchPubKeyOut = it->second;
25+
return true;
26+
}
1727
return false;
28+
}
1829
vchPubKeyOut = key.GetPubKey();
1930
return true;
2031
}
2132

22-
bool CKeyStore::AddKey(const CKey &key) {
23-
return AddKeyPubKey(key, key.GetPubKey());
24-
}
25-
2633
bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
2734
{
2835
LOCK(cs_KeyStore);
@@ -58,17 +65,39 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut)
5865
return false;
5966
}
6067

68+
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
69+
{
70+
//TODO: Use Solver to extract this?
71+
CScript::const_iterator pc = dest.begin();
72+
opcodetype opcode;
73+
std::vector<unsigned char> vch;
74+
if (!dest.GetOp(pc, opcode, vch) || vch.size() < 33 || vch.size() > 65)
75+
return false;
76+
pubKeyOut = CPubKey(vch);
77+
if (!pubKeyOut.IsFullyValid())
78+
return false;
79+
if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || dest.GetOp(pc, opcode, vch))
80+
return false;
81+
return true;
82+
}
83+
6184
bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
6285
{
6386
LOCK(cs_KeyStore);
6487
setWatchOnly.insert(dest);
88+
CPubKey pubKey;
89+
if (ExtractPubKey(dest, pubKey))
90+
mapWatchKeys[pubKey.GetID()] = pubKey;
6591
return true;
6692
}
6793

6894
bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
6995
{
7096
LOCK(cs_KeyStore);
7197
setWatchOnly.erase(dest);
98+
CPubKey pubKey;
99+
if (ExtractPubKey(dest, pubKey))
100+
mapWatchKeys.erase(pubKey.GetID());
72101
return true;
73102
}
74103

src/keystore.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class CKeyStore
3232
virtual bool HaveKey(const CKeyID &address) const =0;
3333
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
3434
virtual void GetKeys(std::set<CKeyID> &setAddress) const =0;
35-
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
35+
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0;
3636

3737
//! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
3838
virtual bool AddCScript(const CScript& redeemScript) =0;
@@ -47,6 +47,7 @@ class CKeyStore
4747
};
4848

4949
typedef std::map<CKeyID, CKey> KeyMap;
50+
typedef std::map<CKeyID, CPubKey> WatchKeyMap;
5051
typedef std::map<CScriptID, CScript > ScriptMap;
5152
typedef std::set<CScript> WatchOnlySet;
5253

@@ -55,11 +56,13 @@ class CBasicKeyStore : public CKeyStore
5556
{
5657
protected:
5758
KeyMap mapKeys;
59+
WatchKeyMap mapWatchKeys;
5860
ScriptMap mapScripts;
5961
WatchOnlySet setWatchOnly;
6062

6163
public:
6264
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
65+
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
6366
bool HaveKey(const CKeyID &address) const
6467
{
6568
bool result;

src/qt/sendcoinsdialog.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,10 +752,9 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
752752
}
753753
else // Valid address
754754
{
755-
CPubKey pubkey;
756755
CKeyID keyid;
757756
addr.GetKeyID(keyid);
758-
if (!model->getPubKey(keyid, pubkey)) // Unknown change address
757+
if (!model->havePrivKey(keyid)) // Unknown change address
759758
{
760759
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
761760
}

src/qt/walletmodel.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
554554
return wallet->GetPubKey(address, vchPubKeyOut);
555555
}
556556

557+
bool WalletModel::havePrivKey(const CKeyID &address) const
558+
{
559+
return wallet->HaveKey(address);
560+
}
561+
557562
// returns a list of COutputs from COutPoints
558563
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
559564
{

src/qt/walletmodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class WalletModel : public QObject
186186
UnlockContext requestUnlock();
187187

188188
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
189+
bool havePrivKey(const CKeyID &address) const;
189190
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
190191
bool isSpent(const COutPoint& outpoint) const;
191192
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;

src/wallet/crypter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,16 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co
255255
{
256256
LOCK(cs_KeyStore);
257257
if (!IsCrypted())
258-
return CKeyStore::GetPubKey(address, vchPubKeyOut);
258+
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
259259

260260
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
261261
if (mi != mapCryptedKeys.end())
262262
{
263263
vchPubKeyOut = (*mi).second.first;
264264
return true;
265265
}
266+
// Check for watch-only pubkeys
267+
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
266268
}
267269
return false;
268270
}

0 commit comments

Comments
 (0)