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