X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fkeystore.h;h=21930603f7705e39a7b157b1f87249ca30e73789;hb=7f70ddc68f4afa4a87a15e620ba519afbc5c8b15;hp=0dc09f05b8dd38b403aec1ac2c5de846ea030bb8;hpb=0efda1a79eab6dd2e101edc615c6dd14138c31a2;p=novacoin.git diff --git a/src/keystore.h b/src/keystore.h index 0dc09f0..2193060 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -1,51 +1,203 @@ -// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_KEYSTORE_H #define BITCOIN_KEYSTORE_H #include "crypter.h" +#include "sync.h" +#include +#include +class CScript; + +class CNoDestination { +public: + friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; } + friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } +}; + +/** A txout script template with a specific destination. It is either: + * CNoDestination: no destination set + * CKeyID: TX_PUBKEYHASH destination + * CScriptID: TX_SCRIPTHASH destination + * + * A CTxDestination is the internal data type encoded in a CBitcoinAddress. + */ +typedef boost::variant CTxDestination; + +/** A virtual base class for key stores */ class CKeyStore { -public: +protected: mutable CCriticalSection cs_KeyStore; +public: + virtual ~CKeyStore() {} + + // Add a key to the store. virtual bool AddKey(const CKey& key) =0; - virtual bool HaveKey(const std::vector &vchPubKey) const =0; - virtual bool GetPrivKey(const std::vector &vchPubKey, CKey& keyOut) const =0; - virtual std::vector GenerateNewKey(); + + // Add a malleable key to store. + virtual bool AddMalleableKey(const CMalleableKey& mKey) =0; + virtual bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const =0; + + // Check whether a key corresponding to a given address is present in the store. + virtual bool HaveKey(const CKeyID &address) const =0; + virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0; + virtual void GetKeys(std::set &setAddress) const =0; + virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; + + // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013 + virtual bool AddCScript(const CScript& redeemScript) =0; + virtual bool HaveCScript(const CScriptID &hash) const =0; + virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; + + // Support for Watch-only addresses + virtual bool AddWatchOnly(const CScript &dest) =0; + virtual bool RemoveWatchOnly(const CScript &dest) =0; + virtual bool HaveWatchOnly(const CScript &dest) const =0; + virtual bool HaveWatchOnly() const =0; + + virtual bool GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const + { + CKey key; + if (!GetKey(address, key)) + return false; + vchSecret = key.GetSecret(fCompressed); + return true; + } + + virtual bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const =0; + virtual bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const =0; + virtual void ListMalleableViews(std::list &malleableViewList) const =0; }; -typedef std::map, CPrivKey> KeyMap; +typedef std::map > KeyMap; +typedef std::map ScriptMap; +typedef std::set WatchOnlySet; +typedef std::map MalleableKeyMap; +/** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore { protected: KeyMap mapKeys; + MalleableKeyMap mapMalleableKeys; + + ScriptMap mapScripts; + WatchOnlySet setWatchOnly; public: bool AddKey(const CKey& key); - bool HaveKey(const std::vector &vchPubKey) const + bool AddMalleableKey(const CMalleableKey& mKey); + bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const + { + { + LOCK(cs_KeyStore); + MalleableKeyMap::const_iterator mi = mapMalleableKeys.find(keyView); + if (mi != mapMalleableKeys.end()) + { + mKey = mi->second; + return true; + } + } + return false; + } + + bool HaveKey(const CKeyID &address) const + { + bool result; + { + LOCK(cs_KeyStore); + result = (mapKeys.count(address) > 0); + } + return result; + } + void GetKeys(std::set &setAddress) const + { + setAddress.clear(); + { + LOCK(cs_KeyStore); + KeyMap::const_iterator mi = mapKeys.begin(); + while (mi != mapKeys.end()) + { + setAddress.insert((*mi).first); + mi++; + } + } + } + bool GetKey(const CKeyID &address, CKey &keyOut) const + { + { + LOCK(cs_KeyStore); + KeyMap::const_iterator mi = mapKeys.find(address); + if (mi != mapKeys.end()) + { + keyOut.Reset(); + keyOut.SetSecret((*mi).second.first, (*mi).second.second); + return true; + } + } + return false; + } + virtual bool AddCScript(const CScript& redeemScript); + virtual bool HaveCScript(const CScriptID &hash) const; + virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; + + virtual bool AddWatchOnly(const CScript &dest); + virtual bool RemoveWatchOnly(const CScript &dest); + virtual bool HaveWatchOnly(const CScript &dest) const; + virtual bool HaveWatchOnly() const; + + bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const { - return (mapKeys.count(vchPubKey) > 0); + { + LOCK(cs_KeyStore); + for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++) + { + if (mi->first.CheckKeyVariant(R, pubKeyVariant)) + return true; + } + } + return false; } - bool GetPrivKey(const std::vector &vchPubKey, CKey& keyOut) const + + bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const { - std::map, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey); - if (mi != mapKeys.end()) { - keyOut.SetPrivKey((*mi).second); - return true; + LOCK(cs_KeyStore); + for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++) + { + if (mi->second.CheckKeyVariant(R, pubKeyVariant, privKey)) + return true; + } } return false; } + + void ListMalleableViews(std::list &malleableViewList) const + { + malleableViewList.clear(); + + { + LOCK(cs_KeyStore); + for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++) + malleableViewList.push_back(CMalleableKeyView(mi->first)); + } + } }; +typedef std::map > > CryptedKeyMap; + +/** Keystore which keeps the private keys encrypted. + * It derives from the basic key store, which is used if no encryption is active. + */ class CCryptoKeyStore : public CBasicKeyStore { private: - std::map, std::vector > mapCryptedKeys; + CryptedKeyMap mapCryptedKeys; CKeyingMaterial vMasterKey; @@ -54,27 +206,16 @@ private: bool fUseCrypto; protected: - bool SetCrypted() - { - if (fUseCrypto) - return true; - if (!mapKeys.empty()) - return false; - fUseCrypto = true; - return true; - } + bool SetCrypted(); // will encrypt previously unencrypted keys bool EncryptKeys(CKeyingMaterial& vMasterKeyIn); + bool DecryptKeys(const CKeyingMaterial& vMasterKeyIn); bool Unlock(const CKeyingMaterial& vMasterKeyIn); public: - mutable CCriticalSection cs_vMasterKey; //No guarantees master key wont get locked before you can use it, so lock this first - - CCryptoKeyStore() : fUseCrypto(false) - { - } + CCryptoKeyStore() : fUseCrypto(false) { } bool IsCrypted() const { @@ -85,31 +226,49 @@ public: { if (!IsCrypted()) return false; - return vMasterKey.empty(); + bool result; + { + LOCK(cs_KeyStore); + result = vMasterKey.empty(); + } + return result; } - bool Lock() + bool Lock(); + + virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); + bool AddKey(const CKey& key); + bool HaveKey(const CKeyID &address) const { - CRITICAL_BLOCK(cs_vMasterKey) { - if (!SetCrypted()) - return false; - - vMasterKey.clear(); + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::HaveKey(address); + return mapCryptedKeys.count(address) > 0; } - return true; } - - virtual bool AddCryptedKey(const std::vector &vchPubKey, const std::vector &vchCryptedSecret); - std::vector GenerateNewKey(); - bool AddKey(const CKey& key); - bool HaveKey(const std::vector &vchPubKey) const + bool GetKey(const CKeyID &address, CKey& keyOut) const; + bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; + void GetKeys(std::set &setAddress) const { if (!IsCrypted()) - return CBasicKeyStore::HaveKey(vchPubKey); - return mapCryptedKeys.count(vchPubKey) > 0; + { + CBasicKeyStore::GetKeys(setAddress); + return; + } + setAddress.clear(); + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + while (mi != mapCryptedKeys.end()) + { + setAddress.insert((*mi).first); + mi++; + } } - bool GetPrivKey(const std::vector &vchPubKey, CKey& keyOut) const; + + /* Wallet status (encrypted, locked) changed. + * Note: Called without locks held. + */ + boost::signals2::signal NotifyStatusChanged; }; #endif