Merge support for watch-only addresses
[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
9 extern bool fWalletUnlockMintOnly;
10
11 bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
12 {
13     CKey key;
14     if (!GetKey(address, key))
15         return false;
16     vchPubKeyOut = key.GetPubKey();
17     return true;
18 }
19
20 bool CBasicKeyStore::AddKey(const CKey& key)
21 {
22     bool fCompressed = false;
23     CSecret secret = key.GetSecret(fCompressed);
24     {
25         LOCK(cs_KeyStore);
26         mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed);
27     }
28     return true;
29 }
30
31 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
32 {
33     {
34         LOCK(cs_KeyStore);
35         mapScripts[redeemScript.GetID()] = redeemScript;
36     }
37     return true;
38 }
39
40 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
41 {
42     bool result;
43     {
44         LOCK(cs_KeyStore);
45         result = (mapScripts.count(hash) > 0);
46     }
47     return result;
48 }
49
50
51 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
52 {
53     {
54         LOCK(cs_KeyStore);
55         ScriptMap::const_iterator mi = mapScripts.find(hash);
56         if (mi != mapScripts.end())
57         {
58             redeemScriptOut = (*mi).second;
59             return true;
60         }
61     }
62     return false;
63 }
64
65 bool CBasicKeyStore::AddWatchOnly(const CTxDestination &dest)
66 {
67     LOCK(cs_KeyStore);
68     setWatchOnly.insert(dest);
69     return true;
70 }
71
72 bool CBasicKeyStore::HaveWatchOnly(const CTxDestination &dest) const
73 {
74     LOCK(cs_KeyStore);
75     return setWatchOnly.count(dest) > 0;
76 }
77
78 bool CCryptoKeyStore::SetCrypted()
79 {
80     {
81         LOCK(cs_KeyStore);
82         if (fUseCrypto)
83             return true;
84         if (!mapKeys.empty())
85             return false;
86         fUseCrypto = true;
87     }
88     return true;
89 }
90
91 bool CCryptoKeyStore::Lock()
92 {
93     if (!SetCrypted())
94         return false;
95
96     {
97         LOCK(cs_KeyStore);
98         vMasterKey.clear();
99         fWalletUnlockMintOnly = false;
100     }
101
102     NotifyStatusChanged(this);
103     return true;
104 }
105
106 bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
107 {
108     {
109         LOCK(cs_KeyStore);
110         if (!SetCrypted())
111             return false;
112
113         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
114         for (; mi != mapCryptedKeys.end(); ++mi)
115         {
116             const CPubKey &vchPubKey = (*mi).second.first;
117             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
118             CSecret vchSecret;
119             if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
120                 return false;
121             if (vchSecret.size() != 32)
122                 return false;
123             CKey key;
124             key.SetPubKey(vchPubKey);
125             key.SetSecret(vchSecret);
126             if (key.GetPubKey() == vchPubKey)
127                 break;
128             return false;
129         }
130         vMasterKey = vMasterKeyIn;
131     }
132     NotifyStatusChanged(this);
133     return true;
134 }
135
136 bool CCryptoKeyStore::AddKey(const CKey& key)
137 {
138     {
139         LOCK(cs_KeyStore);
140         if (!IsCrypted())
141             return CBasicKeyStore::AddKey(key);
142
143         if (IsLocked())
144             return false;
145
146         std::vector<unsigned char> vchCryptedSecret;
147         CPubKey vchPubKey = key.GetPubKey();
148         bool fCompressed;
149         if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
150             return false;
151
152         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
153             return false;
154     }
155     return true;
156 }
157
158
159 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
160 {
161     {
162         LOCK(cs_KeyStore);
163         if (!SetCrypted())
164             return false;
165
166         mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
167     }
168     return true;
169 }
170
171 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
172 {
173     {
174         LOCK(cs_KeyStore);
175         if (!IsCrypted())
176             return CBasicKeyStore::GetKey(address, keyOut);
177
178         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
179         if (mi != mapCryptedKeys.end())
180         {
181             const CPubKey &vchPubKey = (*mi).second.first;
182             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
183             CSecret vchSecret;
184             if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
185                 return false;
186             if (vchSecret.size() != 32)
187                 return false;
188             keyOut.SetPubKey(vchPubKey);
189             keyOut.SetSecret(vchSecret);
190             return true;
191         }
192     }
193     return false;
194 }
195
196 bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
197 {
198     {
199         LOCK(cs_KeyStore);
200         if (!IsCrypted())
201             return CKeyStore::GetPubKey(address, vchPubKeyOut);
202
203         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
204         if (mi != mapCryptedKeys.end())
205         {
206             vchPubKeyOut = (*mi).second.first;
207             return true;
208         }
209     }
210     return false;
211 }
212
213 bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
214 {
215     {
216         LOCK(cs_KeyStore);
217         if (!mapCryptedKeys.empty() || IsCrypted())
218             return false;
219
220         fUseCrypto = true;
221         BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
222         {
223             CKey key;
224             if (!key.SetSecret(mKey.second.first, mKey.second.second))
225                 return false;
226             const CPubKey vchPubKey = key.GetPubKey();
227             std::vector<unsigned char> vchCryptedSecret;
228             bool fCompressed;
229             if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
230                 return false;
231             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
232                 return false;
233         }
234         mapKeys.clear();
235     }
236     return true;
237 }