]> Git Repo - VerusCoin.git/blob - src/keystore.cpp
Wallet sync improvements
[VerusCoin.git] / src / keystore.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
5
6 #include "keystore.h"
7
8 #include "key.h"
9 #include "util.h"
10 #include "pbaas/identity.h"
11 #include "cc/CCinclude.h"
12 #include "boost/algorithm/string.hpp"
13
14 #include <boost/foreach.hpp>
15
16 bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
17 {
18     CKey key;
19     if (!GetKey(address, key))
20         return false;
21     vchPubKeyOut = key.GetPubKey();
22     return true;
23 }
24
25 bool CKeyStore::AddKey(const CKey &key) {
26     return AddKeyPubKey(key, key.GetPubKey());
27 }
28
29 bool CBasicKeyStore::SetHDSeed(const HDSeed& seed)
30 {
31     LOCK(cs_SpendingKeyStore);
32     if (!hdSeed.IsNull()) {
33         // Don't allow an existing seed to be changed. We can maybe relax this
34         // restriction later once we have worked out the UX implications.
35         return false;
36     }
37     hdSeed = seed;
38     return true;
39 }
40
41 bool CBasicKeyStore::HaveHDSeed() const
42 {
43     LOCK(cs_SpendingKeyStore);
44     return !hdSeed.IsNull();
45 }
46
47 bool CBasicKeyStore::GetHDSeed(HDSeed& seedOut) const
48 {
49     LOCK(cs_SpendingKeyStore);
50     if (hdSeed.IsNull()) {
51         return false;
52     } else {
53         seedOut = hdSeed;
54         return true;
55     }
56 }
57
58 CScriptID ScriptOrIdentityID(const CScript& scr)
59 {
60     COptCCParams p;
61     CIdentity identity;
62     if (scr.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size() && (identity = CIdentity(p.vData[0])).IsValid())
63     {
64         return CScriptID(identity.GetID());
65     }
66     else
67     {
68         return CScriptID(scr);
69     }
70 }
71
72 bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
73 {
74     LOCK(cs_KeyStore);
75     mapKeys[pubkey.GetID()] = key;
76     return true;
77 }
78
79 bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
80 {
81     if (redeemScript.size() > CScript::MAX_SCRIPT_ELEMENT_SIZE)
82         return error("CBasicKeyStore::AddCScript(): redeemScripts > %i bytes are invalid", CScript::MAX_SCRIPT_ELEMENT_SIZE);
83
84     LOCK(cs_KeyStore);
85     mapScripts[ScriptOrIdentityID(redeemScript)] = redeemScript;
86     return true;
87 }
88
89 bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
90 {
91     LOCK(cs_KeyStore);
92     return mapScripts.count(hash) > 0;
93 }
94
95 bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
96 {
97     LOCK(cs_KeyStore);
98     ScriptMap::const_iterator mi = mapScripts.find(hash);
99     if (mi != mapScripts.end())
100     {
101         redeemScriptOut = (*mi).second;
102         return true;
103     }
104     return false;
105 }
106
107 bool CBasicKeyStore::HaveIdentity(const CIdentityID &idID) const
108 {
109     return mapIdentities.count(CIdentityMapKey(idID).MapKey()) != 0;
110 }
111
112 bool CBasicKeyStore::AddIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
113 {
114     if (mapIdentities.count(mapKey.MapKey()) || !mapKey.IsValid())
115     {
116         return false;
117     }
118     mapIdentities.insert(make_pair(mapKey.MapKey(), identity));
119     return true;
120 }
121
122 bool CBasicKeyStore::UpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
123 {
124     if (!mapIdentities.count(mapKey.MapKey()) || !mapKey.IsValid())
125     {
126         return false;
127     }
128     // erase and insert to replace
129     mapIdentities.erase(mapKey.MapKey());
130     mapIdentities.insert(make_pair(mapKey.MapKey(), identity));
131     return true;
132 }
133
134 bool CBasicKeyStore::AddUpdateIdentity(const CIdentityMapKey &mapKey, const CIdentityMapValue &identity)
135 {
136     arith_uint256 arithKey = mapKey.MapKey();
137     return CBasicKeyStore::AddIdentity(mapKey, identity) || CBasicKeyStore::UpdateIdentity(mapKey, identity);
138 }
139
140 bool CBasicKeyStore::RemoveIdentity(const CIdentityMapKey &mapKey, const uint256 &txid)
141 {
142     auto localKey = mapKey;
143     if (localKey.idID.IsNull())
144     {
145         return false;
146     }
147     auto startIt = mapIdentities.lower_bound(localKey.MapKey());
148     if (localKey.blockHeight == 0)
149     {
150         localKey.blockHeight = 0x7fffffff;
151     }
152
153     if (startIt != mapIdentities.end())
154     {
155         if (txid.IsNull())
156         {
157             mapIdentities.erase(startIt, mapIdentities.upper_bound(localKey.MapKey()));
158         }
159         else
160         {
161             auto endIt = mapIdentities.upper_bound(localKey.MapKey());
162             for (; startIt != endIt; startIt++)
163             {
164                 if (startIt->second.txid == txid)
165                 {
166                     mapIdentities.erase(startIt);
167                     break;
168                 }
169             }
170         }
171         
172         return true;
173     }
174     return false;
175 }
176
177 // return an identity if it is in the store
178 bool CBasicKeyStore::GetIdentity(const CIdentityID &idID, std::pair<CIdentityMapKey, CIdentityMapValue> &keyAndIdentity, uint32_t lteHeight) const
179 {
180     // debug test - comment normally
181     // printf("lower_bound: %s\n", CIdentityMapKey(idID).ToString().c_str());
182     // printf("upper_bound: %s\n", CIdentityMapKey(idID, lteHeight >= INT32_MAX ? INT32_MAX : lteHeight + 1).ToString().c_str());
183     // printf("first: %s\n", mapIdentities.size() ? CIdentityMapKey(mapIdentities.begin()->first).ToString().c_str() : "");
184     // end debug test
185
186     auto itStart = mapIdentities.lower_bound(CIdentityMapKey(idID).MapKey());
187     if (itStart == mapIdentities.end())
188     {
189         return false;
190     } 
191     // point to the last
192     auto itEnd = mapIdentities.upper_bound(CIdentityMapKey(idID, lteHeight >= INT32_MAX ? INT32_MAX : lteHeight + 1).MapKey());
193     if (itEnd == mapIdentities.begin())
194     {
195         return false;
196     }
197
198     itEnd--;
199     CIdentityMapKey foundKey(itEnd->first);
200     if (foundKey.idID != idID)
201     {
202         return false;
203     }
204     keyAndIdentity = make_pair(foundKey, itEnd->second);
205     return true;
206 }
207
208 // return all identities between two map keys, inclusive
209 bool CBasicKeyStore::GetIdentity(const CIdentityMapKey &keyStart, const CIdentityMapKey &keyEnd, std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> &keysAndIdentityUpdates) const
210 {
211     auto itStart = mapIdentities.lower_bound(keyStart.MapKey());
212     if (itStart == mapIdentities.end())
213     {
214         return false;
215     }
216     auto itEnd = mapIdentities.upper_bound(keyEnd.MapKey());
217     for (; itStart != mapIdentities.end() && itStart != itEnd; itStart++)
218     {
219         keysAndIdentityUpdates.push_back(make_pair(CIdentityMapKey(itStart->first), itStart->second));
220     }
221     return true;
222 }
223
224 bool CBasicKeyStore::GetIdentity(const CIdentityMapKey &mapKey, const uint256 &txid, std::pair<CIdentityMapKey, CIdentityMapValue> &keyAndIdentity)
225 {
226     CIdentityMapKey localKey = mapKey;
227     std::vector<std::pair<CIdentityMapKey, CIdentityMapValue>> toCheck;
228     bool found = false;
229
230     if (localKey.blockHeight == 0)
231     {
232         localKey.blockHeight = 0x7fffffff;
233     }
234     if (!GetIdentity(mapKey, localKey, toCheck))
235     {
236         return found;
237     }
238
239     for (auto id : toCheck)
240     {
241         if (id.second.txid == txid)
242         {
243             keyAndIdentity = id;
244             found = true;
245         }
246     }
247     return found;
248 }
249
250 // return the first identity not less than a specific key
251 bool CBasicKeyStore::GetFirstIdentity(const CIdentityID &idID, std::pair<CIdentityMapKey, CIdentityMapValue> &keyAndIdentity, uint32_t gteHeight) const
252 {
253     auto it = mapIdentities.lower_bound(CIdentityMapKey(idID, gteHeight).MapKey());
254     if (it == mapIdentities.end())
255     {
256         return false;
257     }
258     keyAndIdentity = make_pair(CIdentityMapKey(it->first), it->second);
259     return true;
260 }
261
262 bool CBasicKeyStore::GetIdentities(std::vector<std::pair<CIdentityMapKey, CIdentityMapValue *>> &mine, 
263                                    std::vector<std::pair<CIdentityMapKey, CIdentityMapValue *>> &imsigner, 
264                                    std::vector<std::pair<CIdentityMapKey, CIdentityMapValue *>> &notmine)
265 {
266     for (auto &identity : mapIdentities)
267     {
268         CIdentityMapKey idKey(identity.first);
269         if (idKey.flags & idKey.CAN_SPEND)
270         {
271             mine.push_back(make_pair(idKey, &identity.second));
272         }
273         else if (idKey.flags & idKey.CAN_SIGN)
274         {
275             imsigner.push_back(make_pair(idKey, &identity.second));
276         }
277         else
278         {
279             notmine.push_back(make_pair(idKey, &identity.second));
280         }
281     }
282     return (mine.size() || imsigner.size() || notmine.size());
283 }
284
285 bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
286 {
287     LOCK(cs_KeyStore);
288     setWatchOnly.insert(dest);
289     return true;
290 }
291
292 bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
293 {
294     LOCK(cs_KeyStore);
295     setWatchOnly.erase(dest);
296     return true;
297 }
298
299 bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const
300 {
301     LOCK(cs_KeyStore);
302     return setWatchOnly.count(dest) > 0;
303 }
304
305 bool CBasicKeyStore::HaveWatchOnly() const
306 {
307     LOCK(cs_KeyStore);
308     return (!setWatchOnly.empty());
309 }
310
311 bool CBasicKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk)
312 {
313     LOCK(cs_SpendingKeyStore);
314     auto address = sk.address();
315     mapSproutSpendingKeys[address] = sk;
316     mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(sk.receiving_key())));
317     return true;
318 }
319
320 //! Sapling 
321 bool CBasicKeyStore::AddSaplingSpendingKey(
322     const libzcash::SaplingExtendedSpendingKey &sk,
323     const libzcash::SaplingPaymentAddress &defaultAddr)
324 {
325     LOCK(cs_SpendingKeyStore);
326     auto fvk = sk.expsk.full_viewing_key();
327
328     // if SaplingFullViewingKey is not in SaplingFullViewingKeyMap, add it
329     if (!AddSaplingFullViewingKey(fvk, defaultAddr)) {
330         return false;
331     }
332
333     mapSaplingSpendingKeys[fvk] = sk;
334
335     return true;
336 }
337
338 bool CBasicKeyStore::AddSproutViewingKey(const libzcash::SproutViewingKey &vk)
339 {
340     LOCK(cs_SpendingKeyStore);
341     auto address = vk.address();
342     mapSproutViewingKeys[address] = vk;
343     mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(vk.sk_enc)));
344     return true;
345 }
346
347 bool CBasicKeyStore::AddSaplingFullViewingKey(
348     const libzcash::SaplingFullViewingKey &fvk,
349     const libzcash::SaplingPaymentAddress &defaultAddr)
350 {
351     LOCK(cs_SpendingKeyStore);
352     auto ivk = fvk.in_viewing_key();
353     mapSaplingFullViewingKeys[ivk] = fvk;
354
355     return CBasicKeyStore::AddSaplingIncomingViewingKey(ivk, defaultAddr);
356 }
357
358 // This function updates the wallet's internal address->ivk map. 
359 // If we add an address that is already in the map, the map will
360 // remain unchanged as each address only has one ivk.
361 bool CBasicKeyStore::AddSaplingIncomingViewingKey(
362     const libzcash::SaplingIncomingViewingKey &ivk,
363     const libzcash::SaplingPaymentAddress &addr)
364 {
365     LOCK(cs_SpendingKeyStore);
366
367     // Add addr -> SaplingIncomingViewing to SaplingIncomingViewingKeyMap
368     mapSaplingIncomingViewingKeys[addr] = ivk;
369
370     return true;
371 }
372
373 bool CBasicKeyStore::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk)
374 {
375     LOCK(cs_SpendingKeyStore);
376     mapSproutViewingKeys.erase(vk.address());
377     return true;
378 }
379
380 bool CBasicKeyStore::HaveSproutViewingKey(const libzcash::SproutPaymentAddress &address) const
381 {
382     LOCK(cs_SpendingKeyStore);
383     return mapSproutViewingKeys.count(address) > 0;
384 }
385
386 bool CBasicKeyStore::HaveSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk) const
387 {
388     LOCK(cs_SpendingKeyStore);
389     return mapSaplingFullViewingKeys.count(ivk) > 0;
390 }
391
392 bool CBasicKeyStore::HaveSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress &addr) const
393 {
394     LOCK(cs_SpendingKeyStore);
395     return mapSaplingIncomingViewingKeys.count(addr) > 0;
396 }
397
398 bool CBasicKeyStore::GetSproutViewingKey(
399     const libzcash::SproutPaymentAddress &address,
400     libzcash::SproutViewingKey &vkOut) const
401 {
402     LOCK(cs_SpendingKeyStore);
403     SproutViewingKeyMap::const_iterator mi = mapSproutViewingKeys.find(address);
404     if (mi != mapSproutViewingKeys.end()) {
405         vkOut = mi->second;
406         return true;
407     }
408     return false;
409 }
410
411 bool CBasicKeyStore::GetSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk,
412                                    libzcash::SaplingFullViewingKey &fvkOut) const
413 {
414     LOCK(cs_SpendingKeyStore);
415     SaplingFullViewingKeyMap::const_iterator mi = mapSaplingFullViewingKeys.find(ivk);
416     if (mi != mapSaplingFullViewingKeys.end()) {
417         fvkOut = mi->second;
418         return true;
419     }
420     return false;
421 }
422
423 bool CBasicKeyStore::GetSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress &addr,
424                                    libzcash::SaplingIncomingViewingKey &ivkOut) const
425 {
426     LOCK(cs_SpendingKeyStore);
427     SaplingIncomingViewingKeyMap::const_iterator mi = mapSaplingIncomingViewingKeys.find(addr);
428     if (mi != mapSaplingIncomingViewingKeys.end()) {
429         ivkOut = mi->second;
430         return true;
431     }
432     return false;
433 }
434
435 bool CBasicKeyStore::GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymentAddress &addr, 
436                                     libzcash::SaplingExtendedSpendingKey &extskOut) const {
437     libzcash::SaplingIncomingViewingKey ivk;
438     libzcash::SaplingFullViewingKey fvk;
439
440     return GetSaplingIncomingViewingKey(addr, ivk) &&
441             GetSaplingFullViewingKey(ivk, fvk) &&
442             GetSaplingSpendingKey(fvk, extskOut);
443 }
This page took 0.050368 seconds and 4 git commands to generate.