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