]> Git Repo - VerusCoin.git/blob - src/pbaas/pbaas.h
Build fix
[VerusCoin.git] / src / pbaas / pbaas.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 initialization, notarization, and cross-chain token
8  * transactions and enabling liquid or non-liquid tokens across the
9  * Verus ecosystem.
10  * 
11  * 
12  */
13
14 #ifndef PBAAS_H
15 #define PBAAS_H
16
17 #include <vector>
18 #include <univalue.h>
19
20 #include "cc/CCinclude.h"
21 #include "streams.h"
22 #include "script/script.h"
23 #include "amount.h"
24 #include "pbaas/crosschainrpc.h"
25 #include "pbaas/reserves.h"
26 #include "mmr.h"
27
28 #include <boost/algorithm/string.hpp>
29
30 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex, bool fIncludeAsm=true);
31
32 class CPBaaSNotarization;
33 class TransactionBuilder;
34
35 // these are output cryptoconditions for the Verus reserve liquidity system
36 // VRSC can be proxied to other PBaaS chains and sent back for use with this system
37 // The assumption that Verus is either the proxy on the PBaaS chain or the native
38 // coin on Verus enables us to reduce data requirements systemwide
39
40 // this is for transaction outputs with a Verus proxy on a PBaaS chain cryptoconditions with these outputs
41 // must also be funded with the native chain for fees, unless the chain is a Verus reserve chain, in which
42 // case the fee will be autoconverted from the Verus proxy through the conversion rules of this chain
43
44 static const uint32_t PBAAS_NODESPERNOTARIZATION = 2;       // number of nodes to reference in each notarization
45 static const int64_t PBAAS_MINNOTARIZATIONOUTPUT = 10000;   // enough for one fee worth to finalization and notarization thread
46 static const int32_t PBAAS_MINSTARTBLOCKDELTA = 50;         // minimum number of blocks to wait for starting a chain after definition
47 static const int32_t PBAAS_MAXPRIORBLOCKS = 16;             // maximum prior block commitments to include in prior blocks chain object
48
49 // these are object types that can be stored and recognized in an opret array
50 enum CHAIN_OBJECT_TYPES
51 {
52     CHAINOBJ_INVALID = 0,
53     CHAINOBJ_HEADER = 1,            // serialized full block header w/proof
54     CHAINOBJ_HEADER_REF = 2,        // equivalent to header, but only includes non-canonical data
55     CHAINOBJ_TRANSACTION_PROOF = 3, // serialized transaction or partial transaction with proof
56     CHAINOBJ_PROOF_ROOT = 4,        // merkle proof of preceding block or transaction
57     CHAINOBJ_PRIORBLOCKS = 5,       // prior block commitments to ensure recognition of overlapping notarizations
58     CHAINOBJ_RESERVETRANSFER = 6,   // serialized transaction, sometimes without an opret, which will be reconstructed
59     CHAINOBJ_COMPOSITEOBJECT = 7,   // can hold and index a variety and multiplicity of objects
60     CHAINOBJ_CROSSCHAINPROOF = 8,   // specific composite object, which is a single or multi-proof
61     CHAINOBJ_NOTARYSIGNATURE = 9    // notary signature
62 };
63
64 // the proof of an opret output, which is simply the types of objects and hashes of each
65 class COpRetProof
66 {
67 public:
68     uint32_t orIndex;                   // index into the opret objects to begin with
69     std::vector<uint8_t>    types;
70     std::vector<uint256>    hashes;
71
72     COpRetProof() : orIndex(0), types(0), hashes(0) {}
73     COpRetProof(std::vector<uint8_t> &rTypes, std::vector<uint256> &rHashes, uint32_t opretIndex = 0) : types(rTypes), hashes(rHashes), orIndex(opretIndex) {}
74
75     void AddObject(CHAIN_OBJECT_TYPES typeCode, uint256 objHash)
76     {
77         types.push_back(typeCode);
78         hashes.push_back(objHash);
79     }
80
81     template <typename CHAINOBJTYPE>
82     void AddObject(CHAINOBJTYPE &co, uint256 objHash)
83     {
84         types.push_back(ObjTypeCode(co));
85         hashes.push_back(objHash);
86     }
87
88     ADD_SERIALIZE_METHODS;
89
90     template <typename Stream, typename Operation>
91     inline void SerializationOp(Stream& s, Operation ser_action)
92     {
93         READWRITE(orIndex);
94         READWRITE(types);
95         READWRITE(hashes);
96     }
97 };
98
99 class CHeaderRef
100 {
101 public:
102     uint256 hash;               // block hash
103     CPBaaSPreHeader preHeader;  // non-canonical pre-header data of source chain
104
105     CHeaderRef() : hash() {}
106     CHeaderRef(uint256 &rHash, CPBaaSPreHeader ph) : hash(rHash), preHeader(ph) {}
107     CHeaderRef(const CBlockHeader &bh) : hash(bh.GetHash()), preHeader(bh) {}
108
109     ADD_SERIALIZE_METHODS;
110
111     template <typename Stream, typename Operation>
112     inline void SerializationOp(Stream& s, Operation ser_action)
113     {
114         READWRITE(hash);
115         READWRITE(preHeader);
116     }
117
118     uint256 GetHash() { return hash; }
119 };
120
121 class CPriorBlocksCommitment
122 {
123 public:
124     std::vector<uint256> priorBlocks;       // prior block commitments, which are node hashes that include merkle root, block hash, and compact power
125     uint256 pastBlockType;                  // 1 = POS, 0 = POW indicators for past blocks, enabling selective, pseudorandom proofs of past blocks by type
126
127     CPriorBlocksCommitment() : priorBlocks() {}
128     CPriorBlocksCommitment(const std::vector<uint256> &priors, const uint256 &pastTypes) : priorBlocks(priors), pastBlockType(pastTypes) {}
129
130     ADD_SERIALIZE_METHODS;
131
132     template <typename Stream, typename Operation>
133     inline void SerializationOp(Stream& s, Operation ser_action)
134     {
135         READWRITE(priorBlocks);
136         READWRITE(pastBlockType);
137     }
138 };
139
140 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
141
142 class CBaseChainObject
143 {
144 public:
145     uint16_t objectType;                    // type of object, such as blockheader, transaction, proof, tokentx, etc.
146
147     CBaseChainObject() : objectType(CHAINOBJ_INVALID) {}
148     CBaseChainObject(uint16_t objType) : objectType(objType) {}
149
150     ADD_SERIALIZE_METHODS;
151
152     template <typename Stream, typename Operation>
153     inline void SerializationOp(Stream& s, Operation ser_action)
154     {
155         READWRITE(objectType);
156     }
157 };
158
159 template <typename SERIALIZABLE>
160 class CChainObject : public CBaseChainObject
161 {
162 public:
163     SERIALIZABLE object;                    // the actual object
164
165     CChainObject() : CBaseChainObject() {}
166
167     CChainObject(uint16_t objType, const SERIALIZABLE &rObject) : CBaseChainObject(objType), object(rObject) { }
168
169     ADD_SERIALIZE_METHODS;
170
171     template <typename Stream, typename Operation>
172     inline void SerializationOp(Stream& s, Operation ser_action)
173     {
174         READWRITE(*(CBaseChainObject *)this);
175         READWRITE(object);
176     }
177
178     uint256 GetHash() const
179     {
180         CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
181
182         hw << object;
183         return GetHash();
184     }
185 };
186
187 // each notarization will have an opret object that contains various kind of proof of the notarization itself
188 // as well as recent POW and POS headers and entropy sources.
189 class CCrossChainProof
190 {
191 public:
192     enum
193     {
194         VERSION_INVALID = 0,
195         VERSION_FIRST = 1,
196         VERSION_CURRENT = 1,
197         VERSION_LAST = 1
198     };
199     uint32_t version;
200     std::vector<CBaseChainObject *> chainObjects;    // this owns the memory associated with chainObjects and deletes it on destructions
201
202     CCrossChainProof() : version(VERSION_CURRENT) {}
203     CCrossChainProof(const CCrossChainProof &oldObj)
204     {
205         CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
206         s << oldObj;
207         s >> *this;
208     }
209     CCrossChainProof(const std::vector<CBaseChainObject *> &objects, int Version=VERSION_CURRENT) : version(Version), chainObjects(objects) { }
210
211     ~CCrossChainProof()
212     {
213         DeleteOpRetObjects(chainObjects);
214         version = VERSION_INVALID;
215     }
216
217     const CCrossChainProof &operator=(const CCrossChainProof &operand)
218     {
219         CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
220         s << operand;
221         DeleteOpRetObjects(chainObjects);
222         s >> *this;
223         return *this;
224     }
225
226     ADD_SERIALIZE_METHODS;
227
228     template <typename Stream, typename Operation>
229     inline void SerializationOp(Stream& s, Operation ser_action) {
230         READWRITE(version);
231         if (ser_action.ForRead())
232         {
233             int32_t proofSize;
234             READWRITE(VARINT(proofSize));
235
236             bool error = false;
237             for (int i = 0; i < proofSize && !error; i++)
238             {
239                 try
240                 {
241                     uint16_t objType;
242                     READWRITE(objType);
243                     union {
244                         CChainObject<CBlockHeaderAndProof> *pNewHeader;
245                         CChainObject<CPartialTransactionProof> *pNewTx;
246                         CChainObject<uint256> *pNewProof;
247                         CChainObject<CBlockHeaderProof> *pNewHeaderRef;
248                         CChainObject<CPriorBlocksCommitment> *pPriors;
249                         CChainObject<CReserveTransfer> *pExport;
250                         CChainObject<CCrossChainProof> *pCrossChainProof;
251                         CChainObject<CNotaryEvidence> *pNotarySignature;
252                         CBaseChainObject *pobj;
253                     };
254
255                     pobj = nullptr;
256
257                     switch(objType)
258                     {
259                         case CHAINOBJ_HEADER:
260                         {
261                             CBlockHeaderAndProof obj;
262                             READWRITE(obj);
263                             pNewHeader = new CChainObject<CBlockHeaderAndProof>();
264                             if (pNewHeader)
265                             {
266                                 pNewHeader->objectType = objType;
267                                 pNewHeader->object = obj;
268                             }
269                             break;
270                         }
271                         case CHAINOBJ_TRANSACTION_PROOF:
272                         {
273                             CPartialTransactionProof obj;
274                             READWRITE(obj);
275                             pNewTx = new CChainObject<CPartialTransactionProof>();
276                             if (pNewTx)
277                             {
278                                 pNewTx->objectType = objType;
279                                 pNewTx->object = obj;
280                             }
281                             break;
282                         }
283                         case CHAINOBJ_PROOF_ROOT:
284                         {
285                             uint256 obj;
286                             READWRITE(obj);
287                             pNewProof = new CChainObject<uint256>();
288                             if (pNewProof)
289                             {
290                                 pNewProof->objectType = objType;
291                                 pNewProof->object = obj;
292                             }
293                             break;
294                         }
295                         case CHAINOBJ_HEADER_REF:
296                         {
297                             CBlockHeaderProof obj;
298                             READWRITE(obj);
299                             pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
300                             if (pNewHeaderRef)
301                             {
302                                 pNewHeaderRef->objectType = objType;
303                                 pNewHeaderRef->object = obj;
304                             }
305                             break;
306                         }
307                         case CHAINOBJ_PRIORBLOCKS:
308                         {
309                             CPriorBlocksCommitment obj;
310                             READWRITE(obj);
311                             pPriors = new CChainObject<CPriorBlocksCommitment>();
312                             if (pPriors)
313                             {
314                                 pPriors->objectType = objType;
315                                 pPriors->object = obj;
316                             }
317                             break;
318                         }
319                         case CHAINOBJ_RESERVETRANSFER:
320                         {
321                             CReserveTransfer obj;
322                             READWRITE(obj);
323                             pExport = new CChainObject<CReserveTransfer>();
324                             if (pExport)
325                             {
326                                 pExport->objectType = objType;
327                                 pExport->object = obj;
328                             }
329                             break;
330                         }
331                         case CHAINOBJ_CROSSCHAINPROOF:
332                         {
333                             CCrossChainProof obj;
334                             READWRITE(obj);
335                             pCrossChainProof = new CChainObject<CCrossChainProof>();
336                             if (pCrossChainProof)
337                             {
338                                 pCrossChainProof->objectType = objType;
339                                 pCrossChainProof->object = obj;
340                             }
341                             break;
342                         }
343                         case CHAINOBJ_COMPOSITEOBJECT:
344                         {
345                             CCrossChainProof obj;
346                             READWRITE(obj);
347                             pCrossChainProof = new CChainObject<CCrossChainProof>();
348                             if (pCrossChainProof)
349                             {
350                                 pCrossChainProof->objectType = CHAINOBJ_COMPOSITEOBJECT;
351                                 pCrossChainProof->object = obj;
352                             }
353                             break;
354                         }
355                         case CHAINOBJ_NOTARYSIGNATURE:
356                         {
357                             CNotaryEvidence obj;
358                             READWRITE(obj);
359                             pNotarySignature = new CChainObject<CNotaryEvidence>();
360                             if (pNotarySignature)
361                             {
362                                 pNotarySignature->objectType = CHAINOBJ_NOTARYSIGNATURE;
363                                 pNotarySignature->object = obj;
364                             }
365                             break;
366                         }
367                     }
368
369                     if (pobj)
370                     {
371                         //printf("%s: storing object, code %u\n", __func__, objType);
372                         chainObjects.push_back(pobj);
373                     }
374                 }
375                 catch(const std::exception& e)
376                 {
377                     error = true;
378                     break;
379                 }
380             }
381
382             if (error)
383             {
384                 printf("%s: ERROR: opret is likely corrupt\n", __func__);
385                 LogPrintf("%s: ERROR: opret is likely corrupt\n", __func__);
386                 DeleteOpRetObjects(chainObjects);
387             }
388         }
389         else
390         {
391             //printf("entering CCrossChainProof serialize\n");
392             int32_t proofSize = chainObjects.size();
393             READWRITE(VARINT(proofSize));
394             for (auto &oneVal : chainObjects)
395             {
396                 DehydrateChainObject(s, oneVal);
397             }
398         }
399     }
400
401     bool IsValid() const
402     {
403         return (version >= VERSION_FIRST || version <= VERSION_LAST);
404     }
405
406     bool Empty() const
407     {
408         return chainObjects.size() == 0;
409     }
410
411     const std::vector<uint16_t> TypeVector() const
412     {
413         std::vector<uint16_t> retVal;
414         for (auto &pChainObj : chainObjects)
415         {
416             if (pChainObj)
417             {
418                 retVal.push_back(pChainObj->objectType);
419             }
420         }
421         return retVal;
422     }
423
424     const CCrossChainProof &operator<<(const CPartialTransactionProof &partialTxProof)
425     {
426         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPartialTransactionProof>(CHAINOBJ_TRANSACTION_PROOF, partialTxProof)));
427         return *this;
428     }
429
430     const CCrossChainProof &operator<<(const CBlockHeaderAndProof &headerRefProof)
431     {
432         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderAndProof>(CHAINOBJ_HEADER_REF, headerRefProof)));
433         return *this;
434     }
435
436     const CCrossChainProof &operator<<(const CBlockHeaderProof &headerProof)
437     {
438         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderProof>(CHAINOBJ_HEADER, headerProof)));
439         return *this;
440     }
441
442     const CCrossChainProof &operator<<(const CPriorBlocksCommitment &priorBlocks)
443     {
444         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPriorBlocksCommitment>(CHAINOBJ_PRIORBLOCKS, priorBlocks)));
445         return *this;
446     }
447
448     const CCrossChainProof &operator<<(const uint256 &proofRoot)
449     {
450         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<uint256>(CHAINOBJ_PROOF_ROOT, proofRoot)));
451         return *this;
452     }
453
454     const CCrossChainProof &operator<<(const CReserveTransfer &reserveTransfer)
455     {
456         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CReserveTransfer>(CHAINOBJ_RESERVETRANSFER, reserveTransfer)));
457         return *this;
458     }
459
460     const CCrossChainProof &operator<<(const CCrossChainProof &crossChainProof)
461     {
462         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCrossChainProof>(CHAINOBJ_CROSSCHAINPROOF, crossChainProof)));
463         return *this;
464     }
465 };
466
467 // this must remain cast/data compatible with CCompositeChainObject
468 class CCompositeChainObject : public CCrossChainProof
469 {
470 public:
471     CCompositeChainObject() : CCrossChainProof() {}
472     CCompositeChainObject(const std::vector<CBaseChainObject *> &proofs, int Version=VERSION_CURRENT) : 
473         CCrossChainProof(proofs, Version) { }
474
475     ADD_SERIALIZE_METHODS;
476
477     template <typename Stream, typename Operation>
478     inline void SerializationOp(Stream& s, Operation ser_action) {
479         READWRITE(*(CCrossChainProof *)this);
480     }
481
482     const CCompositeChainObject &operator<<(const CCompositeChainObject &compositeChainObject)
483     {
484         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCompositeChainObject>(CHAINOBJ_COMPOSITEOBJECT, compositeChainObject)));
485         return *this;
486     }
487 };
488
489 // returns a pointer to a base chain object, which can be cast to the
490 // object type indicated in its objType member
491 uint256 GetChainObjectHash(const CBaseChainObject &bo);
492
493 // returns a pointer to a base chain object, which can be cast to the
494 // object type indicated in its objType member
495 template <typename OStream>
496 CBaseChainObject *RehydrateChainObject(OStream &s)
497 {
498     int16_t objType;
499
500     try
501     {
502         s >> objType;
503     }
504     catch(const std::exception& e)
505     {
506         return NULL;
507     }
508
509     union {
510         CChainObject<CBlockHeaderAndProof> *pNewHeader;
511         CChainObject<CPartialTransactionProof> *pNewTx;
512         CChainObject<uint256> *pNewProof;
513         CChainObject<CBlockHeaderProof> *pNewHeaderRef;
514         CChainObject<CPriorBlocksCommitment> *pPriors;
515         CChainObject<CReserveTransfer> *pExport;
516         CChainObject<CCrossChainProof> *pCrossChainProof;
517         CChainObject<CCompositeChainObject> *pCompositeChainObject;
518         CBaseChainObject *retPtr;
519     };
520
521     retPtr = NULL;
522
523     switch(objType)
524     {
525         case CHAINOBJ_HEADER:
526             pNewHeader = new CChainObject<CBlockHeaderAndProof>();
527             if (pNewHeader)
528             {
529                 s >> pNewHeader->object;
530                 pNewHeader->objectType = objType;
531             }
532             break;
533         case CHAINOBJ_TRANSACTION_PROOF:
534             pNewTx = new CChainObject<CPartialTransactionProof>();
535             if (pNewTx)
536             {
537                 s >> pNewTx->object;
538                 pNewTx->objectType = objType;
539             }
540             break;
541         case CHAINOBJ_PROOF_ROOT:
542             pNewProof = new CChainObject<uint256>();
543             if (pNewProof)
544             {
545                 s >> pNewProof->object;
546                 pNewProof->objectType = objType;
547             }
548             break;
549         case CHAINOBJ_HEADER_REF:
550             pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
551             if (pNewHeaderRef)
552             {
553                 s >> pNewHeaderRef->object;
554                 pNewHeaderRef->objectType = objType;
555             }
556             break;
557         case CHAINOBJ_PRIORBLOCKS:
558             pPriors = new CChainObject<CPriorBlocksCommitment>();
559             if (pPriors)
560             {
561                 s >> pPriors->object;
562                 pPriors->objectType = objType;
563             }
564             break;
565         case CHAINOBJ_RESERVETRANSFER:
566             pExport = new CChainObject<CReserveTransfer>();
567             if (pExport)
568             {
569                 s >> pExport->object;
570                 pExport->objectType = objType;
571             }
572             break;
573         case CHAINOBJ_CROSSCHAINPROOF:
574             pCrossChainProof = new CChainObject<CCrossChainProof>();
575             if (pCrossChainProof)
576             {
577                 s >> pCrossChainProof->object;
578                 pCrossChainProof->objectType = objType;
579             }
580             break;
581         case CHAINOBJ_COMPOSITEOBJECT:
582             pCompositeChainObject = new CChainObject<CCompositeChainObject>();
583             if (pCompositeChainObject)
584             {
585                 s >> pCompositeChainObject->object;
586                 pCompositeChainObject->objectType = objType;
587             }
588             break;
589     }
590     return retPtr;
591 }
592
593 // returns a pointer to a base chain object, which can be cast to the
594 // object type indicated in its objType member
595 template <typename OStream>
596 bool DehydrateChainObject(OStream &s, const CBaseChainObject *pobj)
597 {
598     switch(pobj->objectType)
599     {
600         case CHAINOBJ_HEADER:
601         {
602             s << *(CChainObject<CBlockHeaderAndProof> *)pobj;
603             return true;
604         }
605
606         case CHAINOBJ_TRANSACTION_PROOF:
607         {
608             s << *(CChainObject<CPartialTransactionProof> *)pobj;
609             return true;
610         }
611
612         case CHAINOBJ_PROOF_ROOT:
613         {
614             s << *(CChainObject<uint256> *)pobj;
615             return true;
616         }
617
618         case CHAINOBJ_HEADER_REF:
619         {
620             s << *(CChainObject<CBlockHeaderProof> *)pobj;
621             return true;
622         }
623
624         case CHAINOBJ_PRIORBLOCKS:
625         {
626             s << *(CChainObject<CPriorBlocksCommitment> *)pobj;
627             return true;
628         }
629
630         case CHAINOBJ_RESERVETRANSFER:
631         {
632             s << *(CChainObject<CReserveTransfer> *)pobj;
633             return true;
634         }
635         case CHAINOBJ_CROSSCHAINPROOF:
636         {
637             s << *(CChainObject<CCrossChainProof> *)pobj;
638             return true;
639         }
640         case CHAINOBJ_COMPOSITEOBJECT:
641         {
642             s << *(CChainObject<CCompositeChainObject> *)pobj;
643             return true;
644         }
645     }
646     return false;
647 }
648
649 int8_t ObjTypeCode(const CBlockHeaderAndProof &obj);
650
651 int8_t ObjTypeCode(const CPartialTransactionProof &obj);
652
653 int8_t ObjTypeCode(const CBlockHeaderProof &obj);
654
655 int8_t ObjTypeCode(const CPriorBlocksCommitment &obj);
656
657 int8_t ObjTypeCode(const CReserveTransfer &obj);
658
659 int8_t ObjTypeCode(const CCrossChainProof &obj);
660
661 int8_t ObjTypeCode(const CCompositeChainObject &obj);
662
663 // this adds an opret to a mutable transaction that provides the necessary evidence of a signed, cheating stake transaction
664 CScript StoreOpRetArray(const std::vector<CBaseChainObject *> &objPtrs);
665
666 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
667
668 std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript);
669
670 // This data structure is used on an output that provides proof of stake validation for other crypto conditions
671 // with rate limited spends based on a PoS contest
672 class CPoSSelector
673 {
674 public:
675     uint32_t nBits;                         // PoS difficulty target
676     uint32_t nTargetSpacing;                // number of 1/1000ths of a block between selections (e.g. 1 == 1000 selections per block)
677
678     CPoSSelector(uint32_t bits, uint32_t TargetSpacing)
679     {
680         nBits = bits; 
681         nTargetSpacing = TargetSpacing;
682     }
683
684     ADD_SERIALIZE_METHODS;
685
686     template <typename Stream, typename Operation>
687     inline void SerializationOp(Stream& s, Operation ser_action) {
688         READWRITE(nBits);
689         READWRITE(nTargetSpacing);
690     }
691
692     CPoSSelector(const std::vector<unsigned char> &asVector)
693     {
694         FromVector(asVector, *this);
695     }
696
697     std::vector<unsigned char> AsVector()
698     {
699         return ::AsVector(*this);
700     }
701
702     bool IsValid() const
703     {
704         return nBits != 0;
705     }
706 };
707
708 class CInputDescriptor
709 {
710 public:
711     CScript scriptPubKey;
712     CAmount nValue;
713     CTxIn txIn;
714     CInputDescriptor() : nValue(0) {}
715     CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {}
716     bool operator<(const CInputDescriptor &op) const;
717
718     ADD_SERIALIZE_METHODS;
719
720     template <typename Stream, typename Operation>
721     inline void SerializationOp(Stream& s, Operation ser_action) {
722         READWRITE(scriptPubKey);
723         READWRITE(nValue);
724         READWRITE(txIn);
725     }
726 };
727
728 class CRPCChainData
729 {
730 public:
731     CCurrencyDefinition chainDefinition;    // chain information for the specific chain
732     std::string     rpcHost;                // host of the chain's daemon
733     int32_t         rpcPort;                // port of the chain's daemon
734     std::string     rpcUserPass;            // user and password for this daemon
735     int64_t         lastConnectTime;        // set whenever we check valid
736
737     CRPCChainData() {}
738     CRPCChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass) :
739         chainDefinition(chainDef), rpcHost{host}, rpcPort(port), rpcUserPass(userPass), lastConnectTime(0) {}
740
741     ADD_SERIALIZE_METHODS;
742
743     template <typename Stream, typename Operation>
744     inline void SerializationOp(Stream& s, Operation ser_action) {
745         READWRITE(chainDefinition);
746         READWRITE(rpcHost);
747         READWRITE(rpcPort);
748         READWRITE(rpcUserPass);
749         READWRITE(lastConnectTime);
750     }
751
752     std::vector<unsigned char> AsVector()
753     {
754         return ::AsVector(*this);
755     }
756
757     bool IsValid() const
758     {
759         return chainDefinition.IsValid();
760     }
761
762     int64_t SetLastConnection(int64_t setTime)
763     {
764         return (lastConnectTime = setTime);
765     }
766
767     int64_t LastConnectionTime() const
768     {
769         return lastConnectTime;
770     }
771
772     uint160 GetID() const
773     {
774         return chainDefinition.GetID();
775     }
776 };
777
778 // Each merge mined chain gets an entry that includes information required to connect to a live daemon
779 // for that block, cross notarize, and validate notarizations.
780 class CPBaaSMergeMinedChainData : public CRPCChainData
781 {
782 public:
783     static const uint32_t MAX_MERGE_CHAINS = 15;
784     CBlock          block;                  // full block to submit upon winning header
785
786     CPBaaSMergeMinedChainData() {}
787     CPBaaSMergeMinedChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass, CBlock &blk) :
788         CRPCChainData(chainDef, host, port, userPass), block(blk) {}
789
790     ADD_SERIALIZE_METHODS;
791
792     template <typename Stream, typename Operation>
793     inline void SerializationOp(Stream& s, Operation ser_action) {
794         READWRITE(chainDefinition);
795         READWRITE(rpcHost);
796         READWRITE(rpcPort);
797         READWRITE(rpcUserPass);
798         READWRITE(block);
799     }
800
801     std::vector<unsigned char> AsVector()
802     {
803         return ::AsVector(*this);
804     }
805 };
806
807 class CGateway
808 {
809 public:
810     virtual bool ValidateDestination(const std::string &destination) const = 0;
811     virtual CTransferDestination ToTransferDestination(const std::string &destination) const = 0;
812     virtual std::set<uint160> FeeCurrencies() const = 0;
813     virtual const CCurrencyDefinition &GetConverter() const = 0;
814 };
815
816 class CEthGateway : public CGateway
817 {
818     virtual bool ValidateDestination(const std::string &destination) const;
819     virtual CTransferDestination ToTransferDestination(const std::string &destination) const;
820     virtual std::set<uint160> FeeCurrencies() const;
821     virtual const CCurrencyDefinition &GetConverter() const;
822 };
823
824 // This is the data for a PBaaS notarization transaction, either of a PBaaS chain into the Verus chain, or the Verus
825 // chain into a PBaaS chain.
826
827 // Part of a transaction with an opret that contains only the hashes and proofs, without the source
828 // headers, transactions, and objects. This type of notarizatoin is mined into a block by the miner, and is created on the PBaaS
829 // chain.
830 //
831 // Notarizations include the following elements in order:
832 //  Latest block header being notarized, or a header ref for a merge-mined header
833 //  Proof of the header using the latest MMR root
834 //  Cross notarization transaction less its op_ret
835 //  Proof of the cross notarization using the latest MMR root
836 class CPBaaSNotarization
837 {
838 public:
839     enum {
840         VERSION_INVALID = 0,
841         VERSION_FIRST = 1,
842         VERSION_LAST = 1,
843         VERSION_CURRENT = 1,
844         FINAL_CONFIRMATIONS = 9,
845         DEFAULT_NOTARIZATION_FEE = 10000,               // price of a notarization fee in native or launch system currency
846         BLOCK_NOTARIZATION_MODULO = 10,                 // incentive to earn one valid notarization during this many blocks
847         MIN_BLOCKS_BEFORE_NOTARY_FINALIZED = 15,        // 15 blocks must go by before notary signatures or confirming evidence can be provided
848         MAX_NODES = 2,                                  // only provide 2 nodes per notarization
849         MIN_NOTARIZATION_OUTPUT = 0,                    // minimum amount for notarization output
850     };
851     //static const int FINAL_CONFIRMATIONS = 10;
852     //static const int MIN_BLOCKS_BETWEEN_NOTARIZATIONS = 8;
853
854     enum FLAGS
855     {
856         FLAGS_NONE = 0,
857         FLAG_DEFINITION_NOTARIZATION = 1,   // initial notarization on definition of currency/system/chain
858         FLAG_PRE_LAUNCH = 2,                // pre-launch notarization
859         FLAG_START_NOTARIZATION = 4,        // first notarization after pre-launch
860         FLAG_LAUNCH_CONFIRMED = 8,
861         FLAG_REFUNDING = 0x10,
862         FLAG_ACCEPTED_MIRROR = 0x20,        // if this is set, this notarization is a mirror of an earned notarization on another chain
863         FLAG_BLOCKONE_NOTARIZATION = 0x40,  // block 1 notarizations are auto-finalized, the blockchain itself will be worthless if it is wrong
864         FLAG_SAME_CHAIN = 0x80,             // set if all currency information is verifiable on this chain
865         FLAG_LAUNCH_COMPLETE = 0x100        // set if all currency information is verifiable on this chain
866     };
867
868     uint32_t nVersion;
869     uint32_t flags;                         // notarization options
870     CTransferDestination proposer;          // paid when this gets used on import (miner/staker, shares this with 1 notary for each validation)
871
872     uint160 currencyID;                     // the primary currency this notarization represents for the system, may be gateway or external chain
873     uint32_t notarizationHeight;            // <= height on the current system as of this notarization (can't be confirmed earlier)
874     CCoinbaseCurrencyState currencyState;   // state of the currency being notarized as of this notarization
875
876     CUTXORef prevNotarization;              // reference of the prior notarization on this system with which we agree
877     uint256 hashPrevNotarization;           // hash of the prior notarization on this system with which we agree, even one not accepted yet
878     uint32_t prevHeight;                    // height of previous notarization we agree with
879
880     std::map<uint160, CCoinbaseCurrencyState> currencyStates; // currency state of other currencies to be co-notarized for gateways
881     std::map<uint160, CProofRoot> proofRoots; // if cross-chain notarization, includes valid proof root of systemID at notarizationHeight + others verified
882
883     std::vector<CNodeData> nodes;           // if cross chain notarization, network nodes
884
885     CPBaaSNotarization() : nVersion(PBAAS_VERSION_INVALID), flags(0), notarizationHeight(0), prevHeight(0) {}
886
887     CPBaaSNotarization(const uint160 &currencyid,
888                        const CCoinbaseCurrencyState CurrencyState,
889                        uint32_t height,
890                        const CUTXORef &prevnotarization,
891                        uint32_t prevheight,
892                        const std::vector<CNodeData> &Nodes=std::vector<CNodeData>(),
893                        const std::map<uint160, CCoinbaseCurrencyState> &CurrencyStates=std::map<uint160, CCoinbaseCurrencyState>(),
894                        const CTransferDestination &Proposer=CTransferDestination(),
895                        const std::map<uint160, CProofRoot> &ProofRoots=std::map<uint160, CProofRoot>(),
896                        uint32_t version=VERSION_CURRENT,
897                        uint32_t Flags=FLAGS_NONE) : 
898                        nVersion(version),
899                        flags(Flags),
900                        proposer(Proposer),
901                        currencyID(currencyid),
902                        notarizationHeight(height),
903                        currencyState(CurrencyState),
904                        prevNotarization(prevnotarization),
905                        prevHeight(prevheight),
906                        currencyStates(CurrencyStates),
907                        proofRoots(ProofRoots),
908                        nodes(Nodes)
909     {
910     }
911
912     CPBaaSNotarization(const std::vector<unsigned char> &asVector)
913     {
914         ::FromVector(asVector, *this);
915     }
916
917     CPBaaSNotarization(const CTransaction &tx, int32_t *pOutIdx=nullptr);
918
919     CPBaaSNotarization(const CScript &scriptPubKey);
920
921     CPBaaSNotarization(const UniValue &obj);
922
923     ADD_SERIALIZE_METHODS;
924
925     template <typename Stream, typename Operation>
926     inline void SerializationOp(Stream& s, Operation ser_action) {
927         READWRITE(VARINT(nVersion));
928         READWRITE(VARINT(flags));
929         READWRITE(proposer);
930         READWRITE(currencyID);
931         READWRITE(currencyState);
932         READWRITE(notarizationHeight);
933         READWRITE(prevNotarization);
934         READWRITE(hashPrevNotarization);
935         READWRITE(prevHeight);
936
937         std::vector<std::pair<uint160, CCoinbaseCurrencyState>> vecCurrencyStates;
938         if (ser_action.ForRead())
939         {
940             READWRITE(vecCurrencyStates);
941             for (auto &oneRoot : vecCurrencyStates)
942             {
943                 currencyStates.insert(oneRoot);
944             }
945         }
946         else
947         {
948             for (auto &oneRoot : currencyStates)
949             {
950                 vecCurrencyStates.push_back(oneRoot);
951             }
952             READWRITE(vecCurrencyStates);
953         }
954
955         std::vector<std::pair<uint160, CProofRoot>> vecProofRoots;
956
957         if (ser_action.ForRead())
958         {
959             READWRITE(vecProofRoots);
960             for (auto &oneRoot : vecProofRoots)
961             {
962                 proofRoots.insert(oneRoot);
963             }
964         }
965         else
966         {
967             for (auto &oneRoot : proofRoots)
968             {
969                 vecProofRoots.push_back(oneRoot);
970             }
971             READWRITE(vecProofRoots);
972         }
973
974         READWRITE(nodes);
975     }
976
977     std::vector<unsigned char> AsVector()
978     {
979         return ::AsVector(*this);
980     }
981
982     bool IsValid() const
983     {
984         return nVersion >= VERSION_FIRST && nVersion <= VERSION_LAST && !currencyID.IsNull();
985     }
986
987     static std::string NotaryNotarizationKeyName()
988     {
989         return "vrsc::system.notarization.notarization";
990     }
991
992     static std::string LaunchNotarizationKeyName()
993     {
994         return "vrsc::system.currency.launch.notarization";
995     }
996
997     static std::string LaunchPrelaunchKeyName()
998     {
999         return "vrsc::system.currency.launch.prelaunch";
1000     }
1001
1002     static std::string LaunchRefundKeyName()
1003     {
1004         return "vrsc::system.currency.launch.refund";
1005     }
1006
1007     static std::string LaunchConfirmKeyName()
1008     {
1009         return "vrsc::system.currency.launch.confirm";
1010     }
1011
1012     static std::string LaunchCompleteKeyName()
1013     {
1014         return "vrsc::system.currency.launch.complete";
1015     }
1016
1017     static uint160 NotaryNotarizationKey()
1018     {
1019         static uint160 nameSpace;
1020         static uint160 notaryNotarizationKey = CVDXF::GetDataKey(NotaryNotarizationKeyName(), nameSpace);
1021         return notaryNotarizationKey;
1022     }
1023
1024     static uint160 LaunchNotarizationKey()
1025     {
1026         static uint160 nameSpace;
1027         static uint160 signatureKey = CVDXF::GetDataKey(LaunchNotarizationKeyName(), nameSpace);
1028         return signatureKey;
1029     }
1030
1031     static uint160 LaunchPrelaunchKey()
1032     {
1033         static uint160 nameSpace;
1034         static uint160 signatureKey = CVDXF::GetDataKey(LaunchPrelaunchKeyName(), nameSpace);
1035         return signatureKey;
1036     }
1037
1038     static uint160 LaunchRefundKey()
1039     {
1040         static uint160 nameSpace;
1041         static uint160 signatureKey = CVDXF::GetDataKey(LaunchRefundKeyName(), nameSpace);
1042         return signatureKey;
1043     }
1044
1045     static uint160 LaunchConfirmKey()
1046     {
1047         static uint160 nameSpace;
1048         static uint160 signatureKey = CVDXF::GetDataKey(LaunchConfirmKeyName(), nameSpace);
1049         return signatureKey;
1050     }
1051
1052     static uint160 LaunchCompleteKey()
1053     {
1054         static uint160 nameSpace;
1055         static uint160 signatureKey = CVDXF::GetDataKey(LaunchCompleteKeyName(), nameSpace);
1056         return signatureKey;
1057     }
1058
1059     // if false, *this is unmodifed, otherwise, it is set to the last valid notarization in the requested range
1060     bool GetLastNotarization(const uint160 &currencyID, 
1061                              int32_t startHeight=0, 
1062                              int32_t endHeight=0, 
1063                              uint256 *txIDOut=nullptr,
1064                              CTransaction *txOut=nullptr);
1065
1066     // if false, no matching, unspent notarization found
1067     bool GetLastUnspentNotarization(const uint160 &currencyID, 
1068                                     uint256 &txIDOut,
1069                                     int32_t &txOutNum,
1070                                     CTransaction *txOut=nullptr);
1071
1072     bool NextNotarizationInfo(const CCurrencyDefinition &sourceSystem, 
1073                               const CCurrencyDefinition &destCurrency, 
1074                               uint32_t lastExportHeight, 
1075                               uint32_t currentHeight, 
1076                               std::vector<CReserveTransfer> &exportTransfers,
1077                               uint256 &transferHash,
1078                               CPBaaSNotarization &newNotarization,
1079                               std::vector<CTxOut> &importOutputs,
1080                               CCurrencyValueMap &importedCurrency,
1081                               CCurrencyValueMap &gatewayDepositsUsed,
1082                               CCurrencyValueMap &spentCurrencyOut) const;
1083
1084     static bool CreateEarnedNotarization(const CRPCChainData &externalSystem,
1085                                          const CTransferDestination &Proposer,
1086                                          CValidationState &state,
1087                                          std::vector<CTxOut> &txOutputs,
1088                                          CPBaaSNotarization &notarization);
1089
1090     // accepts enough information to build a local accepted notarization transaction
1091     // miner fees are deferred until an import that uses this notarization, in which case
1092     // Proposer will get a share of the fees, if they are large enough. any miner,
1093     // who is mining the bridge can make such a notarization.
1094     static bool CreateAcceptedNotarization(const CCurrencyDefinition &externalSystem,
1095                                            const CPBaaSNotarization &notarization,
1096                                            const CNotaryEvidence &notaryEvidence,
1097                                            CValidationState &state,
1098                                            TransactionBuilder &txBuilder);
1099
1100     static bool ConfirmOrRejectNotarizations(const CWallet *pWallet,
1101                                              const CRPCChainData &externalSystem,
1102                                              CValidationState &state,
1103                                              TransactionBuilder &txBuilder,
1104                                              bool &finalized);
1105
1106     static std::vector<uint256> SubmitFinalizedNotarizations(const CRPCChainData &externalSystem,
1107                                                              CValidationState &state);
1108
1109     bool CheckProof(const uint160 &systemID, const CMMRProof &transactionBlockProof, uint256 checkHash)
1110     {
1111         auto proofRootIt = proofRoots.find(systemID);
1112         if (proofRootIt == proofRoots.end())
1113         {
1114             return false;
1115         }
1116         return transactionBlockProof.CheckProof(checkHash) == proofRootIt->second.stateRoot;
1117     }
1118
1119     CProofRoot GetProofRoot(const uint160 &systemID) const
1120     {
1121         auto proofRootIt = proofRoots.find(systemID);
1122         if (proofRootIt == proofRoots.end())
1123         {
1124             return CProofRoot();
1125         }
1126         return proofRootIt->second;
1127     }
1128
1129     void SetLaunchComplete(bool setTrue=true)
1130     {
1131         if (setTrue)
1132         {
1133             flags |= FLAG_LAUNCH_COMPLETE;
1134         }
1135         else
1136         {
1137             flags &= ~FLAG_LAUNCH_COMPLETE;
1138         }
1139     }
1140
1141     bool IsLaunchComplete() const
1142     {
1143         return flags & FLAG_LAUNCH_COMPLETE;
1144     }
1145
1146     void SetSameChain(bool setTrue=true)
1147     {
1148         if (setTrue)
1149         {
1150             flags |= FLAG_SAME_CHAIN;
1151         }
1152         else
1153         {
1154             flags &= ~FLAG_SAME_CHAIN;
1155         }
1156     }
1157
1158     bool IsSameChain() const
1159     {
1160         return flags & FLAG_SAME_CHAIN;
1161     }
1162
1163     bool IsMirror() const
1164     {
1165         return flags & FLAG_ACCEPTED_MIRROR;
1166     }
1167
1168     // both sets the mirror flag and also transforms the notarization
1169     // between mirror states. returns false if could not change state to requested.
1170     bool SetMirror(bool setTrue=true);
1171
1172     bool IsDefinitionNotarization() const
1173     {
1174         return flags & FLAG_DEFINITION_NOTARIZATION;
1175     }
1176
1177     void SetDefinitionNotarization(bool setTrue=true)
1178     {
1179         if (setTrue)
1180         {
1181             flags |= FLAG_DEFINITION_NOTARIZATION;
1182         }
1183         else
1184         {
1185             flags &= ~FLAG_DEFINITION_NOTARIZATION;
1186         }
1187     }
1188
1189     bool IsBlockOneNotarization() const
1190     {
1191         return flags & FLAG_BLOCKONE_NOTARIZATION;
1192     }
1193
1194     void SetBlockOneNotarization(bool setTrue=true)
1195     {
1196         if (setTrue)
1197         {
1198             flags |= FLAG_BLOCKONE_NOTARIZATION;
1199         }
1200         else
1201         {
1202             flags &= ~FLAG_BLOCKONE_NOTARIZATION;
1203         }
1204     }
1205
1206     bool IsPreLaunch() const
1207     {
1208         return flags & FLAG_PRE_LAUNCH;
1209     }
1210
1211     void SetPreLaunch(bool setTrue=true)
1212     {
1213         if (setTrue)
1214         {
1215             flags |= FLAG_PRE_LAUNCH;
1216         }
1217         else
1218         {
1219             flags &= ~FLAG_PRE_LAUNCH;
1220         }
1221     }
1222
1223     bool IsLaunchCleared() const
1224     {
1225         return flags & FLAG_START_NOTARIZATION;
1226     }
1227
1228     void SetLaunchCleared(bool setTrue=true)
1229     {
1230         if (setTrue)
1231         {
1232             flags |= FLAG_START_NOTARIZATION;
1233         }
1234         else
1235         {
1236             flags &= ~FLAG_START_NOTARIZATION;
1237         }
1238     }
1239
1240     bool IsLaunchConfirmed() const
1241     {
1242         return flags & FLAG_LAUNCH_CONFIRMED;
1243     }
1244
1245     void SetLaunchConfirmed(bool setTrue=true)
1246     {
1247         if (setTrue)
1248         {
1249             flags |= FLAG_LAUNCH_CONFIRMED;
1250         }
1251         else
1252         {
1253             flags &= ~FLAG_LAUNCH_CONFIRMED;
1254         }
1255     }
1256
1257     bool IsRefunding() const
1258     {
1259         return flags & FLAG_REFUNDING;
1260     }
1261
1262     void SetRefunding(bool setTrue=true)
1263     {
1264         if (setTrue)
1265         {
1266             flags |= FLAG_REFUNDING;
1267         }
1268         else
1269         {
1270             flags &= ~FLAG_REFUNDING;
1271         }
1272     }
1273
1274     UniValue ToUniValue() const;
1275 };
1276
1277 class CNotarySystemInfo
1278 {
1279 public:
1280     enum EVersions
1281     {
1282         VERSION_INVALID = 0,
1283         VERSION_CURRENT = 1,
1284         VERSION_FIRST = 1,
1285         VERSION_LAST = 1,
1286     };
1287
1288     enum ENotarySystemTypes
1289     {
1290         TYPE_INVALID = 0,
1291         TYPE_PBAAS = 1,
1292         TYPE_ETHERC20 = 2,
1293         TYPE_KOMODO = 3,
1294     };
1295
1296     uint32_t notarySystemVersion;
1297     uint32_t notarySystemType;
1298     uint32_t height;                            // height of last notarization
1299     CRPCChainData notaryChain;                  // notary chain information and connectivity for PBaaS protocol
1300     CCurrencyDefinition notaryConverter;        // fractional currency to convert between this native currency and the notary currency
1301     CPBaaSNotarization lastConfirmedNotarization;
1302
1303     CNotarySystemInfo() : notarySystemVersion(VERSION_INVALID), height(0) {}
1304
1305     CNotarySystemInfo(uint32_t Height, 
1306                       const CRPCChainData &NotaryChain, 
1307                       const CCurrencyDefinition &NotaryConverter,
1308                       const CPBaaSNotarization &lastNotarization,
1309                       uint32_t NotarySystemType=TYPE_PBAAS,
1310                       uint32_t notaryVersion=VERSION_CURRENT) :
1311                       notarySystemVersion(notaryVersion),
1312                       notarySystemType(NotarySystemType),
1313                       height(Height),
1314                       notaryChain(NotaryChain),
1315                       notaryConverter(NotaryConverter),
1316                       lastConfirmedNotarization(lastNotarization)
1317     {}
1318 };
1319
1320 class CConnectedChains
1321 {
1322 protected:
1323     CPBaaSMergeMinedChainData *GetChainInfo(uint160 chainID);
1324
1325 public:
1326     std::map<uint160, CPBaaSMergeMinedChainData> mergeMinedChains;
1327     std::multimap<arith_uint256, CPBaaSMergeMinedChainData *> mergeMinedTargets;
1328
1329     std::map<uint160, std::pair<CCurrencyDefinition, const CGateway *>> gateways;       // gateway currencies, which bridge to other blockchains/systems
1330
1331     // incoming export transactions from one currency & system and a UTXORef to a valid notarization each depends upon
1332     // indexed by the target, destination currency
1333     std::map<uint160, std::pair<uint32_t, std::pair<CUTXORef, CPartialTransactionProof>>> incomingBridgeTransfers;
1334
1335     // currency definition cache, needs LRU
1336     std::map<uint160, CCurrencyDefinition> currencyDefCache;                            // protected by cs_main, which is used for lookup
1337
1338     // make earned notarizations on one or more notary chains
1339     // On Verus, this can be set to ETH and Ethereum chain data will be pushed to us through Alan (Bridgekeeper) and the RPC API
1340     std::map<uint160, CNotarySystemInfo> notarySystems;
1341
1342     CCurrencyDefinition thisChain;
1343     bool readyToStart;
1344     std::vector<CNodeData> defaultPeerNodes;    // updated by notarizations
1345     std::vector<CTxOut> latestMiningOutputs;    // accessible from all merge miners - can be invalid
1346     int64_t lastAggregation = 0;                // adjusted time of last aggregation
1347
1348     int32_t earnedNotarizationHeight;           // zero or the height of one or more potential submissions
1349     CBlock earnedNotarizationBlock;
1350     int32_t earnedNotarizationIndex;            // index of earned notarization in block
1351
1352     bool dirty;
1353     bool lastSubmissionFailed;                  // if we submit a failed block, make another
1354     std::map<arith_uint256, CBlockHeader> qualifiedHeaders;
1355
1356     CCriticalSection cs_mergemining;
1357     CSemaphore sem_submitthread;
1358
1359     CConnectedChains() : readyToStart(0), sem_submitthread(0), earnedNotarizationHeight(0), dirty(0), lastSubmissionFailed(0) {}
1360
1361     arith_uint256 LowestTarget()
1362     {
1363         if (mergeMinedTargets.size())
1364         {
1365             return mergeMinedTargets.begin()->first;
1366         }
1367         else
1368         {
1369             return arith_uint256(0);
1370         }
1371     }
1372
1373     void SubmissionThread();
1374     static void SubmissionThreadStub();
1375     std::vector<std::pair<std::string, UniValue>> SubmitQualifiedBlocks();
1376
1377     void QueueNewBlockHeader(CBlockHeader &bh);
1378     void QueueEarnedNotarization(CBlock &blk, int32_t txIndex, int32_t height);
1379     void CheckImports();
1380     void SignAndCommitImportTransactions(const CTransaction &lastImportTx, const std::vector<CTransaction> &transactions);
1381     // send new imports from this chain to the specified chain, which generally will be the notary chain
1382     void ProcessLocalImports();
1383
1384     bool AddMergedBlock(CPBaaSMergeMinedChainData &blkData);
1385     bool RemoveMergedBlock(uint160 chainID);
1386     bool GetChainInfo(uint160 chainID, CRPCChainData &rpcChainData);
1387     void PruneOldChains(uint32_t pruneBefore);
1388     uint32_t CombineBlocks(CBlockHeader &bh);
1389
1390     // returns false if destinations are empty or first is not either pubkey or pubkeyhash
1391     bool SetLatestMiningOutputs(const std::vector<CTxOut> &minerOutputs);
1392     void AggregateChainTransfers(const CTxDestination &feeOutput, uint32_t nHeight);
1393     CCurrencyDefinition GetCachedCurrency(const uint160 &currencyID);
1394     CCurrencyDefinition UpdateCachedCurrency(const uint160 &currencyID, uint32_t height);
1395
1396     bool GetLastImport(const uint160 &currencyID, 
1397                        CTransaction &lastImport, 
1398                        int32_t &outputNum);
1399
1400     bool GetLastSourceImport(const uint160 &currencyID, 
1401                              CTransaction &lastImport, 
1402                              int32_t &outputNum);
1403
1404     bool GetUnspentSystemExports(const CCoinsViewCache &view,
1405                                  const uint160 systemID, 
1406                                  std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1407
1408     bool GetUnspentCurrencyExports(const CCoinsViewCache &view,
1409                                    const uint160 currencyID, 
1410                                    std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1411
1412     // get the exports to a specific system on this chain from a specific height up to a specific height
1413     bool GetSystemExports(const uint160 &systemID,                                 // transactions exported to system
1414                           std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> &exports,
1415                           uint32_t fromHeight,
1416                           uint32_t toHeight,
1417                           bool withProofs=false);
1418     
1419     // gets both the launch notarization and its partial transaction proof if launching to a new system
1420     bool GetLaunchNotarization(const CCurrencyDefinition &curDef,
1421                                std::pair<CInputDescriptor, CPartialTransactionProof> &notarizationTx,
1422                                CPBaaSNotarization &launchNotarization,
1423                                CPBaaSNotarization &notaryNotarization);
1424
1425     // get the exports to a specific system on this chain from a specific height up to a specific height
1426     bool GetCurrencyExports(const uint160 &currencyID,                             // transactions exported to system
1427                             std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> &exports,
1428                             uint32_t fromHeight,
1429                             uint32_t toHeight);
1430
1431     bool GetPendingSystemExports(const uint160 systemID,
1432                                  uint32_t fromHeight,
1433                                  multimap<uint160, pair<int, CInputDescriptor>> &exportOutputs);
1434
1435     bool GetPendingCurrencyExports(const uint160 currencyID,
1436                                    uint32_t fromHeight,
1437                                    std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1438
1439     // given exports on this chain, provide the proofs of those export outputs
1440     bool GetExportProofs(uint32_t height,
1441                          std::vector<std::pair<std::pair<CInputDescriptor,CPartialTransactionProof>,std::vector<CReserveTransfer>>> &exports);
1442
1443     static bool GetReserveDeposits(const uint160 &currencyID, const CCoinsViewCache &view, std::vector<CInputDescriptor> &reserveDeposits);
1444
1445     static bool CurrencyExportStatus(const CCurrencyValueMap &totalExports,
1446                                      const uint160 &sourceSystemID,
1447                                      const uint160 &destSystemID,
1448                                      CCurrencyValueMap &newReserveDeposits,
1449                                      CCurrencyValueMap &exportBurn);
1450
1451     static bool CurrencyImportStatus(const CCurrencyValueMap &totalExports,
1452                                      const uint160 &sourceSystemID,
1453                                      const uint160 &destSystemID,
1454                                      CCurrencyValueMap &newReserveDeposits,
1455                                      CCurrencyValueMap &exportBurn);
1456
1457     bool CreateNextExport(const CCurrencyDefinition &_curDef,
1458                           const std::vector<ChainTransferData> &txInputs,
1459                           const std::vector<CInputDescriptor> &priorExports,
1460                           const CTxDestination &feeOutput,
1461                           uint32_t sinceHeight,
1462                           uint32_t curHeight,
1463                           int32_t inputStartNum,
1464                           int32_t &inputsConsumed,
1465                           std::vector<CTxOut> &exportOutputs,
1466                           std::vector<CReserveTransfer> &exportTransfers,
1467                           const CPBaaSNotarization &lastNotarization,
1468                           const CUTXORef &lastNotarizationUTXO,
1469                           CPBaaSNotarization &newNotarization,
1470                           int &newNotarizationOutNum,
1471                           bool onlyIfRequired=true,
1472                           const ChainTransferData *addInputTx=nullptr);
1473
1474     // create a set of imports on the current chain for a set of exports
1475     bool CreateLatestImports(const CCurrencyDefinition &sourceSystemDef,                            // transactions imported from system
1476                              const CUTXORef &confirmedSourceNotarization,
1477                              const std::vector<std::pair<std::pair<CInputDescriptor,CPartialTransactionProof>,std::vector<CReserveTransfer>>> &exports,
1478                              std::map<uint160, std::vector<std::pair<int, CTransaction>>> &newImports);
1479
1480     // returns the first notary system, if there is more than one
1481     const CRPCChainData &FirstNotaryChain() const
1482     {
1483         if (notarySystems.size())
1484         {
1485             return notarySystems.begin()->second.notaryChain;
1486         }
1487         static CRPCChainData invalidChain;
1488         return invalidChain;
1489     }
1490
1491     // returns the map of notary systems
1492     const std::map<uint160, CNotarySystemInfo> &NotarySystems() const
1493     {
1494         return notarySystems;
1495     }
1496
1497     uint32_t NotaryChainHeight();
1498
1499     CCurrencyDefinition &ThisChain()
1500     {
1501         return thisChain;
1502     }
1503
1504     const std::map<uint160, std::pair<CCurrencyDefinition, const CGateway *>> &Gateways() const
1505     {
1506         return gateways;
1507     }
1508
1509     std::pair<CCurrencyDefinition, const CGateway *> GetGateway(const uint160 &gatewayID) const
1510     {
1511         auto it = gateways.find(gatewayID);
1512         if (it != gateways.end())
1513         {
1514             return it->second;
1515         }
1516         return std::make_pair(CCurrencyDefinition(), nullptr);
1517     }
1518
1519     int GetThisChainPort() const;
1520
1521     // start with existing currency state and currency definitino and add
1522     // all pre-launch activity to bring them both up to date
1523     CCoinbaseCurrencyState AddPrelaunchConversions(CCurrencyDefinition &curDef,
1524                                                    const CCoinbaseCurrencyState &currencyState,
1525                                                    int32_t fromHeight,
1526                                                    int32_t height,
1527                                                    int32_t curDefHeight);
1528
1529     CCoinbaseCurrencyState GetCurrencyState(int32_t height);                                // gets this chain's native currency state by block height
1530     CCoinbaseCurrencyState GetCurrencyState(CCurrencyDefinition &curDef, int32_t height, int32_t curDefHeight=0); // gets currency state
1531     CCoinbaseCurrencyState GetCurrencyState(const uint160 &currencyID, int32_t height);     // gets currency state
1532
1533     CCurrencyDefinition GetDestinationCurrency(const CReserveTransfer &rt) const;
1534
1535     bool CheckVerusPBaaSAvailable(UniValue &chainInfo, UniValue &chainDef);
1536     bool CheckVerusPBaaSAvailable();      // may use RPC to call Verus
1537     bool IsVerusPBaaSAvailable();
1538     bool IsNotaryAvailable(bool callToCheck=false);
1539     std::vector<CCurrencyDefinition> GetMergeMinedChains()
1540     {
1541         std::vector<CCurrencyDefinition> ret;
1542         LOCK(cs_mergemining);
1543         for (auto &chain : mergeMinedChains)
1544         {
1545             ret.push_back(chain.second.chainDefinition);
1546         }
1547         return ret;
1548     }
1549
1550     bool GetNotaryCurrencies(const CRPCChainData notaryChain, 
1551                              const std::set<uint160> &currencyIDs, 
1552                              std::map<uint160, std::pair<CCurrencyDefinition,CPBaaSNotarization>> &currencyDefs);
1553     bool GetNotaryIDs(const CRPCChainData notaryChain, const std::set<uint160> &idIDs, std::map<uint160,CIdentity> &identities);
1554 };
1555
1556 template <typename TOBJ>
1557 CTxOut MakeCC1of1Vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector<CTxDestination> vDest, const TOBJ &obj)
1558 {
1559     assert(vDest.size() < 256);
1560
1561     CTxOut vout;
1562     CC *payoutCond = MakeCCcond1(evalcode, pk);
1563     vout = CTxOut(nValue, CCPubKey(payoutCond));
1564     cc_free(payoutCond);
1565
1566     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1567     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
1568
1569     // add the object to the end of the script
1570     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1571     return(vout);
1572 }
1573
1574 template <typename TOBJ>
1575 CTxOut MakeCC1ofAnyVout(uint8_t evalcode, CAmount nValue, std::vector<CTxDestination> vDest, const TOBJ &obj, const CPubKey &pk=CPubKey())
1576 {
1577     // if pk is valid, we will make sure that it is one of the signature options on this CC
1578     if (pk.IsValid())
1579     {
1580         CCcontract_info C;
1581         CCcontract_info *cp;
1582         cp = CCinit(&C, evalcode);
1583         int i;
1584         bool addPubKey = false;
1585         for (i = 0; i < vDest.size(); i++)
1586         {
1587             CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), vDest[i]));
1588             if ((oneKey.IsValid() && oneKey == pk) || CKeyID(GetDestinationID(vDest[i])) == pk.GetID())
1589             {
1590                 // found, so don't add
1591                 break;
1592             }
1593         }
1594         // if not found, add the pubkey
1595         if (i >= vDest.size())
1596         {
1597             vDest.push_back(CTxDestination(pk));
1598         }
1599     }
1600
1601     CTxOut vout;
1602     CC *payoutCond = MakeCCcondAny(evalcode, vDest);
1603     vout = CTxOut(nValue, CCPubKey(payoutCond));
1604     cc_free(payoutCond);
1605
1606     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1607     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 0, (uint8_t)(vDest.size()), vDest, vvch);
1608
1609     for (auto dest : vDest)
1610     {
1611         CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest));
1612         std::vector<unsigned char> bytes = GetDestinationBytes(dest);
1613         if ((!oneKey.IsValid() && bytes.size() != 20) || (bytes.size() != 33 && bytes.size() != 20))
1614         {
1615             printf("Invalid destination %s\n", EncodeDestination(dest).c_str());
1616         }
1617     }
1618
1619     // add the object to the end of the script
1620     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1621     return(vout);
1622 }
1623
1624 template <typename TOBJ>
1625 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, const TOBJ &obj)
1626 {
1627     CTxOut vout;
1628     CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1629     vout = CTxOut(nValue,CCPubKey(payoutCond));
1630     cc_free(payoutCond);
1631
1632     std::vector<CPubKey> vpk({pk1, pk2});
1633     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1634     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, 2, vpk, vvch);
1635
1636     // add the object to the end of the script
1637     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1638     return(vout);
1639 }
1640
1641 template <typename TOBJ>
1642 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector<CTxDestination> vDest, const TOBJ &obj)
1643 {
1644     CTxOut vout;
1645     CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1646     vout = CTxOut(nValue,CCPubKey(payoutCond));
1647     cc_free(payoutCond);
1648
1649     std::vector<CPubKey> vpk({pk1, pk2});
1650     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1651     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
1652
1653     // add the object to the end of the script
1654     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1655     return(vout);
1656 }
1657
1658 bool IsVerusActive();
1659 bool IsVerusMainnetActive();
1660
1661 // used to export coins from one chain to another, if they are not native, they are represented on the other
1662 // chain as tokens
1663 bool ValidateCrossChainExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1664 bool IsCrossChainExportInput(const CScript &scriptSig);
1665
1666 // used to validate import of coins from one chain to another. if they are not native and are supported,
1667 // they are represented o the chain as tokens
1668 bool ValidateCrossChainImport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1669 bool IsCrossChainImportInput(const CScript &scriptSig);
1670
1671 bool ValidateNotaryEvidence(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1672 bool IsNotaryEvidenceInput(const CScript &scriptSig);
1673
1674 // used as a proxy token output for a reserve currency on its fractional reserve chain
1675 bool ValidateReserveOutput(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1676 bool IsReserveOutputInput(const CScript &scriptSig);
1677
1678 // used to transfer a reserve currency between chains
1679 bool ValidateReserveTransfer(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1680 bool IsReserveTransferInput(const CScript &scriptSig);
1681
1682 // used as exchange tokens between reserves and fractional reserves
1683 bool ValidateReserveExchange(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1684 bool IsReserveExchangeInput(const CScript &scriptSig);
1685
1686 // used to deposit reserves into a reserve UTXO set
1687 bool ValidateReserveDeposit(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1688 bool IsReserveDepositInput(const CScript &scriptSig);
1689
1690 bool ValidateChainDefinition(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1691 bool IsChainDefinitionInput(const CScript &scriptSig);
1692
1693 bool ValidateCurrencyState(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1694 bool IsCurrencyStateInput(const CScript &scriptSig);
1695
1696 bool GetCCParams(const CScript &scr, COptCCParams &ccParams);
1697
1698 bool SetPeerNodes(const UniValue &nodes);
1699 bool SetThisChain(const UniValue &chainDefinition);
1700 const uint256 &CurrencyDefHash(UniValue &chainDefinition);
1701
1702 extern CConnectedChains ConnectedChains;
1703 extern uint160 ASSETCHAINS_CHAINID;
1704 CCoinbaseCurrencyState GetInitialCurrencyState(const CCurrencyDefinition &chainDef);
1705
1706 #endif
This page took 0.125532 seconds and 4 git commands to generate.