OP_EVAL implementation
[novacoin.git] / src / keystore.cpp
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
6 #include "headers.h"
7 #include "db.h"
8 #include "crypter.h"
9
10 std::vector<unsigned char> CKeyStore::GenerateNewKey()
11 {
12     RandAddSeedPerfmon();
13     CKey key;
14     key.MakeNewKey();
15     if (!AddKey(key))
16         throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
17     return key.GetPubKey();
18 }
19
20 bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
21 {
22     CKey key;
23     if (!GetKey(address, key))
24         return false;
25     vchPubKeyOut = key.GetPubKey();
26     return true;
27 }
28
29 bool CBasicKeyStore::AddKey(const CKey& key)
30 {
31     CRITICAL_BLOCK(cs_KeyStore)
32         mapKeys[CBitcoinAddress(key.GetPubKey())] = key.GetSecret();
33     return true;
34 }
35
36 bool CBasicKeyStore::AddCScript(const uint160 &hash, const std::vector<unsigned char>& data)
37 {
38     CRITICAL_BLOCK(cs_KeyStore)
39         mapData[hash] = data;
40     return true;
41 }
42
43 bool CBasicKeyStore::HaveCScript(const uint160& hash) const
44 {
45     bool result;
46     CRITICAL_BLOCK(cs_KeyStore)
47         result = (mapData.count(hash) > 0);
48     return result;
49 }
50
51
52 bool CBasicKeyStore::GetCScript(const uint160 &hash, std::vector<unsigned char>& dataOut) const
53 {
54     CRITICAL_BLOCK(cs_KeyStore)
55     {
56         DataMap::const_iterator mi = mapData.find(hash);
57         if (mi != mapData.end())
58         {
59             dataOut = (*mi).second;
60             return true;
61         }
62     }
63     return false;
64 }
65
66 bool CCryptoKeyStore::SetCrypted()
67 {
68     CRITICAL_BLOCK(cs_KeyStore)
69     {
70         if (fUseCrypto)
71             return true;
72         if (!mapKeys.empty())
73             return false;
74         fUseCrypto = true;
75     }
76     return true;
77 }
78
79 std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
80 {
81     RandAddSeedPerfmon();
82     CKey key;
83     key.MakeNewKey();
84     if (!AddKey(key))
85         throw std::runtime_error("CCryptoKeyStore::GenerateNewKey() : AddKey failed");
86     return key.GetPubKey();
87 }
88
89 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
90 {
91     CRITICAL_BLOCK(cs_KeyStore)
92     {
93         if (!SetCrypted())
94             return false;
95
96         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
97         for (; mi != mapCryptedKeys.end(); ++mi)
98         {
99             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
100             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
101             CSecret vchSecret;
102             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
103                 return false;
104             CKey key;
105             key.SetSecret(vchSecret);
106             if (key.GetPubKey() == vchPubKey)
107                 break;
108             return false;
109         }
110         vMasterKey = vMasterKeyIn;
111     }
112     return true;
113 }
114
115 bool CCryptoKeyStore::AddKey(const CKey& key)
116 {
117     CRITICAL_BLOCK(cs_KeyStore)
118     {
119         if (!IsCrypted())
120             return CBasicKeyStore::AddKey(key);
121
122         if (IsLocked())
123             return false;
124
125         std::vector<unsigned char> vchCryptedSecret;
126         std::vector<unsigned char> vchPubKey = key.GetPubKey();
127         if (!EncryptSecret(vMasterKey, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
128             return false;
129
130         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
131             return false;
132     }
133     return true;
134 }
135
136
137 bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
138 {
139     CRITICAL_BLOCK(cs_KeyStore)
140     {
141         if (!SetCrypted())
142             return false;
143
144         mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
145     }
146     return true;
147 }
148
149 bool CCryptoKeyStore::GetSecret(const CBitcoinAddress &address, CSecret& vchSecretOut) const
150 {
151     CRITICAL_BLOCK(cs_KeyStore)
152     {
153         if (!IsCrypted())
154             return CBasicKeyStore::GetSecret(address, vchSecretOut);
155
156         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
157         if (mi != mapCryptedKeys.end())
158         {
159             const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
160             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
161             return DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecretOut);
162         }
163     }
164     return false;
165 }
166
167 bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
168 {
169     CRITICAL_BLOCK(cs_KeyStore)
170     {
171         if (!IsCrypted())
172             return CKeyStore::GetPubKey(address, vchPubKeyOut);
173
174         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
175         if (mi != mapCryptedKeys.end())
176         {
177             vchPubKeyOut = (*mi).second.first;
178             return true;
179         }
180     }
181     return false;
182 }
183
184 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
185 {
186     CRITICAL_BLOCK(cs_KeyStore)
187     {
188         if (!mapCryptedKeys.empty() || IsCrypted())
189             return false;
190
191         fUseCrypto = true;
192         CKey key;
193         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
194         {
195             if (!key.SetSecret(mKey.second))
196                 return false;
197             const std::vector<unsigned char> vchPubKey = key.GetPubKey();
198             std::vector<unsigned char> vchCryptedSecret;
199             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
200                 return false;
201             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
202                 return false;
203         }
204         mapKeys.clear();
205     }
206     return true;
207 }