Make keystore.h bit compact
[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 CKeyStore::GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const
22 {
23     CKey key;
24     if (!GetKey(address, key))
25         return false;
26     vchSecret = key.GetSecret(fCompressed);
27     return true;
28 }
29
30 bool CBasicKeyStore::AddKey(const CKey& key)
31 {
32     bool fCompressed = false;
33     auto secret = key.GetSecret(fCompressed);
34     {
35         LOCK(cs_KeyStore);
36         mapKeys[key.GetPubKey().GetID()] = { secret, fCompressed };
37     }
38     return true;
39 }
40
41 bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH)
42 {
43     {
44         LOCK(cs_KeyStore);
45         mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH;
46     }
47     return true;
48 }
49
50 bool CBasicKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
51 {
52     {
53         LOCK(cs_KeyStore);
54         MalleableKeyMap::const_iterator mi = mapMalleableKeys.find(keyView);
55         if (mi != mapMalleableKeys.end())
56         {
57             mKey = mi->first.GetMalleableKey(mi->second);
58             return true;
59         }
60     }
61     return false;
62 }
63
64 bool CBasicKeyStore::HaveKey(const CKeyID &address) const
65 {
66     bool result;
67     {
68         LOCK(cs_KeyStore);
69         result = (mapKeys.count(address) > 0);
70     }
71     return result;
72 }
73
74 void CBasicKeyStore::GetKeys(std::set<CKeyID> &setAddress) const
75 {
76     setAddress.clear();
77     {
78         LOCK(cs_KeyStore);
79         KeyMap::const_iterator mi;
80         for (mi = mapKeys.begin(); mi != mapKeys.end(); ++mi) setAddress.insert((*mi).first);
81     }
82 }
83
84 bool CBasicKeyStore::GetKey(const CKeyID &address, CKey &keyOut) const
85 {
86     {
87         LOCK(cs_KeyStore);
88         KeyMap::const_iterator mi = mapKeys.find(address);
89         if (mi != mapKeys.end())
90         {
91             keyOut.SetSecret((*mi).second.first, (*mi).second.second);
92             return true;
93         }
94     }
95     return false;
96 }
97
98 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
99 {
100     if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
101         return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE);
102
103     {
104         LOCK(cs_KeyStore);
105         mapScripts[redeemScript.GetID()] = redeemScript;
106     }
107     return true;
108 }
109
110 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
111 {
112     bool result;
113     {
114         LOCK(cs_KeyStore);
115         result = (mapScripts.count(hash) > 0);
116     }
117     return result;
118 }
119
120
121 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
122 {
123     {
124         LOCK(cs_KeyStore);
125         auto mi = mapScripts.find(hash);
126         if (mi != mapScripts.end())
127         {
128             redeemScriptOut = (*mi).second;
129             return true;
130         }
131     }
132     return false;
133 }
134
135 bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
136 {
137     LOCK(cs_KeyStore);
138
139     CTxDestination address;
140     if (ExtractDestination(dest, address)) {
141         CKeyID keyID;
142         CBitcoinAddress(address).GetKeyID(keyID);
143         if (HaveKey(keyID))
144             return false;
145     }
146
147     setWatchOnly.insert(dest);
148     return true;
149 }
150
151
152 bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
153 {
154     LOCK(cs_KeyStore);
155     setWatchOnly.erase(dest);
156     return true;
157 }
158
159 bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
160 {
161     LOCK(cs_KeyStore);
162     return setWatchOnly.count(dest) > 0;
163 }
164
165 bool CBasicKeyStore::HaveWatchOnly() const
166 {
167     LOCK(cs_KeyStore);
168     return (!setWatchOnly.empty());
169 }
170
171 bool CBasicKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
172 {
173     {
174         LOCK(cs_KeyStore);
175         for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
176         {
177             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
178                 return true;
179         }
180     }
181     return false;
182 }
183
184 bool CBasicKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
185 {
186     {
187         LOCK(cs_KeyStore);
188         for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
189         {
190             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
191             {
192                 view = mi->first;
193                 return true;
194             }
195         }
196     }
197     return false;
198 }
199
200 bool CBasicKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
201 {
202     {
203         LOCK(cs_KeyStore);
204         for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
205         {
206             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
207             {
208                 CMalleableKey mKey = mi->first.GetMalleableKey(mi->second);
209                 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);
210             }
211         }
212     }
213     return false;
214 }
215
216 void CBasicKeyStore::ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
217 {
218     malleableViewList.clear();
219     {
220         LOCK(cs_KeyStore);
221         for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
222             malleableViewList.push_back(CMalleableKeyView(mi->first));
223     }
224 }
225
226 bool CBasicKeyStore::GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
227 {
228     const CKeyID &mpkID = mpk.GetID();
229     {
230         LOCK(cs_KeyStore);
231         for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
232             if (mi->first.GetID() == mpkID)
233             {
234                 view = CMalleableKeyView(mi->first);
235                 return true;
236             }
237     }
238     return false;
239 }
240
241
242 bool CCryptoKeyStore::SetCrypted()
243 {
244     {
245         LOCK(cs_KeyStore);
246         if (fUseCrypto)
247             return true;
248         if (!mapKeys.empty())
249             return false;
250         fUseCrypto = true;
251     }
252     return true;
253 }
254
255 CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
256 {
257 }
258
259 bool CCryptoKeyStore::IsCrypted() const
260 {
261     return fUseCrypto;
262 }
263
264 bool CCryptoKeyStore::IsLocked() const
265 {
266     if (!IsCrypted())
267         return false;
268     bool result;
269     {
270         LOCK(cs_KeyStore);
271         result = vMasterKey.empty();
272     }
273     return result;
274 }
275
276 bool CCryptoKeyStore::Lock()
277 {
278     if (!SetCrypted())
279         return false;
280
281     {
282         LOCK(cs_KeyStore);
283         vMasterKey.clear();
284         fWalletUnlockMintOnly = false;
285     }
286
287     NotifyStatusChanged(this);
288     return true;
289 }
290
291 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
292 {
293     {
294         LOCK(cs_KeyStore);
295         if (!SetCrypted())
296             return false;
297
298         bool keyPass = false;
299         bool keyFail = false;
300
301         // Check regular key pairs
302         {
303             auto mi = mapCryptedKeys.begin();
304             for (; mi != mapCryptedKeys.end(); ++mi)
305             {
306                 const auto &vchPubKey = (*mi).second.first;
307                 const auto &vchCryptedSecret = (*mi).second.second;
308                 CSecret vchSecret;
309                 if (!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
310                 {
311                     keyFail = true;
312                     break;
313                 }
314                 if (vchSecret.size() != 32)
315                 {
316                     keyFail = true;
317                     break;
318                 }
319                 keyPass = true;
320                 if (fDecryptionThoroughlyChecked)
321                     break;
322             }
323         }
324
325         // Check malleable key pairs
326         {
327             if (keyPass && !keyFail)
328             {
329                 auto mi = mapCryptedMalleableKeys.begin();
330                 for(; mi != mapCryptedMalleableKeys.end(); ++mi)
331                 {
332                     const auto &H = mi->first.GetMalleablePubKey().GetH();
333                     CSecret vchSecretH;
334                     if (!DecryptSecret(vMasterKeyIn, mi->second, H.GetHash(), vchSecretH))
335                     {
336                         keyFail = true;
337                         break;
338                     }
339                     if (vchSecretH.size() != 32)
340                     {
341                         keyFail = true;
342                         break;
343                     }
344                     keyPass = true;
345                     if (fDecryptionThoroughlyChecked)
346                         break;
347                 }
348             }
349         }
350
351         if (keyPass && keyFail)
352         {
353             printf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
354             assert(false);
355         }
356         if (keyFail || !keyPass)
357             return false;
358         vMasterKey = vMasterKeyIn;
359         fDecryptionThoroughlyChecked = true;
360     }
361     NotifyStatusChanged(this);
362     return true;
363 }
364
365
366 bool CCryptoKeyStore::AddKey(const CKey& key)
367 {
368     {
369         LOCK(cs_KeyStore);
370
371         CScript script;
372         script.SetDestination(key.GetPubKey().GetID());
373
374         if (HaveWatchOnly(script))
375             return false;
376
377         if (!IsCrypted())
378             return CBasicKeyStore::AddKey(key);
379
380         if (IsLocked())
381             return false;
382
383         std::vector<unsigned char> vchCryptedSecret;
384         auto vchPubKey = key.GetPubKey();
385         bool fCompressed;
386         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
387             return false;
388
389         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
390             return false;
391     }
392     return true;
393 }
394
395 bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
396 {
397     {
398         LOCK(cs_KeyStore);
399         if (!SetCrypted())
400             return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
401
402         if (IsLocked())
403             return false;
404
405         CKey keyH;
406         keyH.SetSecret(vchSecretH, true);
407
408         std::vector<unsigned char> vchCryptedSecretH;
409         if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
410             return false;
411
412         if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
413             return false;
414     }
415     return true;
416 }
417
418 bool CCryptoKeyStore::HaveKey(const CKeyID &address) const
419 {
420     {
421         LOCK(cs_KeyStore);
422         if (!IsCrypted())
423             return CBasicKeyStore::HaveKey(address);
424         return mapCryptedKeys.count(address) > 0;
425     }
426 }
427
428 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
429 {
430     {
431         LOCK(cs_KeyStore);
432         if (!SetCrypted())
433             return false;
434
435         mapCryptedKeys[vchPubKey.GetID()] = { vchPubKey, vchCryptedSecret };
436     }
437     return true;
438 }
439
440 bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>  &vchCryptedSecretH)
441 {
442     {
443         LOCK(cs_KeyStore);
444         if (!SetCrypted())
445             return false;
446
447         mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
448     }
449     return true;
450 }
451
452 bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
453 {
454     {
455         LOCK(cs_KeyStore);
456         if (!IsCrypted())
457             return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
458
459         for (auto mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
460         {
461             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
462             {
463                 const CPubKey H = mi->first.GetMalleablePubKey().GetH();
464
465                 CSecret vchSecretH;
466                 if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
467                     return false;
468                 if (vchSecretH.size() != 32)
469                     return false;
470
471                 CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
472                 return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
473             }
474         }
475
476     }
477     return true;
478 }
479
480 bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
481 {
482     {
483         LOCK(cs_KeyStore);
484         if (!IsCrypted())
485             return CBasicKeyStore::GetMalleableKey(keyView, mKey);
486         auto mi = mapCryptedMalleableKeys.find(keyView);
487         if (mi != mapCryptedMalleableKeys.end())
488         {
489             const CPubKey H = keyView.GetMalleablePubKey().GetH();
490
491             CSecret vchSecretH;
492             if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
493                 return false;
494
495             if (vchSecretH.size() != 32)
496                 return false;
497             mKey = mi->first.GetMalleableKey(vchSecretH);
498
499             return true;
500         }
501     }
502     return false;
503 }
504
505 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
506 {
507     {
508         LOCK(cs_KeyStore);
509         if (!IsCrypted())
510             return CBasicKeyStore::GetKey(address, keyOut);
511
512         auto mi = mapCryptedKeys.find(address);
513         if (mi != mapCryptedKeys.end())
514         {
515             const CPubKey &vchPubKey = (*mi).second.first;
516             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
517             CSecret vchSecret;
518             if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
519                 return false;
520             if (vchSecret.size() != 32)
521                 return false;
522             keyOut.SetSecret(vchSecret);
523             keyOut.SetCompressedPubKey(vchPubKey.IsCompressed());
524             return true;
525         }
526     }
527     return false;
528 }
529
530 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
531 {
532     {
533         LOCK(cs_KeyStore);
534         if (!IsCrypted())
535             return CKeyStore::GetPubKey(address, vchPubKeyOut);
536
537         auto mi = mapCryptedKeys.find(address);
538         if (mi != mapCryptedKeys.end())
539         {
540             vchPubKeyOut = (*mi).second.first;
541             return true;
542         }
543     }
544     return false;
545 }
546
547 void CCryptoKeyStore::GetKeys(std::set<CKeyID> &setAddress) const
548 {
549     if (!IsCrypted())
550     {
551         CBasicKeyStore::GetKeys(setAddress);
552         return;
553     }
554     setAddress.clear();
555     CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
556     while (mi != mapCryptedKeys.end())
557     {
558         setAddress.insert((*mi).first);
559         mi++;
560     }
561 }
562
563 bool CCryptoKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
564 {
565     {
566         LOCK(cs_KeyStore);
567         if (!IsCrypted())
568             return CBasicKeyStore::CheckOwnership(pubKeyVariant, R);
569         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
570         {
571             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
572                 return true;
573         }
574     }
575     return false;
576 }
577
578 bool CCryptoKeyStore::CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
579 {
580     {
581         LOCK(cs_KeyStore);
582         if (!IsCrypted())
583             return CBasicKeyStore::CheckOwnership(pubKeyVariant, R, view);
584         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
585         {
586             if (mi->first.CheckKeyVariant(R, pubKeyVariant))
587             {
588                 view = mi->first;
589                 return true;
590             }
591         }
592     }
593     return false;
594 }
595
596 bool CCryptoKeyStore::CheckOwnership(const CMalleablePubKey &mpk)
597 {
598     CMalleableKeyView view;
599     return GetMalleableView(mpk, view);
600 }
601
602 void CCryptoKeyStore::ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
603 {
604     malleableViewList.clear();
605     {
606         LOCK(cs_KeyStore);
607         if (!IsCrypted())
608             return CBasicKeyStore::ListMalleableViews(malleableViewList);
609         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
610             malleableViewList.push_back(CMalleableKeyView(mi->first));
611     }
612 }
613
614 bool CCryptoKeyStore::GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
615 {
616     const CKeyID &mpkID = mpk.GetID();
617     {
618         LOCK(cs_KeyStore);
619         if (!IsCrypted())
620             return CBasicKeyStore::GetMalleableView(mpk, view);
621         for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
622             if (mi->first.GetID() == mpkID)
623             {
624                 view = CMalleableKeyView(mi->first);
625                 return true;
626             }
627     }
628     return false;
629 }
630
631 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
632 {
633     {
634         LOCK(cs_KeyStore);
635         if (!mapCryptedKeys.empty() || IsCrypted())
636             return false;
637
638         fUseCrypto = true;
639         for(auto& mKey : mapKeys)
640         {
641             CKey key;
642             if (!key.SetSecret(mKey.second.first, mKey.second.second))
643                 return false;
644             const auto vchPubKey = key.GetPubKey();
645             std::vector<unsigned char> vchCryptedSecret;
646             bool fCompressed;
647             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
648                 return false;
649             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
650                 return false;
651         }
652         mapKeys.clear();
653
654         for(auto& mKey : mapMalleableKeys)
655         {
656             const auto vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
657             std::vector<unsigned char> vchCryptedSecretH;
658             if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
659                 return false;
660             if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
661                 return false;
662         }
663         mapMalleableKeys.clear();
664     }
665     return true;
666 }
667
668 bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
669 {
670     {
671         LOCK(cs_KeyStore);
672         if (!IsCrypted())
673             return false;
674
675         auto mi = mapCryptedKeys.begin();
676         for (; mi != mapCryptedKeys.end(); ++mi)
677         {
678             const auto &vchPubKey = (*mi).second.first;
679             const auto &vchCryptedSecret = (*mi).second.second;
680             CSecret vchSecret;
681             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
682                 return false;
683             if (vchSecret.size() != 32)
684                 return false;
685             CKey key;
686             key.SetSecret(vchSecret);
687             key.SetCompressedPubKey(vchPubKey.IsCompressed());
688             if (!CBasicKeyStore::AddKey(key))
689                 return false;
690         }
691
692         mapCryptedKeys.clear();
693
694         auto mi2 = mapCryptedMalleableKeys.begin();
695         for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
696         {
697             const auto vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
698
699             CSecret vchSecretH;
700             if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
701                 return false;
702             if (vchSecretH.size() != 32)
703                 return false;
704
705             if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
706                 return false;
707         }
708         mapCryptedMalleableKeys.clear();
709     }
710
711     return true;
712 }