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