Use scoped locks instead of CRITICAL_BLOCK
[novacoin.git] / src / keystore.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "crypter.h"
8 #include "db.h"
9 #include "script.h"
10
11 bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
12 {
13     CKey key;
14     if (!GetKey(address, key))
15         return false;
16     vchPubKeyOut = key.GetPubKey();
17     return true;
18 }
19
20 bool CBasicKeyStore::AddKey(const CKey& key)
21 {
22     bool fCompressed = false;
23     CSecret secret = key.GetSecret(fCompressed);
24     {
25         LOCK(cs_KeyStore);
26         mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
27     }
28     return true;
29 }
30
31 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
32 {
33     {
34         LOCK(cs_KeyStore);
35         mapScripts[Hash160(redeemScript)] = redeemScript;
36     }
37     return true;
38 }
39
40 bool CBasicKeyStore::HaveCScript(const uint160& hash) const
41 {
42     bool result;
43     {
44         LOCK(cs_KeyStore);
45         result = (mapScripts.count(hash) > 0);
46     }
47     return result;
48 }
49
50
51 bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
52 {
53     {
54         LOCK(cs_KeyStore);
55         ScriptMap::const_iterator mi = mapScripts.find(hash);
56         if (mi != mapScripts.end())
57         {
58             redeemScriptOut = (*mi).second;
59             return true;
60         }
61     }
62     return false;
63 }
64
65 bool CCryptoKeyStore::SetCrypted()
66 {
67     {
68         LOCK(cs_KeyStore);
69         if (fUseCrypto)
70             return true;
71         if (!mapKeys.empty())
72             return false;
73         fUseCrypto = true;
74     }
75     return true;
76 }
77
78 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
79 {
80     {
81         LOCK(cs_KeyStore);
82         if (!SetCrypted())
83             return false;
84
85         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
86         for (; mi != mapCryptedKeys.end(); ++mi)
87         {
88             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
89             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
90             CSecret vchSecret;
91             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
92                 return false;
93             if (vchSecret.size() != 32)
94                 return false;
95             CKey key;
96             key.SetPubKey(vchPubKey);
97             key.SetSecret(vchSecret);
98             if (key.GetPubKey() == vchPubKey)
99                 break;
100             return false;
101         }
102         vMasterKey = vMasterKeyIn;
103     }
104     return true;
105 }
106
107 bool CCryptoKeyStore::AddKey(const CKey& key)
108 {
109     {
110         LOCK(cs_KeyStore);
111         if (!IsCrypted())
112             return CBasicKeyStore::AddKey(key);
113
114         if (IsLocked())
115             return false;
116
117         std::vector<unsigned char> vchCryptedSecret;
118         std::vector<unsigned char> vchPubKey = key.GetPubKey();
119         bool fCompressed;
120         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
121             return false;
122
123         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
124             return false;
125     }
126     return true;
127 }
128
129
130 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
131 {
132     {
133         LOCK(cs_KeyStore);
134         if (!SetCrypted())
135             return false;
136
137         mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
138     }
139     return true;
140 }
141
142 bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
143 {
144     {
145         LOCK(cs_KeyStore);
146         if (!IsCrypted())
147             return CBasicKeyStore::GetKey(address, keyOut);
148
149         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
150         if (mi != mapCryptedKeys.end())
151         {
152             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
153             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
154             CSecret vchSecret;
155             if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
156                 return false;
157             if (vchSecret.size() != 32)
158                 return false;
159             keyOut.SetPubKey(vchPubKey);
160             keyOut.SetSecret(vchSecret);
161             return true;
162         }
163     }
164     return false;
165 }
166
167 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
168 {
169     {
170         LOCK(cs_KeyStore);
171         if (!IsCrypted())
172             return CKeyStore::GetPubKey(address, vchPubKeyOut);
173
174         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
175         if (mi != mapCryptedKeys.end())
176         {
177             vchPubKeyOut = (*mi).second.first;
178             return true;
179         }
180     }
181     return false;
182 }
183
184 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
185 {
186     {
187         LOCK(cs_KeyStore);
188         if (!mapCryptedKeys.empty() || IsCrypted())
189             return false;
190
191         fUseCrypto = true;
192         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
193         {
194             CKey key;
195             if (!key.SetSecret(mKey.second.first, mKey.second.second))
196                 return false;
197             const std::vector<unsigned char> vchPubKey = key.GetPubKey();
198             std::vector<unsigned char> vchCryptedSecret;
199             bool fCompressed;
200             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
201                 return false;
202             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
203                 return false;
204         }
205         mapKeys.clear();
206     }
207     return true;
208 }