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