Changeset View
Changeset View
Standalone View
Standalone View
src/keystore.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <keystore.h> | #include <keystore.h> | ||||
#include <key.h> | #include <key.h> | ||||
#include <pubkey.h> | #include <pubkey.h> | ||||
#include <util/system.h> | #include <util/system.h> | ||||
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey &pubkey) { | void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts( | ||||
const CPubKey &pubkey) { | |||||
AssertLockHeld(cs_KeyStore); | AssertLockHeld(cs_KeyStore); | ||||
CKeyID key_id = pubkey.GetID(); | CKeyID key_id = pubkey.GetID(); | ||||
// We must actually know about this key already. | // We must actually know about this key already. | ||||
assert(HaveKey(key_id) || mapWatchKeys.count(key_id)); | assert(HaveKey(key_id) || mapWatchKeys.count(key_id)); | ||||
// This adds the redeemscripts necessary to detect alternative outputs using | // This adds the redeemscripts necessary to detect alternative outputs using | ||||
// the same keys. Also note that having superfluous scripts in the keystore | // the same keys. Also note that having superfluous scripts in the keystore | ||||
// never hurts. They're only used to guide recursion in signing and IsMine | // never hurts. They're only used to guide recursion in signing and IsMine | ||||
// logic - if a script is present but we can't do anything with it, it has | // logic - if a script is present but we can't do anything with it, it has | ||||
// no effect. "Implicitly" refers to fact that scripts are derived | // no effect. "Implicitly" refers to fact that scripts are derived | ||||
// automatically from existing keys, and are present in memory, even without | // automatically from existing keys, and are present in memory, even without | ||||
// being explicitly loaded (e.g. from a file). | // being explicitly loaded (e.g. from a file). | ||||
// Right now there are none so do nothing. | // Right now there are none so do nothing. | ||||
} | } | ||||
bool CBasicKeyStore::GetPubKey(const CKeyID &address, | bool FillableSigningProvider::GetPubKey(const CKeyID &address, | ||||
CPubKey &vchPubKeyOut) const { | CPubKey &vchPubKeyOut) const { | ||||
CKey key; | CKey key; | ||||
if (!GetKey(address, key)) { | if (!GetKey(address, key)) { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
WatchKeyMap::const_iterator it = mapWatchKeys.find(address); | WatchKeyMap::const_iterator it = mapWatchKeys.find(address); | ||||
if (it != mapWatchKeys.end()) { | if (it != mapWatchKeys.end()) { | ||||
vchPubKeyOut = it->second; | vchPubKeyOut = it->second; | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
vchPubKeyOut = key.GetPubKey(); | vchPubKeyOut = key.GetPubKey(); | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::AddKeyPubKey(const CKey &key, const CPubKey &pubkey) { | bool FillableSigningProvider::AddKeyPubKey(const CKey &key, | ||||
const CPubKey &pubkey) { | |||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
mapKeys[pubkey.GetID()] = key; | mapKeys[pubkey.GetID()] = key; | ||||
ImplicitlyLearnRelatedKeyScripts(pubkey); | ImplicitlyLearnRelatedKeyScripts(pubkey); | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::HaveKey(const CKeyID &address) const { | bool FillableSigningProvider::HaveKey(const CKeyID &address) const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
return mapKeys.count(address) > 0; | return mapKeys.count(address) > 0; | ||||
} | } | ||||
std::set<CKeyID> CBasicKeyStore::GetKeys() const { | std::set<CKeyID> FillableSigningProvider::GetKeys() const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
std::set<CKeyID> set_address; | std::set<CKeyID> set_address; | ||||
for (const auto &mi : mapKeys) { | for (const auto &mi : mapKeys) { | ||||
set_address.insert(mi.first); | set_address.insert(mi.first); | ||||
} | } | ||||
return set_address; | return set_address; | ||||
} | } | ||||
bool CBasicKeyStore::GetKey(const CKeyID &address, CKey &keyOut) const { | bool FillableSigningProvider::GetKey(const CKeyID &address, | ||||
CKey &keyOut) const { | |||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
KeyMap::const_iterator mi = mapKeys.find(address); | KeyMap::const_iterator mi = mapKeys.find(address); | ||||
if (mi != mapKeys.end()) { | if (mi != mapKeys.end()) { | ||||
keyOut = mi->second; | keyOut = mi->second; | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
bool CBasicKeyStore::AddCScript(const CScript &redeemScript) { | bool FillableSigningProvider::AddCScript(const CScript &redeemScript) { | ||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { | if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { | ||||
return error("CBasicKeyStore::AddCScript(): redeemScripts > %i bytes " | return error( | ||||
"FillableSigningProvider::AddCScript(): redeemScripts > %i bytes " | |||||
"are invalid", | "are invalid", | ||||
MAX_SCRIPT_ELEMENT_SIZE); | MAX_SCRIPT_ELEMENT_SIZE); | ||||
} | } | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
mapScripts[CScriptID(redeemScript)] = redeemScript; | mapScripts[CScriptID(redeemScript)] = redeemScript; | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::HaveCScript(const CScriptID &hash) const { | bool FillableSigningProvider::HaveCScript(const CScriptID &hash) const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
return mapScripts.count(hash) > 0; | return mapScripts.count(hash) > 0; | ||||
} | } | ||||
std::set<CScriptID> CBasicKeyStore::GetCScripts() const { | std::set<CScriptID> FillableSigningProvider::GetCScripts() const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
std::set<CScriptID> set_script; | std::set<CScriptID> set_script; | ||||
for (const auto &mi : mapScripts) { | for (const auto &mi : mapScripts) { | ||||
set_script.insert(mi.first); | set_script.insert(mi.first); | ||||
} | } | ||||
return set_script; | return set_script; | ||||
} | } | ||||
bool CBasicKeyStore::GetCScript(const CScriptID &hash, | bool FillableSigningProvider::GetCScript(const CScriptID &hash, | ||||
CScript &redeemScriptOut) const { | CScript &redeemScriptOut) const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
ScriptMap::const_iterator mi = mapScripts.find(hash); | ScriptMap::const_iterator mi = mapScripts.find(hash); | ||||
if (mi != mapScripts.end()) { | if (mi != mapScripts.end()) { | ||||
redeemScriptOut = (*mi).second; | redeemScriptOut = (*mi).second; | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
Show All 12 Lines | static bool ExtractPubKey(const CScript &dest, CPubKey &pubKeyOut) { | ||||
} | } | ||||
if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || | if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || | ||||
dest.GetOp(pc, opcode, vch)) { | dest.GetOp(pc, opcode, vch)) { | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::AddWatchOnly(const CScript &dest) { | bool FillableSigningProvider::AddWatchOnly(const CScript &dest) { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
setWatchOnly.insert(dest); | setWatchOnly.insert(dest); | ||||
CPubKey pubKey; | CPubKey pubKey; | ||||
if (ExtractPubKey(dest, pubKey)) { | if (ExtractPubKey(dest, pubKey)) { | ||||
mapWatchKeys[pubKey.GetID()] = pubKey; | mapWatchKeys[pubKey.GetID()] = pubKey; | ||||
ImplicitlyLearnRelatedKeyScripts(pubKey); | ImplicitlyLearnRelatedKeyScripts(pubKey); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest) { | bool FillableSigningProvider::RemoveWatchOnly(const CScript &dest) { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
setWatchOnly.erase(dest); | setWatchOnly.erase(dest); | ||||
CPubKey pubKey; | CPubKey pubKey; | ||||
if (ExtractPubKey(dest, pubKey)) { | if (ExtractPubKey(dest, pubKey)) { | ||||
mapWatchKeys.erase(pubKey.GetID()); | mapWatchKeys.erase(pubKey.GetID()); | ||||
} | } | ||||
// Related CScripts are not removed; having superfluous scripts around is | // Related CScripts are not removed; having superfluous scripts around is | ||||
// harmless (see comment in ImplicitlyLearnRelatedKeyScripts). | // harmless (see comment in ImplicitlyLearnRelatedKeyScripts). | ||||
return true; | return true; | ||||
} | } | ||||
bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const { | bool FillableSigningProvider::HaveWatchOnly(const CScript &dest) const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
return setWatchOnly.count(dest) > 0; | return setWatchOnly.count(dest) > 0; | ||||
} | } | ||||
bool CBasicKeyStore::HaveWatchOnly() const { | bool FillableSigningProvider::HaveWatchOnly() const { | ||||
LOCK(cs_KeyStore); | LOCK(cs_KeyStore); | ||||
return (!setWatchOnly.empty()); | return (!setWatchOnly.empty()); | ||||
} | } | ||||
CKeyID GetKeyForDestination(const CBasicKeyStore &store, | CKeyID GetKeyForDestination(const FillableSigningProvider &store, | ||||
const CTxDestination &dest) { | 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. | ||||
if (auto id = boost::get<PKHash>(&dest)) { | if (auto id = boost::get<PKHash>(&dest)) { | ||||
return CKeyID(*id); | return CKeyID(*id); | ||||
} | } | ||||
return CKeyID(); | return CKeyID(); | ||||
} | } |