Add logic to track pubkeys as watch-only, not just scripts
This commit is contained in:
parent
d3354c52d7
commit
f5813bdd3e
@ -6,23 +6,30 @@
|
||||
#include "keystore.h"
|
||||
|
||||
#include "key.h"
|
||||
#include "pubkey.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
|
||||
{
|
||||
CKey key;
|
||||
if (!GetKey(address, key))
|
||||
return false;
|
||||
vchPubKeyOut = key.GetPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKeyStore::AddKey(const CKey &key) {
|
||||
return AddKeyPubKey(key, key.GetPubKey());
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
|
||||
{
|
||||
CKey key;
|
||||
if (!GetKey(address, key)) {
|
||||
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
|
||||
if (it != mapWatchKeys.end()) {
|
||||
vchPubKeyOut = it->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
vchPubKeyOut = key.GetPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@ -58,10 +65,29 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut)
|
||||
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) || vch.size() < 33 || vch.size() > 65)
|
||||
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 CBasicKeyStore::AddWatchOnly(const CScript &dest)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
setWatchOnly.insert(dest);
|
||||
CPubKey pubKey;
|
||||
if (ExtractPubKey(dest, pubKey))
|
||||
mapWatchKeys[pubKey.GetID()] = pubKey;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -69,6 +95,9 @@ bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
setWatchOnly.erase(dest);
|
||||
CPubKey pubKey;
|
||||
if (ExtractPubKey(dest, pubKey))
|
||||
mapWatchKeys.erase(pubKey.GetID());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
virtual bool HaveKey(const CKeyID &address) const =0;
|
||||
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
|
||||
virtual void GetKeys(std::set<CKeyID> &setAddress) const =0;
|
||||
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0;
|
||||
|
||||
//! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
|
||||
virtual bool AddCScript(const CScript& redeemScript) =0;
|
||||
@ -47,6 +47,7 @@ public:
|
||||
};
|
||||
|
||||
typedef std::map<CKeyID, CKey> KeyMap;
|
||||
typedef std::map<CKeyID, CPubKey> WatchKeyMap;
|
||||
typedef std::map<CScriptID, CScript > ScriptMap;
|
||||
typedef std::set<CScript> WatchOnlySet;
|
||||
|
||||
@ -55,11 +56,13 @@ class CBasicKeyStore : public CKeyStore
|
||||
{
|
||||
protected:
|
||||
KeyMap mapKeys;
|
||||
WatchKeyMap mapWatchKeys;
|
||||
ScriptMap mapScripts;
|
||||
WatchOnlySet setWatchOnly;
|
||||
|
||||
public:
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
bool result;
|
||||
|
@ -752,10 +752,9 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
|
||||
}
|
||||
else // Valid address
|
||||
{
|
||||
CPubKey pubkey;
|
||||
CKeyID keyid;
|
||||
addr.GetKeyID(keyid);
|
||||
if (!model->getPubKey(keyid, pubkey)) // Unknown change address
|
||||
if (!model->havePrivKey(keyid)) // Unknown change address
|
||||
{
|
||||
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
|
||||
}
|
||||
|
@ -554,6 +554,11 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
return wallet->GetPubKey(address, vchPubKeyOut);
|
||||
}
|
||||
|
||||
bool WalletModel::havePrivKey(const CKeyID &address) const
|
||||
{
|
||||
return wallet->HaveKey(address);
|
||||
}
|
||||
|
||||
// returns a list of COutputs from COutPoints
|
||||
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
|
||||
{
|
||||
|
@ -186,6 +186,7 @@ public:
|
||||
UnlockContext requestUnlock();
|
||||
|
||||
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
bool havePrivKey(const CKeyID &address) const;
|
||||
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
|
||||
bool isSpent(const COutPoint& outpoint) const;
|
||||
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;
|
||||
|
@ -255,7 +255,7 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
@ -263,6 +263,8 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
// Check for watch-only pubkeys
|
||||
return CBasicKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user