X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fkeystore.cpp;h=0aca325fd3bcfd9be91e0645268c68a18ffe5913;hp=23f9e32fa2a08cd815a5fa42d8a9404eaac971c8;hb=415da519893e8fef7a10007fc82934385addd03d;hpb=e5c027b49b72d8245ebec26cb92d918377fd81e0 diff --git a/src/keystore.cpp b/src/keystore.cpp index 23f9e32..0aca325 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -1,14 +1,15 @@ // 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. -#include "headers.h" -#include "crypter.h" -#include "db.h" +#include "keystore.h" #include "script.h" +#include "base58.h" -bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector &vchPubKeyOut) const +extern bool fWalletUnlockMintOnly; + +bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const { CKey key; if (!GetKey(address, key)) @@ -21,31 +22,49 @@ bool CBasicKeyStore::AddKey(const CKey& key) { bool fCompressed = false; CSecret secret = key.GetSecret(fCompressed); - CRITICAL_BLOCK(cs_KeyStore) - mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed); + { + LOCK(cs_KeyStore); + mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed); + } + return true; +} + +bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH) +{ + { + LOCK(cs_KeyStore); + mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH; + } return true; } bool CBasicKeyStore::AddCScript(const CScript& redeemScript) { - CRITICAL_BLOCK(cs_KeyStore) - mapScripts[Hash160(redeemScript)] = redeemScript; + if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) + return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE); + + { + LOCK(cs_KeyStore); + mapScripts[redeemScript.GetID()] = redeemScript; + } return true; } -bool CBasicKeyStore::HaveCScript(const uint160& hash) const +bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const { bool result; - CRITICAL_BLOCK(cs_KeyStore) + { + LOCK(cs_KeyStore); result = (mapScripts.count(hash) > 0); + } return result; } -bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const +bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); ScriptMap::const_iterator mi = mapScripts.find(hash); if (mi != mapScripts.end()) { @@ -56,10 +75,46 @@ bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) c return false; } +bool CBasicKeyStore::AddWatchOnly(const CScript &dest) +{ + LOCK(cs_KeyStore); + + CTxDestination address; + if (ExtractDestination(dest, address)) { + CKeyID keyID; + CBitcoinAddress(address).GetKeyID(keyID); + if (HaveKey(keyID)) + return false; + } + + setWatchOnly.insert(dest); + return true; +} + + +bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest) +{ + LOCK(cs_KeyStore); + setWatchOnly.erase(dest); + return true; +} + +bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const +{ + LOCK(cs_KeyStore); + return setWatchOnly.count(dest) > 0; +} + +bool CBasicKeyStore::HaveWatchOnly() const +{ + LOCK(cs_KeyStore); + return (!setWatchOnly.empty()); +} + bool CCryptoKeyStore::SetCrypted() { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); if (fUseCrypto) return true; if (!mapKeys.empty()) @@ -69,39 +124,63 @@ bool CCryptoKeyStore::SetCrypted() return true; } +bool CCryptoKeyStore::Lock() +{ + if (!SetCrypted()) + return false; + + { + LOCK(cs_KeyStore); + vMasterKey.clear(); + fWalletUnlockMintOnly = false; + } + + NotifyStatusChanged(this); + return true; +} + bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); if (!SetCrypted()) return false; CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); for (; mi != mapCryptedKeys.end(); ++mi) { - const std::vector &vchPubKey = (*mi).second.first; + const CPubKey &vchPubKey = (*mi).second.first; const std::vector &vchCryptedSecret = (*mi).second.second; CSecret vchSecret; - if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret)) + if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) return false; if (vchSecret.size() != 32) return false; CKey key; - key.SetPubKey(vchPubKey); key.SetSecret(vchSecret); + key.SetCompressedPubKey(vchPubKey.IsCompressed()); if (key.GetPubKey() == vchPubKey) break; return false; } + vMasterKey = vMasterKeyIn; } + NotifyStatusChanged(this); return true; } bool CCryptoKeyStore::AddKey(const CKey& key) { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); + + CScript script; + script.SetDestination(key.GetPubKey().GetID()); + + if (HaveWatchOnly(script)) + return false; + if (!IsCrypted()) return CBasicKeyStore::AddKey(key); @@ -109,9 +188,9 @@ bool CCryptoKeyStore::AddKey(const CKey& key) return false; std::vector vchCryptedSecret; - std::vector vchPubKey = key.GetPubKey(); + CPubKey vchPubKey = key.GetPubKey(); bool fCompressed; - if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret)) + if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret)) return false; if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret)) @@ -120,48 +199,135 @@ bool CCryptoKeyStore::AddKey(const CKey& key) return true; } +bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH) +{ + { + LOCK(cs_KeyStore); + if (!SetCrypted()) + return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH); + + if (IsLocked()) + return false; + + CKey keyH; + keyH.SetSecret(vchSecretH, true); + + std::vector vchCryptedSecretH; + if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH)) + return false; + + if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH)) + return false; + } + return true; +} + +bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) +{ + { + LOCK(cs_KeyStore); + if (!SetCrypted()) + return false; + + mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret); + } + return true; +} -bool CCryptoKeyStore::AddCryptedKey(const std::vector &vchPubKey, const std::vector &vchCryptedSecret) +bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector &vchCryptedSecretH) { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); if (!SetCrypted()) return false; - mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret); + mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH; } return true; } -bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const +bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey); + + for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++) + { + if (mi->first.CheckKeyVariant(R, pubKeyVariant)) + { + const CPubKey H = mi->first.GetMalleablePubKey().GetH(); + + CSecret vchSecretH; + if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH)) + return false; + if (vchSecretH.size() != 32) + return false; + + CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH); + return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);; + } + } + + } + return true; +} + +bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::GetMalleableKey(keyView, mKey); + CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.find(keyView); + if (mi != mapCryptedMalleableKeys.end()) + { + const CPubKey H = keyView.GetMalleablePubKey().GetH(); + + CSecret vchSecretH; + if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH)) + return false; + + if (vchSecretH.size() != 32) + return false; + mKey = mi->first.GetMalleableKey(vchSecretH); + + return true; + } + } + return false; +} + +bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); if (!IsCrypted()) return CBasicKeyStore::GetKey(address, keyOut); CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); if (mi != mapCryptedKeys.end()) { - const std::vector &vchPubKey = (*mi).second.first; + const CPubKey &vchPubKey = (*mi).second.first; const std::vector &vchCryptedSecret = (*mi).second.second; CSecret vchSecret; - if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret)) + if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) return false; if (vchSecret.size() != 32) return false; - keyOut.SetPubKey(vchPubKey); keyOut.SetSecret(vchSecret); + keyOut.SetCompressedPubKey(vchPubKey.IsCompressed()); return true; } } return false; } -bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector& vchPubKeyOut) const +bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const { - CRITICAL_BLOCK(cs_KeyStore) { + LOCK(cs_KeyStore); if (!IsCrypted()) return CKeyStore::GetPubKey(address, vchPubKeyOut); @@ -177,8 +343,8 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector vchPubKey = key.GetPubKey(); + const CPubKey vchPubKey = key.GetPubKey(); std::vector vchCryptedSecret; bool fCompressed; - if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret)) + if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret)) return false; if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) return false; } mapKeys.clear(); + + BOOST_FOREACH(MalleableKeyMap::value_type& mKey, mapMalleableKeys) + { + const CPubKey vchPubKeyH = mKey.first.GetMalleablePubKey().GetH(); + std::vector vchCryptedSecretH; + if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH)) + return false; + if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH)) + return false; + } + mapMalleableKeys.clear(); } return true; } + +bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn) +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return false; + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + for (; mi != mapCryptedKeys.end(); ++mi) + { + const CPubKey &vchPubKey = (*mi).second.first; + const std::vector &vchCryptedSecret = (*mi).second.second; + CSecret vchSecret; + if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) + return false; + if (vchSecret.size() != 32) + return false; + CKey key; + key.SetSecret(vchSecret); + key.SetCompressedPubKey(vchPubKey.IsCompressed()); + if (!CBasicKeyStore::AddKey(key)) + return false; + } + + mapCryptedKeys.clear(); + + CryptedMalleableKeyMap::const_iterator mi2 = mapCryptedMalleableKeys.begin(); + for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2) + { + const CPubKey vchPubKeyH = mi2->first.GetMalleablePubKey().GetH(); + + CSecret vchSecretH; + if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH)) + return false; + if (vchSecretH.size() != 32) + return false; + + if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH)) + return false; + } + mapCryptedMalleableKeys.clear(); + } + + return true; +}