Use scoped locks instead of CRITICAL_BLOCK
[novacoin.git] / src / keystore.h
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 #ifndef BITCOIN_KEYSTORE_H
6 #define BITCOIN_KEYSTORE_H
7
8 #include "crypter.h"
9 #include "script.h"
10
11 /** A virtual base class for key stores */
12 class CKeyStore
13 {
14 protected:
15     mutable CCriticalSection cs_KeyStore;
16
17 public:
18     // Add a key to the store.
19     virtual bool AddKey(const CKey& key) =0;
20
21     // Check whether a key corresponding to a given address is present in the store.
22     virtual bool HaveKey(const CBitcoinAddress &address) const =0;
23     virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
24     virtual void GetKeys(std::set<CBitcoinAddress> &setAddress) const =0;
25     virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
26
27     // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
28     virtual bool AddCScript(const CScript& redeemScript) =0;
29     virtual bool HaveCScript(const uint160 &hash) const =0;
30     virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const =0;
31
32     virtual bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret, bool &fCompressed) const
33     {
34         CKey key;
35         if (!GetKey(address, key))
36             return false;
37         vchSecret = key.GetSecret(fCompressed);
38         return true;
39     }
40 };
41
42 typedef std::map<CBitcoinAddress, std::pair<CSecret, bool> > KeyMap;
43 typedef std::map<uint160, CScript > ScriptMap;
44
45 /** Basic key store, that keeps keys in an address->secret map */
46 class CBasicKeyStore : public CKeyStore
47 {
48 protected:
49     KeyMap mapKeys;
50     ScriptMap mapScripts;
51
52 public:
53     bool AddKey(const CKey& key);
54     bool HaveKey(const CBitcoinAddress &address) const
55     {
56         bool result;
57         {
58             LOCK(cs_KeyStore);
59             result = (mapKeys.count(address) > 0);
60         }
61         return result;
62     }
63     void GetKeys(std::set<CBitcoinAddress> &setAddress) const
64     {
65         setAddress.clear();
66         {
67             LOCK(cs_KeyStore);
68             KeyMap::const_iterator mi = mapKeys.begin();
69             while (mi != mapKeys.end())
70             {
71                 setAddress.insert((*mi).first);
72                 mi++;
73             }
74         }
75     }
76     bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
77     {
78         {
79             LOCK(cs_KeyStore);
80             KeyMap::const_iterator mi = mapKeys.find(address);
81             if (mi != mapKeys.end())
82             {
83                 keyOut.Reset();
84                 keyOut.SetSecret((*mi).second.first, (*mi).second.second);
85                 return true;
86             }
87         }
88         return false;
89     }
90     virtual bool AddCScript(const CScript& redeemScript);
91     virtual bool HaveCScript(const uint160 &hash) const;
92     virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const;
93 };
94
95 typedef std::map<CBitcoinAddress, std::pair<std::vector<unsigned char>, std::vector<unsigned char> > > CryptedKeyMap;
96
97 /** Keystore which keeps the private keys encrypted.
98  * It derives from the basic key store, which is used if no encryption is active.
99  */
100 class CCryptoKeyStore : public CBasicKeyStore
101 {
102 private:
103     CryptedKeyMap mapCryptedKeys;
104
105     CKeyingMaterial vMasterKey;
106
107     // if fUseCrypto is true, mapKeys must be empty
108     // if fUseCrypto is false, vMasterKey must be empty
109     bool fUseCrypto;
110
111 protected:
112     bool SetCrypted();
113
114     // will encrypt previously unencrypted keys
115     bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
116
117     bool Unlock(const CKeyingMaterial& vMasterKeyIn);
118
119 public:
120     CCryptoKeyStore() : fUseCrypto(false)
121     {
122     }
123
124     bool IsCrypted() const
125     {
126         return fUseCrypto;
127     }
128
129     bool IsLocked() const
130     {
131         if (!IsCrypted())
132             return false;
133         bool result;
134         {
135             LOCK(cs_KeyStore);
136             result = vMasterKey.empty();
137         }
138         return result;
139     }
140
141     bool Lock()
142     {
143         if (!SetCrypted())
144             return false;
145
146         {
147             LOCK(cs_KeyStore);
148             vMasterKey.clear();
149         }
150
151         return true;
152     }
153
154     virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
155     bool AddKey(const CKey& key);
156     bool HaveKey(const CBitcoinAddress &address) const
157     {
158         {
159             LOCK(cs_KeyStore);
160             if (!IsCrypted())
161                 return CBasicKeyStore::HaveKey(address);
162             return mapCryptedKeys.count(address) > 0;
163         }
164         return false;
165     }
166     bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
167     bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
168     void GetKeys(std::set<CBitcoinAddress> &setAddress) const
169     {
170         if (!IsCrypted())
171         {
172             CBasicKeyStore::GetKeys(setAddress);
173             return;
174         }
175         setAddress.clear();
176         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
177         while (mi != mapCryptedKeys.end())
178         {
179             setAddress.insert((*mi).first);
180             mi++;
181         }
182     }
183 };
184
185 #endif