ef617484f8b52ffc5e8f0271eda551ca0cb2e972
[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 COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "keystore.h"
7 #include "script.h"
8 #include "base58.h"
9
10 extern bool fWalletUnlockMintOnly;
11
12 bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
13 {
14     CKey key;
15     if (!GetKey(address, key))
16         return false;
17     vchPubKeyOut = key.GetPubKey();
18     return true;
19 }
20
21 bool CBasicKeyStore::AddKey(const CKey& key)
22 {
23     bool fCompressed = false;
24     CSecret secret = key.GetSecret(fCompressed);
25     {
26         LOCK(cs_KeyStore);
27         mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed);
28     }
29     return true;
30 }
31
32 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
33 {
34     if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
35         return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
36
37     {
38         LOCK(cs_KeyStore);
39         mapScripts[redeemScript.GetID()] = redeemScript;
40     }
41     return true;
42 }
43
44 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
45 {
46     bool result;
47     {
48         LOCK(cs_KeyStore);
49         result = (mapScripts.count(hash) > 0);
50     }
51     return result;
52 }
53
54
55 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
56 {
57     {
58         LOCK(cs_KeyStore);
59         ScriptMap::const_iterator mi = mapScripts.find(hash);
60         if (mi != mapScripts.end())
61         {
62             redeemScriptOut = (*mi).second;
63             return true;
64         }
65     }
66     return false;
67 }
68
69 bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
70 {
71     LOCK(cs_KeyStore);
72
73     CTxDestination address;
74     if (ExtractDestination(dest, address)) {
75         CKeyID keyID;
76         CBitcoinAddress(address).GetKeyID(keyID);
77         if (HaveKey(keyID))
78             return false;
79     }
80
81     setWatchOnly.insert(dest);
82     return true;
83 }
84
85
86 bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
87 {
88     LOCK(cs_KeyStore);
89     setWatchOnly.erase(dest);
90     return true;
91 }
92
93 bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
94 {
95     LOCK(cs_KeyStore);
96     return setWatchOnly.count(dest) > 0;
97 }
98
99 bool CBasicKeyStore::HaveWatchOnly() const
100 {
101     LOCK(cs_KeyStore);
102     return (!setWatchOnly.empty());
103 }
104
105 bool CCryptoKeyStore::SetCrypted()
106 {
107     {
108         LOCK(cs_KeyStore);
109         if (fUseCrypto)
110             return true;
111         if (!mapKeys.empty())
112             return false;
113         fUseCrypto = true;
114     }
115     return true;
116 }
117
118 bool CCryptoKeyStore::Lock()
119 {
120     if (!SetCrypted())
121         return false;
122
123     {
124         LOCK(cs_KeyStore);
125         vMasterKey.clear();
126         fWalletUnlockMintOnly = false;
127     }
128
129     NotifyStatusChanged(this);
130     return true;
131 }
132
133 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
134 {
135     {
136         LOCK(cs_KeyStore);
137         if (!SetCrypted())
138             return false;
139
140         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
141         for (; mi != mapCryptedKeys.end(); ++mi)
142         {
143             const CPubKey &vchPubKey = (*mi).second.first;
144             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
145             CSecret vchSecret;
146             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
147                 return false;
148             if (vchSecret.size() != 32)
149                 return false;
150             CKey key;
151             key.SetPubKey(vchPubKey);
152             key.SetSecret(vchSecret);
153             if (key.GetPubKey() == vchPubKey)
154                 break;
155             return false;
156         }
157         vMasterKey = vMasterKeyIn;
158     }
159     NotifyStatusChanged(this);
160     return true;
161 }
162
163 bool CCryptoKeyStore::AddKey(const CKey& key)
164 {
165     {
166         LOCK(cs_KeyStore);
167
168         CScript script;
169         script.SetDestination(key.GetPubKey().GetID());
170
171         if (HaveWatchOnly(script))
172             return false;
173
174         if (!IsCrypted())
175             return CBasicKeyStore::AddKey(key);
176
177         if (IsLocked())
178             return false;
179
180         std::vector<unsigned char> vchCryptedSecret;
181         CPubKey vchPubKey = key.GetPubKey();
182         bool fCompressed;
183         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
184             return false;
185
186         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
187             return false;
188     }
189     return true;
190 }
191
192
193 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
194 {
195     {
196         LOCK(cs_KeyStore);
197         if (!SetCrypted())
198             return false;
199
200         mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
201     }
202     return true;
203 }
204
205 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
206 {
207     {
208         LOCK(cs_KeyStore);
209         if (!IsCrypted())
210             return CBasicKeyStore::GetKey(address, keyOut);
211
212         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
213         if (mi != mapCryptedKeys.end())
214         {
215             const CPubKey &vchPubKey = (*mi).second.first;
216             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
217             CSecret vchSecret;
218             if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
219                 return false;
220             if (vchSecret.size() != 32)
221                 return false;
222             keyOut.SetPubKey(vchPubKey);
223             keyOut.SetSecret(vchSecret);
224             return true;
225         }
226     }
227     return false;
228 }
229
230 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
231 {
232     {
233         LOCK(cs_KeyStore);
234         if (!IsCrypted())
235             return CKeyStore::GetPubKey(address, vchPubKeyOut);
236
237         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
238         if (mi != mapCryptedKeys.end())
239         {
240             vchPubKeyOut = (*mi).second.first;
241             return true;
242         }
243     }
244     return false;
245 }
246
247 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
248 {
249     {
250         LOCK(cs_KeyStore);
251         if (!mapCryptedKeys.empty() || IsCrypted())
252             return false;
253
254         fUseCrypto = true;
255         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
256         {
257             CKey key;
258             if (!key.SetSecret(mKey.second.first, mKey.second.second))
259                 return false;
260             const CPubKey vchPubKey = key.GetPubKey();
261             std::vector<unsigned char> vchCryptedSecret;
262             bool fCompressed;
263             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
264                 return false;
265             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
266                 return false;
267         }
268         mapKeys.clear();
269     }
270     return true;
271 }
272
273 bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
274 {
275     {
276         LOCK(cs_KeyStore);
277         if (!IsCrypted())
278             return false;
279
280         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
281         for (; mi != mapCryptedKeys.end(); ++mi)
282         {
283             const CPubKey &vchPubKey = (*mi).second.first;
284             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
285             CSecret vchSecret;
286             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
287                 return false;
288             if (vchSecret.size() != 32)
289                 return false;
290             CKey key;
291             key.SetPubKey(vchPubKey);
292             key.SetSecret(vchSecret);
293             if (!CBasicKeyStore::AddKey(key))
294                 return false;
295         }
296
297         mapCryptedKeys.clear();
298     }
299
300     return true;
301 }