]> Git Repo - VerusCoin.git/blob - src/pbaas/pbaas.h
714e92596c1a9cfccae39c4be561056085c3ebbf
[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
34 // these are output cryptoconditions for the Verus reserve liquidity system
35 // VRSC can be proxied to other PBaaS chains and sent back for use with this system
36 // The assumption that Verus is either the proxy on the PBaaS chain or the native
37 // coin on Verus enables us to reduce data requirements systemwide
38
39 // this is for transaction outputs with a Verus proxy on a PBaaS chain cryptoconditions with these outputs
40 // must also be funded with the native chain for fees, unless the chain is a Verus reserve chain, in which
41 // case the fee will be autoconverted from the Verus proxy through the conversion rules of this chain
42
43 static const uint32_t PBAAS_NODESPERNOTARIZATION = 2;       // number of nodes to reference in each notarization
44 static const int64_t PBAAS_MINNOTARIZATIONOUTPUT = 10000;   // enough for one fee worth to finalization and notarization thread
45 static const int32_t PBAAS_MINSTARTBLOCKDELTA = 50;         // minimum number of blocks to wait for starting a chain after definition
46 static const int32_t PBAAS_MAXPRIORBLOCKS = 16;             // maximum prior block commitments to include in prior blocks chain object
47
48 // we wil uncomment service types as they are implemented
49 // commented service types are here as guidance and reminders
50 enum PBAAS_SERVICE_TYPES {
51     SERVICE_INVALID = 0,
52     SERVICE_NOTARIZATION = 1,
53     SERVICE_LAST = 1
54 };
55
56 // these are object types that can be stored and recognized in an opret array
57 enum CHAIN_OBJECT_TYPES
58 {
59     CHAINOBJ_INVALID = 0,
60     CHAINOBJ_HEADER = 1,            // serialized full block header w/proof
61     CHAINOBJ_HEADER_REF = 2,        // equivalent to header, but only includes non-canonical data
62     CHAINOBJ_TRANSACTION_PROOF = 3,       // serialized transaction or partial transaction with proof
63     CHAINOBJ_PROOF_ROOT = 4,        // merkle proof of preceding block or transaction
64     CHAINOBJ_PRIORBLOCKS = 5,       // prior block commitments to ensure recognition of overlapping notarizations
65     CHAINOBJ_RESERVETRANSFER = 6,   // serialized transaction, sometimes without an opret, which will be reconstructed
66     CHAINOBJ_COMPOSITEOBJECT = 7,   // can hold and index a variety and multiplicity of objects
67     CHAINOBJ_CROSSCHAINPROOF = 8    // specific composite object, which is a single or multi-proof
68 };
69
70 // the proof of an opret output, which is simply the types of objects and hashes of each
71 class COpRetProof
72 {
73 public:
74     uint32_t orIndex;                   // index into the opret objects to begin with
75     std::vector<uint8_t>    types;
76     std::vector<uint256>    hashes;
77
78     COpRetProof() : orIndex(0), types(0), hashes(0) {}
79     COpRetProof(std::vector<uint8_t> &rTypes, std::vector<uint256> &rHashes, uint32_t opretIndex = 0) : types(rTypes), hashes(rHashes), orIndex(opretIndex) {}
80
81     void AddObject(CHAIN_OBJECT_TYPES typeCode, uint256 objHash)
82     {
83         types.push_back(typeCode);
84         hashes.push_back(objHash);
85     }
86
87     template <typename CHAINOBJTYPE>
88     void AddObject(CHAINOBJTYPE &co, uint256 objHash)
89     {
90         types.push_back(ObjTypeCode(co));
91         hashes.push_back(objHash);
92     }
93
94     ADD_SERIALIZE_METHODS;
95
96     template <typename Stream, typename Operation>
97     inline void SerializationOp(Stream& s, Operation ser_action)
98     {
99         READWRITE(orIndex);
100         READWRITE(types);
101         READWRITE(hashes);
102     }
103 };
104
105 class CHeaderRef
106 {
107 public:
108     uint256 hash;               // block hash
109     CPBaaSPreHeader preHeader;  // non-canonical pre-header data of source chain
110
111     CHeaderRef() : hash() {}
112     CHeaderRef(uint256 &rHash, CPBaaSPreHeader ph) : hash(rHash), preHeader(ph) {}
113     CHeaderRef(const CBlockHeader &bh) : hash(bh.GetHash()), preHeader(bh) {}
114
115     ADD_SERIALIZE_METHODS;
116
117     template <typename Stream, typename Operation>
118     inline void SerializationOp(Stream& s, Operation ser_action)
119     {
120         READWRITE(hash);
121         READWRITE(preHeader);
122     }
123
124     uint256 GetHash() { return hash; }
125 };
126
127 class CPriorBlocksCommitment
128 {
129 public:
130     std::vector<uint256> priorBlocks;       // prior block commitments, which are node hashes that include merkle root, block hash, and compact power
131     uint256 pastBlockType;                  // 1 = POS, 0 = POW indicators for past blocks, enabling selective, pseudorandom proofs of past blocks by type
132
133     CPriorBlocksCommitment() : priorBlocks() {}
134     CPriorBlocksCommitment(const std::vector<uint256> &priors, const uint256 &pastTypes) : priorBlocks(priors), pastBlockType(pastTypes) {}
135
136     ADD_SERIALIZE_METHODS;
137
138     template <typename Stream, typename Operation>
139     inline void SerializationOp(Stream& s, Operation ser_action)
140     {
141         READWRITE(priorBlocks);
142         READWRITE(pastBlockType);
143     }
144 };
145
146 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
147
148 class CBaseChainObject
149 {
150 public:
151     uint16_t objectType;                    // type of object, such as blockheader, transaction, proof, tokentx, etc.
152
153     CBaseChainObject() : objectType(CHAINOBJ_INVALID) {}
154     CBaseChainObject(uint16_t objType) : objectType(objType) {}
155
156     ADD_SERIALIZE_METHODS;
157
158     template <typename Stream, typename Operation>
159     inline void SerializationOp(Stream& s, Operation ser_action)
160     {
161         READWRITE(objectType);
162     }
163 };
164
165 template <typename SERIALIZABLE>
166 class CChainObject : public CBaseChainObject
167 {
168 public:
169     SERIALIZABLE object;                    // the actual object
170
171     CChainObject() : CBaseChainObject() {}
172
173     CChainObject(uint16_t objType, const SERIALIZABLE &rObject) : CBaseChainObject(objType), object(rObject) { }
174
175     ADD_SERIALIZE_METHODS;
176
177     template <typename Stream, typename Operation>
178     inline void SerializationOp(Stream& s, Operation ser_action)
179     {
180         READWRITE(*(CBaseChainObject *)this);
181         READWRITE(object);
182     }
183
184     uint256 GetHash() const
185     {
186         CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
187
188         hw << object;
189         return GetHash();
190     }
191 };
192
193 // each notarization will have an opret object that contains various kind of proof of the notarization itself
194 // as well as recent POW and POS headers and entropy sources.
195 class CCrossChainProof
196 {
197 public:
198     enum
199     {
200         VERSION_INVALID = 0,
201         VERSION_FIRST = 1,
202         VERSION_CURRENT = 1,
203         VERSION_LAST = 1
204     };
205     uint32_t version;
206     std::vector<CBaseChainObject *> chainObjects;    // this owns the memory associated with chainObjects and deletes it on destructions
207
208     CCrossChainProof() : version(VERSION_CURRENT) {}
209     CCrossChainProof(const CCrossChainProof &oldObj)
210     {
211         CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
212         s << oldObj;
213         s >> *this;
214     }
215     CCrossChainProof(const std::vector<CBaseChainObject *> &objects, int Version=VERSION_CURRENT) : version(Version), chainObjects(objects) { }
216
217     ~CCrossChainProof()
218     {
219         DeleteOpRetObjects(chainObjects);
220         version = VERSION_INVALID;
221     }
222
223     ADD_SERIALIZE_METHODS;
224
225     template <typename Stream, typename Operation>
226     inline void SerializationOp(Stream& s, Operation ser_action) {
227         READWRITE(version);
228         if (ser_action.ForRead())
229         {
230             int32_t proofSize;
231             READWRITE(VARINT(proofSize));
232
233             bool error = false;
234             for (int i = 0; i < proofSize && !error; i++)
235             {
236                 try
237                 {
238                     uint16_t objType;
239                     READWRITE(objType);
240                     union {
241                         CChainObject<CBlockHeaderAndProof> *pNewHeader;
242                         CChainObject<CPartialTransactionProof> *pNewTx;
243                         CChainObject<uint256> *pNewProof;
244                         CChainObject<CBlockHeaderProof> *pNewHeaderRef;
245                         CChainObject<CPriorBlocksCommitment> *pPriors;
246                         CChainObject<CReserveTransfer> *pExport;
247                         CChainObject<CCrossChainProof> *pCrossChainProof;
248                         CBaseChainObject *pobj;
249                     };
250
251                     pobj = nullptr;
252
253                     switch(objType)
254                     {
255                         case CHAINOBJ_HEADER:
256                         {
257                             CBlockHeaderAndProof obj;
258                             READWRITE(obj);
259                             pNewHeader = new CChainObject<CBlockHeaderAndProof>();
260                             if (pNewHeader)
261                             {
262                                 pNewHeader->objectType = objType;
263                                 pNewHeader->object = obj;
264                             }
265                             break;
266                         }
267                         case CHAINOBJ_TRANSACTION_PROOF:
268                         {
269                             CPartialTransactionProof obj;
270                             READWRITE(obj);
271                             pNewTx = new CChainObject<CPartialTransactionProof>();
272                             if (pNewTx)
273                             {
274                                 pNewTx->objectType = objType;
275                                 pNewTx->object = obj;
276                             }
277                             break;
278                         }
279                         case CHAINOBJ_PROOF_ROOT:
280                         {
281                             uint256 obj;
282                             READWRITE(obj);
283                             pNewProof = new CChainObject<uint256>();
284                             if (pNewProof)
285                             {
286                                 pNewProof->objectType = objType;
287                                 pNewProof->object = obj;
288                             }
289                             break;
290                         }
291                         case CHAINOBJ_HEADER_REF:
292                         {
293                             CBlockHeaderProof obj;
294                             READWRITE(obj);
295                             pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
296                             if (pNewHeaderRef)
297                             {
298                                 pNewHeaderRef->objectType = objType;
299                                 pNewHeaderRef->object = obj;
300                             }
301                             break;
302                         }
303                         case CHAINOBJ_PRIORBLOCKS:
304                         {
305                             CPriorBlocksCommitment obj;
306                             READWRITE(obj);
307                             pPriors = new CChainObject<CPriorBlocksCommitment>();
308                             if (pPriors)
309                             {
310                                 pPriors->objectType = objType;
311                                 pPriors->object = obj;
312                             }
313                             break;
314                         }
315                         case CHAINOBJ_RESERVETRANSFER:
316                         {
317                             CReserveTransfer obj;
318                             READWRITE(obj);
319                             pExport = new CChainObject<CReserveTransfer>();
320                             if (pExport)
321                             {
322                                 pExport->objectType = objType;
323                                 pExport->object = obj;
324                             }
325                             break;
326                         }
327                         case CHAINOBJ_CROSSCHAINPROOF:
328                         {
329                             CCrossChainProof obj;
330                             READWRITE(obj);
331                             pCrossChainProof = new CChainObject<CCrossChainProof>();
332                             if (pCrossChainProof)
333                             {
334                                 pCrossChainProof->objectType = objType;
335                                 pCrossChainProof->object = obj;
336                             }
337                             break;
338                         }
339                         case CHAINOBJ_COMPOSITEOBJECT:
340                         {
341                             CCrossChainProof obj;
342                             READWRITE(obj);
343                             pCrossChainProof = new CChainObject<CCrossChainProof>();
344                             if (pCrossChainProof)
345                             {
346                                 pCrossChainProof->objectType = CHAINOBJ_COMPOSITEOBJECT;
347                                 pCrossChainProof->object = obj;
348                             }
349                             break;
350                         }
351                     }
352
353                     if (pobj)
354                     {
355                         //printf("%s: storing object, code %u\n", __func__, objType);
356                         chainObjects.push_back(pobj);
357                     }
358                 }
359                 catch(const std::exception& e)
360                 {
361                     error = true;
362                     break;
363                 }
364             }
365
366             if (error)
367             {
368                 printf("%s: ERROR: opret is likely corrupt\n", __func__);
369                 LogPrintf("%s: ERROR: opret is likely corrupt\n", __func__);
370                 DeleteOpRetObjects(chainObjects);
371             }
372         }
373         else
374         {
375             //printf("entering CCrossChainProof serialize\n");
376             int32_t proofSize = chainObjects.size();
377             READWRITE(VARINT(proofSize));
378             for (auto &oneVal : chainObjects)
379             {
380                 DehydrateChainObject(s, oneVal);
381             }
382         }
383     }
384
385     bool IsValid() const
386     {
387         return (version >= VERSION_FIRST || version <= VERSION_LAST);
388     }
389
390     bool Empty() const
391     {
392         return chainObjects.size() == 0;
393     }
394
395     const std::vector<uint16_t> TypeVector() const
396     {
397         std::vector<uint16_t> retVal;
398         for (auto &pChainObj : chainObjects)
399         {
400             if (pChainObj)
401             {
402                 retVal.push_back(pChainObj->objectType);
403             }
404         }
405         return retVal;
406     }
407
408     const CCrossChainProof &operator<<(const CPartialTransactionProof &partialTxProof)
409     {
410         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPartialTransactionProof>(CHAINOBJ_TRANSACTION_PROOF, partialTxProof)));
411         return *this;
412     }
413
414     const CCrossChainProof &operator<<(const CBlockHeaderAndProof &headerRefProof)
415     {
416         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderAndProof>(CHAINOBJ_HEADER_REF, headerRefProof)));
417         return *this;
418     }
419
420     const CCrossChainProof &operator<<(const CBlockHeaderProof &headerProof)
421     {
422         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderProof>(CHAINOBJ_HEADER, headerProof)));
423         return *this;
424     }
425
426     const CCrossChainProof &operator<<(const CPriorBlocksCommitment &priorBlocks)
427     {
428         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPriorBlocksCommitment>(CHAINOBJ_PRIORBLOCKS, priorBlocks)));
429         return *this;
430     }
431
432     const CCrossChainProof &operator<<(const uint256 &proofRoot)
433     {
434         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<uint256>(CHAINOBJ_PROOF_ROOT, proofRoot)));
435         return *this;
436     }
437
438     const CCrossChainProof &operator<<(const CReserveTransfer &reserveTransfer)
439     {
440         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CReserveTransfer>(CHAINOBJ_RESERVETRANSFER, reserveTransfer)));
441         return *this;
442     }
443
444     const CCrossChainProof &operator<<(const CCrossChainProof &crossChainProof)
445     {
446         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCrossChainProof>(CHAINOBJ_CROSSCHAINPROOF, crossChainProof)));
447         return *this;
448     }
449 };
450
451 // this must remain cast/data compatible with CCompositeChainObject
452 class CCompositeChainObject : public CCrossChainProof
453 {
454 public:
455     CCompositeChainObject() : CCrossChainProof() {}
456     CCompositeChainObject(const std::vector<CBaseChainObject *> &proofs, int Version=VERSION_CURRENT) : 
457         CCrossChainProof(proofs, Version) { }
458
459     ADD_SERIALIZE_METHODS;
460
461     template <typename Stream, typename Operation>
462     inline void SerializationOp(Stream& s, Operation ser_action) {
463         READWRITE(*(CCrossChainProof *)this);
464     }
465
466     const CCompositeChainObject &operator<<(const CCompositeChainObject &compositeChainObject)
467     {
468         chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCompositeChainObject>(CHAINOBJ_COMPOSITEOBJECT, compositeChainObject)));
469         return *this;
470     }
471 };
472
473 // returns a pointer to a base chain object, which can be cast to the
474 // object type indicated in its objType member
475 uint256 GetChainObjectHash(const CBaseChainObject &bo);
476
477 // returns a pointer to a base chain object, which can be cast to the
478 // object type indicated in its objType member
479 template <typename OStream>
480 CBaseChainObject *RehydrateChainObject(OStream &s)
481 {
482     int16_t objType;
483
484     try
485     {
486         s >> objType;
487     }
488     catch(const std::exception& e)
489     {
490         return NULL;
491     }
492
493     union {
494         CChainObject<CBlockHeaderAndProof> *pNewHeader;
495         CChainObject<CPartialTransactionProof> *pNewTx;
496         CChainObject<uint256> *pNewProof;
497         CChainObject<CBlockHeaderProof> *pNewHeaderRef;
498         CChainObject<CPriorBlocksCommitment> *pPriors;
499         CChainObject<CReserveTransfer> *pExport;
500         CChainObject<CCrossChainProof> *pCrossChainProof;
501         CChainObject<CCompositeChainObject> *pCompositeChainObject;
502         CBaseChainObject *retPtr;
503     };
504
505     retPtr = NULL;
506
507     switch(objType)
508     {
509         case CHAINOBJ_HEADER:
510             pNewHeader = new CChainObject<CBlockHeaderAndProof>();
511             if (pNewHeader)
512             {
513                 s >> pNewHeader->object;
514                 pNewHeader->objectType = objType;
515             }
516             break;
517         case CHAINOBJ_TRANSACTION_PROOF:
518             pNewTx = new CChainObject<CPartialTransactionProof>();
519             if (pNewTx)
520             {
521                 s >> pNewTx->object;
522                 pNewTx->objectType = objType;
523             }
524             break;
525         case CHAINOBJ_PROOF_ROOT:
526             pNewProof = new CChainObject<uint256>();
527             if (pNewProof)
528             {
529                 s >> pNewProof->object;
530                 pNewProof->objectType = objType;
531             }
532             break;
533         case CHAINOBJ_HEADER_REF:
534             pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
535             if (pNewHeaderRef)
536             {
537                 s >> pNewHeaderRef->object;
538                 pNewHeaderRef->objectType = objType;
539             }
540             break;
541         case CHAINOBJ_PRIORBLOCKS:
542             pPriors = new CChainObject<CPriorBlocksCommitment>();
543             if (pPriors)
544             {
545                 s >> pPriors->object;
546                 pPriors->objectType = objType;
547             }
548             break;
549         case CHAINOBJ_RESERVETRANSFER:
550             pExport = new CChainObject<CReserveTransfer>();
551             if (pExport)
552             {
553                 s >> pExport->object;
554                 pExport->objectType = objType;
555             }
556             break;
557         case CHAINOBJ_CROSSCHAINPROOF:
558             pCrossChainProof = new CChainObject<CCrossChainProof>();
559             if (pCrossChainProof)
560             {
561                 s >> pCrossChainProof->object;
562                 pCrossChainProof->objectType = objType;
563             }
564             break;
565         case CHAINOBJ_COMPOSITEOBJECT:
566             pCompositeChainObject = new CChainObject<CCompositeChainObject>();
567             if (pCompositeChainObject)
568             {
569                 s >> pCompositeChainObject->object;
570                 pCompositeChainObject->objectType = objType;
571             }
572             break;
573     }
574     return retPtr;
575 }
576
577 // returns a pointer to a base chain object, which can be cast to the
578 // object type indicated in its objType member
579 template <typename OStream>
580 bool DehydrateChainObject(OStream &s, const CBaseChainObject *pobj)
581 {
582     switch(pobj->objectType)
583     {
584         case CHAINOBJ_HEADER:
585         {
586             s << *(CChainObject<CBlockHeaderAndProof> *)pobj;
587             return true;
588         }
589
590         case CHAINOBJ_TRANSACTION_PROOF:
591         {
592             s << *(CChainObject<CPartialTransactionProof> *)pobj;
593             return true;
594         }
595
596         case CHAINOBJ_PROOF_ROOT:
597         {
598             s << *(CChainObject<uint256> *)pobj;
599             return true;
600         }
601
602         case CHAINOBJ_HEADER_REF:
603         {
604             s << *(CChainObject<CBlockHeaderProof> *)pobj;
605             return true;
606         }
607
608         case CHAINOBJ_PRIORBLOCKS:
609         {
610             s << *(CChainObject<CPriorBlocksCommitment> *)pobj;
611             return true;
612         }
613
614         case CHAINOBJ_RESERVETRANSFER:
615         {
616             s << *(CChainObject<CReserveTransfer> *)pobj;
617             return true;
618         }
619         case CHAINOBJ_CROSSCHAINPROOF:
620         {
621             s << *(CChainObject<CCrossChainProof> *)pobj;
622             return true;
623         }
624         case CHAINOBJ_COMPOSITEOBJECT:
625         {
626             s << *(CChainObject<CCompositeChainObject> *)pobj;
627             return true;
628         }
629     }
630     return false;
631 }
632
633 int8_t ObjTypeCode(const CBlockHeaderAndProof &obj);
634
635 int8_t ObjTypeCode(const CPartialTransactionProof &obj);
636
637 int8_t ObjTypeCode(const CBlockHeaderProof &obj);
638
639 int8_t ObjTypeCode(const CPriorBlocksCommitment &obj);
640
641 int8_t ObjTypeCode(const CReserveTransfer &obj);
642
643 int8_t ObjTypeCode(const CCrossChainProof &obj);
644
645 int8_t ObjTypeCode(const CCompositeChainObject &obj);
646
647 // this adds an opret to a mutable transaction that provides the necessary evidence of a signed, cheating stake transaction
648 CScript StoreOpRetArray(const std::vector<CBaseChainObject *> &objPtrs);
649
650 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
651
652 std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript);
653
654 // This data structure is used on an output that provides proof of stake validation for other crypto conditions
655 // with rate limited spends based on a PoS contest
656 class CPoSSelector
657 {
658 public:
659     uint32_t nBits;                         // PoS difficulty target
660     uint32_t nTargetSpacing;                // number of 1/1000ths of a block between selections (e.g. 1 == 1000 selections per block)
661
662     CPoSSelector(uint32_t bits, uint32_t TargetSpacing)
663     {
664         nBits = bits; 
665         nTargetSpacing = TargetSpacing;
666     }
667
668     ADD_SERIALIZE_METHODS;
669
670     template <typename Stream, typename Operation>
671     inline void SerializationOp(Stream& s, Operation ser_action) {
672         READWRITE(nBits);
673         READWRITE(nTargetSpacing);
674     }
675
676     CPoSSelector(const std::vector<unsigned char> &asVector)
677     {
678         FromVector(asVector, *this);
679     }
680
681     std::vector<unsigned char> AsVector()
682     {
683         return ::AsVector(*this);
684     }
685
686     bool IsValid() const
687     {
688         return nBits != 0;
689     }
690 };
691
692 // Additional data for an output pool used for a PBaaS chain's reward for service, such as mining, staking, node or electrum service
693 class CServiceReward
694 {
695 public:
696     uint32_t nVersion;                      // version of this chain definition data structure to allow for extensions (not daemon version)
697     uint16_t serviceType;                   // type of service
698     int32_t billingPeriod;                  // this is used to identify to which billing period of a chain, this reward applies
699
700     CServiceReward() : nVersion(PBAAS_VERSION_INVALID), serviceType(SERVICE_INVALID) {}
701
702     CServiceReward(PBAAS_SERVICE_TYPES ServiceType, int32_t period) : nVersion(PBAAS_VERSION), serviceType(ServiceType), billingPeriod(period) {}
703
704     ADD_SERIALIZE_METHODS;
705
706     template <typename Stream, typename Operation>
707     inline void SerializationOp(Stream& s, Operation ser_action) {
708         READWRITE(serviceType);
709         READWRITE(billingPeriod);
710     }
711
712     CServiceReward(const std::vector<unsigned char> &asVector)
713     {
714         FromVector(asVector, *this);
715     }
716
717     CServiceReward(const UniValue &obj) : nVersion(PBAAS_VERSION)
718     {
719         serviceType = uni_get_str(find_value(obj, "servicetype")) == "notarization" ? SERVICE_NOTARIZATION : SERVICE_INVALID;
720         billingPeriod = uni_get_int(find_value(obj, "billingperiod"));
721         if (!billingPeriod)
722         {
723             serviceType = SERVICE_INVALID;
724         }
725     }
726
727     CServiceReward(const CTransaction &tx, bool validate = false);
728
729     UniValue ToUniValue() const
730     {
731         UniValue obj(UniValue::VOBJ);
732         obj.push_back(Pair("servicetype", serviceType == SERVICE_NOTARIZATION ? "notarization" : "unknown"));
733         obj.push_back(Pair("billingperiod", billingPeriod));
734         return obj;
735     }
736
737     std::vector<unsigned char> AsVector()
738     {
739         return ::AsVector(*this);
740     }
741
742     bool IsValid() const
743     {
744         return serviceType != SERVICE_INVALID;
745     }
746 };
747
748 class CInputDescriptor
749 {
750 public:
751     CScript scriptPubKey;
752     CAmount nValue;
753     CTxIn txIn;
754     CInputDescriptor() : nValue(0) {}
755     CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {}
756 };
757
758 class CRPCChainData
759 {
760 public:
761     CCurrencyDefinition chainDefinition;  // chain information for the specific chain
762     std::string     rpcHost;                // host of the chain's daemon
763     int32_t         rpcPort;                // port of the chain's daemon
764     std::string     rpcUserPass;            // user and password for this daemon
765
766     CRPCChainData() {}
767     CRPCChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass) :
768         chainDefinition(chainDef), rpcHost{host}, rpcPort(port), rpcUserPass(userPass) {}
769
770     ADD_SERIALIZE_METHODS;
771
772     template <typename Stream, typename Operation>
773     inline void SerializationOp(Stream& s, Operation ser_action) {
774         READWRITE(chainDefinition);
775         READWRITE(rpcHost);
776         READWRITE(rpcPort);
777         READWRITE(rpcUserPass);
778     }
779
780     std::vector<unsigned char> AsVector()
781     {
782         return ::AsVector(*this);
783     }
784
785     bool IsValid() const
786     {
787         return chainDefinition.IsValid();
788     }
789
790     uint160 GetID()
791     {
792         return chainDefinition.GetID();
793     }
794 };
795
796 // Each merge mined chain gets an entry that includes information required to connect to a live daemon
797 // for that block, cross notarize, and validate notarizations.
798 class CPBaaSMergeMinedChainData : public CRPCChainData
799 {
800 public:
801     static const uint32_t MAX_MERGE_CHAINS = 15;
802     CBlock          block;                  // full block to submit upon winning header
803
804     CPBaaSMergeMinedChainData() {}
805     CPBaaSMergeMinedChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass, CBlock &blk) :
806         CRPCChainData(chainDef, host, port, userPass), block(blk) {}
807
808     ADD_SERIALIZE_METHODS;
809
810     template <typename Stream, typename Operation>
811     inline void SerializationOp(Stream& s, Operation ser_action) {
812         READWRITE(chainDefinition);
813         READWRITE(rpcHost);
814         READWRITE(rpcPort);
815         READWRITE(rpcUserPass);
816         READWRITE(block);
817     }
818
819     std::vector<unsigned char> AsVector()
820     {
821         return ::AsVector(*this);
822     }
823 };
824
825 class CConnectedChains
826 {
827 protected:
828     CPBaaSMergeMinedChainData *GetChainInfo(uint160 chainID);
829
830 public:
831     std::map<uint160, CPBaaSMergeMinedChainData> mergeMinedChains;
832     std::map<arith_uint256, CPBaaSMergeMinedChainData *> mergeMinedTargets;
833     std::map<uint160, CCurrencyDefinition> currencyDefCache;                            // protected by cs_main, which is used for lookup
834
835     std::string notaryChainVersion;
836     int32_t notaryChainHeight;
837     CRPCChainData notaryChain;                  // notary chain information
838
839     // if this is a fractional, liquid currency, reserve definitions go here
840     std::map<uint160, CCurrencyDefinition> reserveCurrencies;
841
842     CCurrencyDefinition thisChain;
843     bool readyToStart;
844     std::vector<CNodeData> defaultPeerNodes;    // updated by notarizations
845     std::vector<std::pair<int, CScript>> latestMiningOutputs; // accessible from all merge miners - can be invalid
846     CTxDestination  latestDestination;          // latest destination from miner output 0 - can be invalid
847     int64_t lastAggregation = 0;                // adjusted time of last aggregation
848
849     int32_t earnedNotarizationHeight;           // zero or the height of one or more potential submissions
850     CBlock earnedNotarizationBlock;
851     int32_t earnedNotarizationIndex;            // index of earned notarization in block
852
853     bool dirty;
854     bool lastSubmissionFailed;                  // if we submit a failed block, make another
855     std::map<arith_uint256, CBlockHeader> qualifiedHeaders;
856
857     CCriticalSection cs_mergemining;
858     CSemaphore sem_submitthread;
859
860     CConnectedChains() : readyToStart(0), sem_submitthread(0), earnedNotarizationHeight(0), dirty(0), lastSubmissionFailed(0) {}
861
862     arith_uint256 LowestTarget()
863     {
864         if (mergeMinedTargets.size())
865         {
866             return mergeMinedTargets.begin()->first;
867         }
868         else
869         {
870             return arith_uint256(0);
871         }
872     }
873
874     void SubmissionThread();
875     static void SubmissionThreadStub();
876     std::vector<std::pair<std::string, UniValue>> SubmitQualifiedBlocks();
877
878     void QueueNewBlockHeader(CBlockHeader &bh);
879     void QueueEarnedNotarization(CBlock &blk, int32_t txIndex, int32_t height);
880     void CheckImports();
881     void SignAndCommitImportTransactions(const CTransaction &lastImportTx, const std::vector<CTransaction> &transactions);
882     // send new imports from this chain to the specified chain, which generally will be the notary chain
883     void ProcessLocalImports();
884
885     bool AddMergedBlock(CPBaaSMergeMinedChainData &blkData);
886     bool RemoveMergedBlock(uint160 chainID);
887     bool GetChainInfo(uint160 chainID, CRPCChainData &rpcChainData);
888     void PruneOldChains(uint32_t pruneBefore);
889     uint32_t CombineBlocks(CBlockHeader &bh);
890
891     // returns false if destinations are empty or first is not either pubkey or pubkeyhash
892     bool SetLatestMiningOutputs(const std::vector<std::pair<int, CScript>> &minerOutputs, CTxDestination &firstDestinationOut);
893     void AggregateChainTransfers(const CTxDestination &feeOutput, uint32_t nHeight);
894     CCurrencyDefinition GetCachedCurrency(const uint160 &currencyID);
895
896     bool GetLastImport(const uint160 &systemID, 
897                        CTransaction &lastImport, 
898                        CPartialTransactionProof &crossChainExport, 
899                        CCrossChainImport &ccImport, 
900                        CCrossChainExport &ccCrossExport);
901
902     // returns newly created import transactions to the specified chain from exports on this chain specified chain
903     bool CreateLatestImports(const CCurrencyDefinition &chainDef, 
904                              const CTransaction &lastCrossChainImport, 
905                              const CTransaction &importTxTemplate,
906                              const CTransaction &lastConfirmedNotarization,
907                              const CCurrencyValueMap &totalAvailableInput,
908                              CAmount TotalNativeInput,
909                              std::vector<CTransaction> &newImports);
910
911     CRPCChainData &NotaryChain()
912     {
913         return notaryChain;
914     }
915
916     uint32_t NotaryChainHeight();
917
918     CCurrencyDefinition &ThisChain()
919     {
920         return thisChain;
921     }
922
923     int GetThisChainPort() const;
924
925     CCoinbaseCurrencyState GetCurrencyState(int32_t height);
926
927     bool CheckVerusPBaaSAvailable(UniValue &chainInfo, UniValue &chainDef);
928     bool CheckVerusPBaaSAvailable();      // may use RPC to call Verus
929     bool IsVerusPBaaSAvailable();
930     std::vector<CCurrencyDefinition> GetMergeMinedChains()
931     {
932         std::vector<CCurrencyDefinition> ret;
933         LOCK(cs_mergemining);
934         for (auto &chain : mergeMinedChains)
935         {
936             ret.push_back(chain.second.chainDefinition);
937         }
938         return ret;
939     }
940
941     const std::map<uint160, CCurrencyDefinition> &ReserveCurrencies()
942     {
943         return reserveCurrencies;
944     }
945
946     bool LoadReserveCurrencies();
947 };
948
949 template <typename TOBJ>
950 CTxOut MakeCC1of1Vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector<CTxDestination> vDest, const TOBJ &obj)
951 {
952     assert(vDest.size() < 256);
953
954     CTxOut vout;
955     CC *payoutCond = MakeCCcond1(evalcode, pk);
956     vout = CTxOut(nValue, CCPubKey(payoutCond));
957     cc_free(payoutCond);
958
959     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
960     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
961
962     // add the object to the end of the script
963     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
964     return(vout);
965 }
966
967 template <typename TOBJ>
968 CTxOut MakeCC1ofAnyVout(uint8_t evalcode, CAmount nValue, std::vector<CTxDestination> vDest, const TOBJ &obj, const CPubKey &pk=CPubKey())
969 {
970     // if pk is valid, we will make sure that it is one of the signature options on this CC
971     if (pk.IsValid())
972     {
973         CCcontract_info C;
974         CCcontract_info *cp;
975         cp = CCinit(&C, evalcode);
976         int i;
977         bool addPubKey = false;
978         for (i = 0; i < vDest.size(); i++)
979         {
980             CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), vDest[i]));
981             if ((oneKey.IsValid() && oneKey == pk) || CKeyID(GetDestinationID(vDest[i])) == pk.GetID())
982             {
983                 // found, so don't add
984                 break;
985             }
986         }
987         // if not found, add the pubkey
988         if (i >= vDest.size())
989         {
990             vDest.push_back(CTxDestination(pk));
991         }
992     }
993
994     CTxOut vout;
995     CC *payoutCond = MakeCCcondAny(evalcode, vDest);
996     vout = CTxOut(nValue, CCPubKey(payoutCond));
997     cc_free(payoutCond);
998
999     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1000     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 0, (uint8_t)(vDest.size()), vDest, vvch);
1001
1002     for (auto dest : vDest)
1003     {
1004         CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest));
1005         std::vector<unsigned char> bytes = GetDestinationBytes(dest);
1006         if ((!oneKey.IsValid() && bytes.size() != 20) || (bytes.size() != 33 && bytes.size() != 20))
1007         {
1008             printf("Invalid destination %s\n", EncodeDestination(dest).c_str());
1009         }
1010     }
1011
1012     // add the object to the end of the script
1013     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1014     return(vout);
1015 }
1016
1017 template <typename TOBJ>
1018 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, const TOBJ &obj)
1019 {
1020     CTxOut vout;
1021     CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1022     vout = CTxOut(nValue,CCPubKey(payoutCond));
1023     cc_free(payoutCond);
1024
1025     std::vector<CPubKey> vpk({pk1, pk2});
1026     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1027     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, 2, vpk, vvch);
1028
1029     // add the object to the end of the script
1030     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1031     return(vout);
1032 }
1033
1034 template <typename TOBJ>
1035 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector<CTxDestination> vDest, const TOBJ &obj)
1036 {
1037     CTxOut vout;
1038     CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1039     vout = CTxOut(nValue,CCPubKey(payoutCond));
1040     cc_free(payoutCond);
1041
1042     std::vector<CPubKey> vpk({pk1, pk2});
1043     std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1044     COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
1045
1046     // add the object to the end of the script
1047     vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1048     return(vout);
1049 }
1050
1051 bool IsVerusActive();
1052 bool IsVerusMainnetActive();
1053
1054 // used to export coins from one chain to another, if they are not native, they are represented on the other
1055 // chain as tokens
1056 bool ValidateCrossChainExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1057 bool IsCrossChainExportInput(const CScript &scriptSig);
1058
1059 // used to validate import of coins from one chain to another. if they are not native and are supported,
1060 // they are represented o the chain as tokens
1061 bool ValidateCrossChainImport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1062 bool IsCrossChainImportInput(const CScript &scriptSig);
1063
1064 // used to validate a specific service reward based on the spending transaction
1065 bool ValidateServiceReward(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1066 bool IsServiceRewardInput(const CScript &scriptSig);
1067
1068 // used as a proxy token output for a reserve currency on its fractional reserve chain
1069 bool ValidateReserveOutput(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1070 bool IsReserveOutputInput(const CScript &scriptSig);
1071
1072 // used to transfer a reserve currency between chains
1073 bool ValidateReserveTransfer(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1074 bool IsReserveTransferInput(const CScript &scriptSig);
1075
1076 // used as exchange tokens between reserves and fractional reserves
1077 bool ValidateReserveExchange(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1078 bool IsReserveExchangeInput(const CScript &scriptSig);
1079
1080 // used to deposit reserves into a reserve UTXO set
1081 bool ValidateReserveDeposit(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1082 bool IsReserveDepositInput(const CScript &scriptSig);
1083
1084 bool ValidateChainDefinition(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1085 bool IsChainDefinitionInput(const CScript &scriptSig);
1086
1087 bool ValidateCurrencyState(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1088 bool IsCurrencyStateInput(const CScript &scriptSig);
1089
1090 bool GetCCParams(const CScript &scr, COptCCParams &ccParams);
1091
1092 bool SetPeerNodes(const UniValue &nodes);
1093 bool SetThisChain(const UniValue &chainDefinition);
1094 const uint256 &CurrencyDefHash(UniValue &chainDefinition);
1095
1096 extern CConnectedChains ConnectedChains;
1097 extern uint160 ASSETCHAINS_CHAINID;
1098 CCoinbaseCurrencyState GetInitialCurrencyState(CCurrencyDefinition &chainDef);
1099
1100 #endif
This page took 0.080993 seconds and 2 git commands to generate.