]> Git Repo - VerusCoin.git/blob - src/pbaas/identity.h
Add theft proof VerusID time locks
[VerusCoin.git] / src / pbaas / identity.h
1 /********************************************************************
2  * (C) 2019 Michael Toutonghi
3  * 
4  * Distributed under the MIT software license, see the accompanying
5  * file COPYING or http://www.opensource.org/licenses/mit-license.php.
6  * 
7  * This provides support for PBaaS identity definition,
8  * 
9  * This is a decentralized identity class that provides the minimum
10  * basic function needed to enable persistent DID-similar identities, 
11  * needed for signatories, that will eventually bridge compatibly to
12  * DID identities.
13  * 
14  * 
15  */
16
17 #ifndef IDENTITY_H
18 #define IDENTITY_H
19
20 #include <univalue.h>
21 #include <sstream>
22 #include <vector>
23 #include "streams.h"
24 #include "pubkey.h"
25 #include "base58.h"
26 #include "uint256.h"
27 #include "key_io.h"
28 #include "crosschainrpc.h"
29 #include "zcash/Address.hpp"
30 #include "script/script.h"
31 #include "script/standard.h"
32 #include "primitives/transaction.h"
33 #include "arith_uint256.h"
34
35 std::string CleanName(const std::string &Name, uint160 &Parent, bool displayapproved=false);
36 std::vector<std::string> ParseSubNames(const std::string &Name, std::string &ChainOut, bool displayfilter=false, bool addVerus=true);
37
38 class CCommitmentHash
39 {
40 public:
41     static const CAmount DEFAULT_OUTPUT_AMOUNT = 0;
42     uint256 hash;
43
44     CCommitmentHash() {}
45     CCommitmentHash(const uint256 &Hash) : hash(Hash) {}
46
47     CCommitmentHash(const UniValue &uni)
48     {
49         hash = uint256S(uni_get_str(uni));
50     }
51
52     CCommitmentHash(const std::vector<unsigned char> &asVector)
53     {
54         ::FromVector(asVector, *this);
55     }
56
57     CCommitmentHash(const CTransaction &tx);
58
59     ADD_SERIALIZE_METHODS;
60
61     template <typename Stream, typename Operation>
62     inline void SerializationOp(Stream& s, Operation ser_action) {
63         READWRITE(hash);
64     }
65
66     UniValue ToUniValue() const
67     {
68         return UniValue(hash.GetHex());
69     }
70 };
71
72 class CNameReservation
73 {
74 public:
75     static const CAmount DEFAULT_OUTPUT_AMOUNT = 0;
76     static const int MAX_NAME_SIZE = (KOMODO_ASSETCHAIN_MAXLEN - 1);
77     std::string name;
78     CIdentityID referral;
79     uint256 salt;
80
81     CNameReservation() {}
82     CNameReservation(const std::string &Name, const CIdentityID &Referral, const uint256 &Salt) : name(Name.size() > MAX_NAME_SIZE ? std::string(Name.begin(), Name.begin() + MAX_NAME_SIZE) : Name), referral(Referral), salt(Salt) {}
83
84     CNameReservation(const UniValue &uni)
85     {
86         uint160 parent;
87         name = CleanName(uni_get_str(find_value(uni, "name")), parent);
88         salt = uint256S(uni_get_str(find_value(uni, "salt")));
89         CTxDestination dest = DecodeDestination(uni_get_str(find_value(uni, "referral")));
90         if (dest.which() == COptCCParams::ADDRTYPE_ID)
91         {
92             referral = CIdentityID(GetDestinationID(dest));
93         }
94         else if (dest.which() != COptCCParams::ADDRTYPE_INVALID)
95         {
96             salt.SetNull(); // either valid destination, no destination, or invalid reservation
97         }
98     }
99
100     CNameReservation(const CTransaction &tx, int *pNumOut=nullptr);
101
102     CNameReservation(std::vector<unsigned char> &asVector)
103     {
104         ::FromVector(asVector, *this);
105         if (name.size() > MAX_NAME_SIZE)
106         {
107             name = std::string(name.begin(), name.begin() + MAX_NAME_SIZE);
108         }
109     }
110
111     ADD_SERIALIZE_METHODS;
112
113     template <typename Stream, typename Operation>
114     inline void SerializationOp(Stream& s, Operation ser_action) {
115         READWRITE(name);
116         READWRITE(referral);
117         READWRITE(salt);
118     }
119
120     UniValue ToUniValue() const;
121
122     CCommitmentHash GetCommitment()
123     {
124         return CCommitmentHash(GetHash(*this));
125     }
126
127     bool IsValid() const
128     {
129         return (name != "" && name.size() <= MAX_NAME_SIZE) && !salt.IsNull();
130     }
131 };
132
133 // this includes the necessary data for a principal to sign, but does not
134 // include enough information to derive a persistent identity
135 class CPrincipal
136 {
137 public:
138     static const uint8_t VERSION_INVALID = 0;
139     static const uint8_t VERSION_VERUSID = 1;
140     static const uint8_t VERSION_PBAAS = 2;
141     static const uint8_t VERSION_FIRSTVALID = 1;
142     static const uint8_t VERSION_LASTVALID = 2;
143
144     uint32_t nVersion;
145     uint32_t flags;
146
147     // signing authority
148     std::vector<CTxDestination> primaryAddresses;
149     int32_t minSigs;
150
151     CPrincipal() : nVersion(VERSION_INVALID) {}
152
153     CPrincipal(uint32_t Version,
154                uint32_t Flags,
155                const std::vector<CTxDestination> &primary, 
156                int32_t minPrimarySigs) :
157                nVersion(Version),
158                flags(Flags),
159                primaryAddresses(primary),
160                minSigs(minPrimarySigs)
161         {}
162
163     CPrincipal(const UniValue &uni);
164     CPrincipal(std::vector<unsigned char> &asVector)
165     {
166         ::FromVector(asVector, *this);
167     }
168
169     ADD_SERIALIZE_METHODS;
170
171     template <typename Stream, typename Operation>
172     inline void SerializationOp(Stream& s, Operation ser_action) {
173         READWRITE(nVersion);
174         READWRITE(flags);
175         std::vector<std::vector<unsigned char>> addressVs;
176         if (ser_action.ForRead())
177         {
178             READWRITE(addressVs);
179
180             for (auto vec : addressVs)
181             {
182                 if (vec.size() == 20)
183                 {
184                     primaryAddresses.push_back(CTxDestination(CKeyID(uint160(vec))));
185                 }
186                 else if (vec.size() == 33)
187                 {
188                     primaryAddresses.push_back(CTxDestination(CPubKey(vec)));
189                 }
190                 else
191                 {
192                     primaryAddresses.push_back(CTxDestination(CNoDestination()));
193                 }
194             }
195         }
196         else
197         {
198             for (auto dest : primaryAddresses)
199             {
200                 addressVs.push_back(GetDestinationBytes(dest));
201             }
202
203             READWRITE(addressVs);
204         }
205         READWRITE(minSigs);
206     }
207
208     UniValue ToUniValue() const;
209
210     bool IsValid() const
211     {
212         return nVersion >= VERSION_FIRSTVALID && 
213                nVersion <= VERSION_LASTVALID && 
214                primaryAddresses.size() && 
215                primaryAddresses.size() <= 10 && 
216                minSigs >= 1 &&
217                minSigs <= primaryAddresses.size();
218     }
219
220     bool IsPrimaryMutation(const CPrincipal &newPrincipal) const
221     {
222         if (nVersion != newPrincipal.nVersion ||
223             minSigs != minSigs ||
224             primaryAddresses.size() != newPrincipal.primaryAddresses.size())
225         {
226             return true;
227         }
228         for (int i = 0; i < primaryAddresses.size(); i++)
229         {
230             if (primaryAddresses[i] != newPrincipal.primaryAddresses[i])
231             {
232                 return true;
233             }
234         }       
235         return false; 
236     }
237 };
238
239 class CIdentity : public CPrincipal
240 {
241 public:
242     enum
243     {
244         FLAG_REVOKED = 0x8000,              // set when this identity is revoked
245         FLAG_ACTIVECURRENCY = 0x1,          // flag that is set when this ID is being used as an active currency name
246         FLAG_LOCKED = 0x2,                  // set when this identity is revoked
247         MAX_UNLOCK_DELAY = 60 * 24 * 3      // 3 day maximum unlock time for an ID
248     };
249
250     static const int MAX_NAME_LEN = 64;
251
252     uint160 parent;
253
254     // real name or pseudonym, must be unique on the blockchain on which it is defined and can be used
255     // as a name for blockchains or other purposes on any chain in the Verus ecosystem once exported to
256     // the Verus chain. The hash of this name hashed with the parent if present, must equal the principal ID
257     //
258     // this name is always normalized to lower case. any identity that is registered
259     // on a PBaaS chain may be exported to the Verus chain and referenced by appending
260     // a dot ".", followed by the chain name on which this identity was registered.
261     // that will eventually create a domain name system as follows:
262     // root == VRSC (implicit), so a name that is defined on the Verus chain may be referenced as
263     //         just its name.
264     //
265     // name from another chain == name.chainname
266     //      the chainID that would derive from such a name will be Hash(ChainID(chainname) + Hash(name));
267     // 
268     std::string name;
269
270     // content hashes, key value, where key is 20 byte ripemd160
271     std::map<uint160, uint256> contentMap;
272
273     // revocation authority - can only invalidate identity or update revocation
274     uint160 revocationAuthority;
275
276     // recovery authority - can change primary addresses in case of primary key loss or compromise
277     uint160 recoveryAuthority;
278
279     // z-addresses for contact and privately made attestations that can be proven to others
280     std::vector<libzcash::SaplingPaymentAddress> privateAddresses;
281
282     uint32_t unlockAfter;
283
284     CIdentity() : CPrincipal(), unlockAfter(0) {}
285
286     CIdentity(uint32_t Version,
287               uint32_t Flags,
288               const std::vector<CTxDestination> &primary,
289               int32_t minPrimarySigs,
290               const uint160 &Parent,
291               const std::string &Name,
292               const std::vector<std::pair<uint160, uint256>> &hashes,
293               const uint160 &Revocation,
294               const uint160 &Recovery,
295               const std::vector<libzcash::SaplingPaymentAddress> &Inboxes = std::vector<libzcash::SaplingPaymentAddress>(),
296               int32_t unlockTime=0) : 
297               CPrincipal(Version, Flags, primary, minPrimarySigs),
298               parent(Parent),
299               name(Name),
300               revocationAuthority(Revocation),
301               recoveryAuthority(Recovery),
302               privateAddresses(Inboxes),
303               unlockAfter(unlockTime)
304     {
305         for (auto &entry : hashes)
306         {
307             if (!entry.first.IsNull())
308             {
309                 contentMap[entry.first] = entry.second;
310             }
311             else
312             {
313                 // any recognizable error should make this invalid
314                 nVersion = VERSION_INVALID;
315             }
316         }
317     }
318
319     CIdentity(const UniValue &uni);
320     CIdentity(const CTransaction &tx, int *voutNum=nullptr);
321     CIdentity(const CScript &scriptPubKey);
322     CIdentity(const std::vector<unsigned char> &asVector)
323     {
324         ::FromVector(asVector, *this);
325     }
326
327     ADD_SERIALIZE_METHODS;
328
329     template <typename Stream, typename Operation>
330     inline void SerializationOp(Stream& s, Operation ser_action) {
331         READWRITE(*(CPrincipal *)this);
332         READWRITE(parent);
333         READWRITE(LIMITED_STRING(name, MAX_NAME_LEN));
334
335         std::vector<std::pair<uint160, uint256>> kvContent;
336         if (ser_action.ForRead())
337         {
338             READWRITE(kvContent);
339             for (auto &entry : kvContent)
340             {
341                 if (!entry.first.IsNull())
342                 {
343                     contentMap[entry.first] = entry.second;
344                 }
345                 else
346                 {
347                     // any recognizable error should make this invalid
348                     nVersion = VERSION_INVALID;
349                 }
350             }
351         }
352         else
353         {
354             for (auto entry : contentMap)
355             {
356                 kvContent.push_back(entry);
357             }
358             READWRITE(kvContent);
359         }
360
361         READWRITE(contentMap);
362         READWRITE(revocationAuthority);
363         READWRITE(recoveryAuthority);
364         READWRITE(privateAddresses);
365
366         if (nVersion >= VERSION_PBAAS)
367         {
368             READWRITE(unlockAfter);
369         }
370     }
371
372     UniValue ToUniValue() const;
373
374     void Revoke()
375     {
376         flags |= FLAG_REVOKED;
377         Unlock(0, 0);
378     }
379
380     void Unrevoke()
381     {
382         flags &= ~FLAG_REVOKED;
383     }
384
385     bool IsRevoked() const
386     {
387         return flags & FLAG_REVOKED;
388     }
389
390     void Lock(int32_t unlockTime)
391     {
392         if (unlockTime <= 0)
393         {
394             unlockTime = 1;
395         }
396         else if (unlockTime > MAX_UNLOCK_DELAY)
397         {
398             unlockTime = MAX_UNLOCK_DELAY;
399         }
400         flags |= FLAG_LOCKED;
401         unlockAfter = unlockTime;
402     }
403
404     void Unlock(uint32_t height, uint32_t txExpiryHeight)
405     {
406         if (IsRevoked())
407         {
408             flags &= ~FLAG_LOCKED;
409             unlockAfter = 0;
410         }
411         else if (IsLocked())
412         {
413             flags &= ~FLAG_LOCKED;
414             unlockAfter += txExpiryHeight;
415         }
416         else if (height > unlockAfter)
417         {
418             unlockAfter = 0;
419         }
420         if (unlockAfter > (txExpiryHeight + MAX_UNLOCK_DELAY))
421         {
422             unlockAfter = txExpiryHeight + MAX_UNLOCK_DELAY;
423         }
424     }
425
426     // This only returns the state of the lock flag. Note that an ID stays locked from spending or
427     // signing until the height it was unlocked plus the time lock applied when it was locked.
428     bool IsLocked() const
429     {
430         return flags & FLAG_LOCKED;
431     }
432
433     // consider the unlockAfter height as well
434     // this continues to return that it is locked after it is unlocked
435     // until passed the parameter of the height at which it was unlocked, plus the time lock
436     bool IsLocked(uint32_t height) const
437     {
438         return nVersion >= VERSION_PBAAS &&
439                (IsLocked() || unlockAfter >= height) &&
440                !IsRevoked();
441     }
442
443     int32_t UnlockHeight() const
444     {
445         return unlockAfter;
446     }
447
448     void ActivateCurrency()
449     {
450         if (nVersion == VERSION_FIRSTVALID)
451         {
452             nVersion = VERSION_PBAAS;
453         }
454         flags |= FLAG_ACTIVECURRENCY;
455     }
456
457     void DeactivateCurrency()
458     {
459         flags &= ~FLAG_ACTIVECURRENCY;
460     }
461
462     bool HasActiveCurrency() const
463     {
464         return flags & FLAG_ACTIVECURRENCY;
465     }
466
467     bool IsValid() const
468     {
469         return CPrincipal::IsValid() && name.size() > 0 && (name.size() <= MAX_NAME_LEN);
470     }
471
472     bool IsValidUnrevoked() const
473     {
474         return IsValid() && !IsRevoked();
475     }
476
477     CIdentityID GetID() const;
478     CIdentityID GetID(const std::string &Name) const;
479     static CIdentityID GetID(const std::string &Name, uint160 &parent);
480
481     CIdentity LookupIdentity(const std::string &name, uint32_t height=0, uint32_t *pHeightOut=nullptr, CTxIn *pTxIn=nullptr);
482     static CIdentity LookupIdentity(const CIdentityID &nameID, uint32_t height=0, uint32_t *pHeightOut=nullptr, CTxIn *pTxIn=nullptr);
483     static CIdentity LookupFirstIdentity(const CIdentityID &idID, uint32_t *pHeightOut=nullptr, CTxIn *idTxIn=nullptr, CTransaction *pidTx=nullptr);
484
485     CIdentity RevocationAuthority() const
486     {
487         return GetID() == revocationAuthority ? *this : LookupIdentity(revocationAuthority);
488     }
489
490     CIdentity RecoveryAuthority() const
491     {
492         return GetID() == recoveryAuthority ? *this : LookupIdentity(recoveryAuthority);
493     }
494
495     template <typename TOBJ>
496     CTxOut TransparentOutput(uint8_t evalcode, CAmount nValue, const TOBJ &obj) const
497     {
498         CTxOut ret;
499
500         if (IsValidUnrevoked())
501         {
502             CConditionObj<TOBJ> ccObj = CConditionObj<TOBJ>(evalcode, std::vector<CTxDestination>({CTxDestination(CIdentityID(GetID()))}), 1, &obj);
503             ret = CTxOut(nValue, MakeMofNCCScript(ccObj));
504         }
505         return ret;
506     }
507
508     template <typename TOBJ>
509     CTxOut TransparentOutput(CAmount nValue) const
510     {
511         CTxOut ret;
512
513         if (IsValidUnrevoked())
514         {
515             CConditionObj<TOBJ> ccObj = CConditionObj<TOBJ>(0, std::vector<CTxDestination>({CTxDestination(CIdentityID(GetID()))}), 1);
516             ret = CTxOut(nValue, MakeMofNCCScript(ccObj));
517         }
518         return ret;
519     }
520
521     CScript TransparentOutput() const;
522     static CScript TransparentOutput(const CIdentityID &destinationID);
523
524     // creates an output script to control updates to this identity
525     CScript IdentityUpdateOutputScript(uint32_t height) const;
526
527     bool IsInvalidMutation(const CIdentity &newIdentity, uint32_t height, uint32_t expiryHeight) const
528     {
529         auto nSolVersion = CConstVerusSolutionVector::GetVersionByHeight(height);
530         if (parent != newIdentity.parent ||
531             (nSolVersion < CActivationHeight::ACTIVATE_IDCONSENSUS2 && name != newIdentity.name) ||
532             (nSolVersion < CActivationHeight::ACTIVATE_PBAAS && (newIdentity.HasActiveCurrency() || 
533                                                                  newIdentity.IsLocked() || 
534                                                                  newIdentity.nVersion >= VERSION_PBAAS)) ||
535             (nSolVersion >= CActivationHeight::ACTIVATE_PBAAS && newIdentity.nVersion < VERSION_PBAAS) ||
536             GetID() != newIdentity.GetID() ||
537             ((newIdentity.flags & ~FLAG_REVOKED) && (newIdentity.nVersion == VERSION_FIRSTVALID)) ||
538             ((newIdentity.flags & ~(FLAG_REVOKED + FLAG_ACTIVECURRENCY + FLAG_LOCKED)) && (newIdentity.nVersion >= VERSION_PBAAS)) ||
539             ((flags & FLAG_ACTIVECURRENCY) && !(newIdentity.flags & FLAG_ACTIVECURRENCY)) ||
540             newIdentity.nVersion < VERSION_FIRSTVALID ||
541             newIdentity.nVersion > VERSION_LASTVALID)
542         {
543             return true;
544         }
545
546         // we cannot unlock instantly unless we are revoked, we also cannot relock
547         // to enable an earlier unlock time
548         if (newIdentity.nVersion >= VERSION_PBAAS)
549         {
550             if (IsLocked(height))
551             {
552                 if (!newIdentity.IsLocked(height) && !newIdentity.IsRevoked())
553                 {
554                     return true;
555                 }
556                 else if (!newIdentity.IsRevoked())
557                 {
558                     if (IsLocked() && !newIdentity.IsLocked())
559                     {
560                         if ((newIdentity.unlockAfter != (unlockAfter + expiryHeight)) &&
561                             !(unlockAfter > MAX_UNLOCK_DELAY && newIdentity.unlockAfter == (MAX_UNLOCK_DELAY + expiryHeight)))
562                         {
563                             return true;
564                         }
565                     }
566                     else if (!IsLocked())
567                     {
568                         // only revocation can change unlock after time, and we don't allow re-lock until unlock either, which
569                         // can change the new unlock time
570                         if (newIdentity.IsLocked())
571                         {
572                             if ((expiryHeight + newIdentity.unlockAfter < unlockAfter))
573                             {
574                                 return true;
575                             }
576                         }
577                         else if (newIdentity.unlockAfter != unlockAfter)
578                         {
579                             return true;
580                         }
581                     }
582                 }
583             }
584             else if (newIdentity.IsLocked(height))
585             {
586                 if (newIdentity.unlockAfter > MAX_UNLOCK_DELAY)
587                 {
588                     return true;
589                 }
590             }
591         }
592         return false;
593     }
594
595     bool IsPrimaryMutation(const CIdentity &newIdentity, uint32_t height) const
596     {
597         auto nSolVersion = CConstVerusSolutionVector::GetVersionByHeight(height);
598         if (CPrincipal::IsPrimaryMutation(newIdentity) ||
599             (nSolVersion >= CActivationHeight::ACTIVATE_IDCONSENSUS2 && name != newIdentity.name && GetID() == newIdentity.GetID()) ||
600             contentMap != newIdentity.contentMap ||
601             privateAddresses != newIdentity.privateAddresses ||
602             unlockAfter != newIdentity.unlockAfter ||
603             (HasActiveCurrency() != newIdentity.HasActiveCurrency()) ||
604             IsLocked() != newIdentity.IsLocked())
605         {
606             return true;
607         }
608         return false;
609     }
610
611     bool IsRevocation(const CIdentity &newIdentity) const 
612     {
613         if (!IsRevoked() && newIdentity.IsRevoked())
614         {
615             return true;
616         }
617         return false;
618     }
619
620     bool IsRevocationMutation(const CIdentity &newIdentity, uint32_t height) const 
621     {
622         auto nSolVersion = CConstVerusSolutionVector::GetVersionByHeight(height);
623         if (revocationAuthority != newIdentity.revocationAuthority &&
624             (nSolVersion < CActivationHeight::ACTIVATE_IDCONSENSUS2 || !IsRevoked()))
625         {
626             return true;
627         }
628         return false;
629     }
630
631     bool IsRecovery(const CIdentity &newIdentity) const
632     {
633         if (IsRevoked() && !newIdentity.IsRevoked())
634         {
635             return true;
636         }
637         return false;
638     }
639
640     bool IsRecoveryMutation(const CIdentity &newIdentity, uint32_t height) const
641     {
642         auto nSolVersion = CConstVerusSolutionVector::GetVersionByHeight(height);
643         if (recoveryAuthority != newIdentity.recoveryAuthority ||
644             (IsRevoked() &&
645              ((nSolVersion >= CActivationHeight::ACTIVATE_IDCONSENSUS2 && revocationAuthority != newIdentity.revocationAuthority) ||
646               IsPrimaryMutation(newIdentity, height))))
647         {
648             return true;
649         }
650         return false;
651     }
652 };
653
654 class CIdentityMapKey
655 {
656 public:
657     // the flags
658     static const uint16_t VALID = 1;
659     static const uint16_t CAN_SPEND = 0x8000;
660     static const uint16_t CAN_SIGN = 0x4000;
661     static const uint16_t MANUAL_HOLD = 0x2000; // we were CAN_SIGN in the past, so keep a last state updated after we are removed, keep it updated so its useful when signing related txes
662     static const uint16_t BLACKLIST = 0x1000;   // do not track identities that are blacklisted
663     static const uint32_t MAX_BLOCKHEIGHT = INT32_MAX;
664
665     // these elements are used as a sort key for the identity map
666     // with most significant member first. flags have no effect on sort order, since elements will be unique already
667     CIdentityID idID;                           // 20 byte ID
668     uint32_t blockHeight;                       // four byte blockheight
669     uint32_t blockOrder;                        // 1-based numerical order if in the same block based on first to last spend, 1 otherwise, 0 is invalid except for queries
670     uint32_t flags;
671
672     CIdentityMapKey() : blockHeight(0), blockOrder(1), flags(0) {}
673     CIdentityMapKey(const CIdentityID &id, uint32_t blkHeight=0, uint32_t orderInBlock=1, uint32_t Flags=0) : idID(id), blockHeight(blkHeight), blockOrder(orderInBlock), flags(Flags) {}
674
675     CIdentityMapKey(const arith_uint256 &mapKey)
676     {
677         flags = mapKey.GetLow64() & 0xffffffff;
678         blockOrder = mapKey.GetLow64() >> 32;
679         blockHeight = (mapKey >> 64).GetLow64() & 0xffffffff;
680         uint256 keyBytes(ArithToUint256(mapKey));
681         idID = CIdentityID(uint160(std::vector<unsigned char>(keyBytes.begin() + 12, keyBytes.end())));
682     }
683
684     ADD_SERIALIZE_METHODS;
685
686     template <typename Stream, typename Operation>
687     inline void SerializationOp(Stream& s, Operation ser_action) {
688         READWRITE(idID);
689         READWRITE(blockHeight);
690         READWRITE(blockOrder);
691         READWRITE(flags);
692     }
693
694     arith_uint256 MapKey() const
695     {
696         std::vector<unsigned char> vch(idID.begin(), idID.end());
697         vch.insert(vch.end(), 12, 0);
698         arith_uint256 retVal = UintToArith256(uint256(vch));
699         retVal = (retVal << 32) | blockHeight;
700         retVal = (retVal << 32) | blockOrder;
701         retVal = (retVal << 32) | flags;
702         return retVal;
703     }
704
705     // if it actually represents a real identity and not just a key for queries. blockOrder is 1-based
706     bool IsValid() const
707     {
708         return !idID.IsNull() && blockHeight != 0 && flags & VALID && blockOrder >= 1;
709     }
710
711     std::string ToString() const
712     {
713         return "{\"id\":" + idID.GetHex() + ", \"blockheight\":" + std::to_string(blockHeight) + ", \"blockorder\":" + std::to_string(blockOrder) + ", \"flags\":" + std::to_string(flags) + ", \"mapkey\":" + ArithToUint256(MapKey()).GetHex() + "}";
714     }
715
716     bool CanSign() const
717     {
718         return flags & CAN_SIGN;
719     }
720
721     bool CanSpend() const
722     {
723         return flags & CAN_SPEND;
724     }
725 };
726
727 class CIdentityMapValue : public CIdentity
728 {
729 public:
730     uint256 txid;
731
732     CIdentityMapValue() : CIdentity() {}
733     CIdentityMapValue(const CTransaction &tx) : CIdentity(tx), txid(tx.GetHash()) {}
734
735     ADD_SERIALIZE_METHODS;
736
737     template <typename Stream, typename Operation>
738     inline void SerializationOp(Stream& s, Operation ser_action) {
739         READWRITE(*(CIdentity *)this);
740         READWRITE(txid);
741     }
742 };
743
744 // an identity signature is a compound signature consisting of the block height of its creation, and one or more cryptographic 
745 // signatures of the controlling addresses. validation can be performed based on the validity when signed, using the block height
746 // stored in the signature instance, or based on the continued signature validity of the current identity, which may automatically
747 // invalidate when the identity is updated.
748 class CIdentitySignature
749 {
750 public:
751     enum {
752         VERSION_INVALID = 0,
753         VERSION_VERUSID = 1,
754         VERSION_FIRST = 1,
755         VERSION_LAST = 1
756     };
757     uint8_t version;
758     uint32_t blockHeight;
759     std::set<std::vector<unsigned char>> signatures;
760
761     CIdentitySignature() : version(VERSION_VERUSID), blockHeight(0) {}
762     CIdentitySignature(uint32_t height, const std::vector<unsigned char> &oneSig) : version(VERSION_VERUSID), blockHeight(height), signatures({oneSig}) {}
763     CIdentitySignature(uint32_t height, const std::set<std::vector<unsigned char>> &sigs) : version(VERSION_VERUSID), blockHeight(height), signatures(sigs) {}
764     CIdentitySignature(const std::vector<unsigned char> &asVector)
765     {
766         ::FromVector(asVector, *this);
767     }
768
769     template <typename Stream, typename Operation>
770     inline void SerializationOp(Stream& s, Operation ser_action) {
771         READWRITE(version);
772         if (version <= VERSION_LAST && version >= VERSION_FIRST)
773         {
774             READWRITE(blockHeight);
775             std::vector<std::vector<unsigned char>> sigs;
776             if (ser_action.ForRead())
777             {
778                 READWRITE(sigs);
779
780                 for (auto &oneSig : sigs)
781                 {
782                     signatures.insert(oneSig);
783                 }
784             }
785             else
786             {
787                 for (auto &oneSig : signatures)
788                 {
789                     sigs.push_back(oneSig);
790                 }
791
792                 READWRITE(sigs);
793             }
794         }
795     }
796
797     ADD_SERIALIZE_METHODS;
798
799     void AddSignature(const std::vector<unsigned char> &signature)
800     {
801         signatures.insert(signature);
802     }
803     
804     uint32_t Version()
805     {
806         return version;
807     }
808
809     uint32_t IsValid()
810     {
811         return version <= VERSION_LAST && version >= VERSION_FIRST;
812     }
813 };
814
815 struct CCcontract_info;
816 struct Eval;
817 class CValidationState;
818
819 bool ValidateIdentityPrimary(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
820 bool ValidateIdentityRevoke(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
821 bool ValidateIdentityRecover(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
822 bool ValidateIdentityCommitment(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
823 bool ValidateIdentityReservation(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
824 bool PrecheckIdentityReservation(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
825 bool PrecheckIdentityReservation(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height, int referralLevels, int64_t referralAmount);
826 bool PrecheckIdentityPrimary(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
827 bool IsIdentityInput(const CScript &scriptSig);
828 bool ValidateQuantumKeyOut(struct CCcontract_info *cp, Eval* eval, const CTransaction &spendingTx, uint32_t nIn, bool fulfilled);
829 bool IsQuantumKeyOutInput(const CScript &scriptSig);
830 bool PrecheckQuantumKeyOut(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
831 bool ValidateFinalizeExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
832 bool IsFinalizeExportInput(const CScript &scriptSig);
833 bool FinalizeExportContextualPreCheck(const CTransaction &tx, int32_t outNum, CValidationState &state, uint32_t height);
834
835 #endif // IDENTITY_H
This page took 0.072837 seconds and 4 git commands to generate.