1 /********************************************************************
2 * (C) 2019 Michael Toutonghi
4 * Distributed under the MIT software license, see the accompanying
5 * file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 * This provides support for PBaaS initialization, notarization, and cross-chain token
8 * transactions and enabling liquid or non-liquid tokens across the
20 #include "cc/CCinclude.h"
22 #include "script/script.h"
24 #include "pbaas/crosschainrpc.h"
25 #include "pbaas/reserves.h"
28 #include <boost/algorithm/string.hpp>
30 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex, bool fIncludeAsm=true);
32 class CPBaaSNotarization;
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
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
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
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 {
52 SERVICE_NOTARIZATION = 1,
56 // these are object types that can be stored and recognized in an opret array
57 enum CHAIN_OBJECT_TYPES
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
70 // the proof of an opret output, which is simply the types of objects and hashes of each
74 uint32_t orIndex; // index into the opret objects to begin with
75 std::vector<uint8_t> types;
76 std::vector<uint256> hashes;
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) {}
81 void AddObject(CHAIN_OBJECT_TYPES typeCode, uint256 objHash)
83 types.push_back(typeCode);
84 hashes.push_back(objHash);
87 template <typename CHAINOBJTYPE>
88 void AddObject(CHAINOBJTYPE &co, uint256 objHash)
90 types.push_back(ObjTypeCode(co));
91 hashes.push_back(objHash);
94 ADD_SERIALIZE_METHODS;
96 template <typename Stream, typename Operation>
97 inline void SerializationOp(Stream& s, Operation ser_action)
108 uint256 hash; // block hash
109 CPBaaSPreHeader preHeader; // non-canonical pre-header data of source chain
111 CHeaderRef() : hash() {}
112 CHeaderRef(uint256 &rHash, CPBaaSPreHeader ph) : hash(rHash), preHeader(ph) {}
113 CHeaderRef(const CBlockHeader &bh) : hash(bh.GetHash()), preHeader(bh) {}
115 ADD_SERIALIZE_METHODS;
117 template <typename Stream, typename Operation>
118 inline void SerializationOp(Stream& s, Operation ser_action)
121 READWRITE(preHeader);
124 uint256 GetHash() { return hash; }
127 class CPriorBlocksCommitment
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
133 CPriorBlocksCommitment() : priorBlocks() {}
134 CPriorBlocksCommitment(const std::vector<uint256> &priors, const uint256 &pastTypes) : priorBlocks(priors), pastBlockType(pastTypes) {}
136 ADD_SERIALIZE_METHODS;
138 template <typename Stream, typename Operation>
139 inline void SerializationOp(Stream& s, Operation ser_action)
141 READWRITE(priorBlocks);
142 READWRITE(pastBlockType);
146 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
148 class CBaseChainObject
151 uint16_t objectType; // type of object, such as blockheader, transaction, proof, tokentx, etc.
153 CBaseChainObject() : objectType(CHAINOBJ_INVALID) {}
154 CBaseChainObject(uint16_t objType) : objectType(objType) {}
156 ADD_SERIALIZE_METHODS;
158 template <typename Stream, typename Operation>
159 inline void SerializationOp(Stream& s, Operation ser_action)
161 READWRITE(objectType);
165 template <typename SERIALIZABLE>
166 class CChainObject : public CBaseChainObject
169 SERIALIZABLE object; // the actual object
171 CChainObject() : CBaseChainObject() {}
173 CChainObject(uint16_t objType, const SERIALIZABLE &rObject) : CBaseChainObject(objType), object(rObject) { }
175 ADD_SERIALIZE_METHODS;
177 template <typename Stream, typename Operation>
178 inline void SerializationOp(Stream& s, Operation ser_action)
180 READWRITE(*(CBaseChainObject *)this);
184 uint256 GetHash() const
186 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
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
206 std::vector<CBaseChainObject *> chainObjects; // this owns the memory associated with chainObjects and deletes it on destructions
208 CCrossChainProof() : version(VERSION_CURRENT) {}
209 CCrossChainProof(const CCrossChainProof &oldObj)
211 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
215 CCrossChainProof(const std::vector<CBaseChainObject *> &objects, int Version=VERSION_CURRENT) : version(Version), chainObjects(objects) { }
219 DeleteOpRetObjects(chainObjects);
220 version = VERSION_INVALID;
223 ADD_SERIALIZE_METHODS;
225 template <typename Stream, typename Operation>
226 inline void SerializationOp(Stream& s, Operation ser_action) {
228 if (ser_action.ForRead())
231 READWRITE(VARINT(proofSize));
234 for (int i = 0; i < proofSize && !error; i++)
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;
255 case CHAINOBJ_HEADER:
257 CBlockHeaderAndProof obj;
259 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
262 pNewHeader->objectType = objType;
263 pNewHeader->object = obj;
267 case CHAINOBJ_TRANSACTION_PROOF:
269 CPartialTransactionProof obj;
271 pNewTx = new CChainObject<CPartialTransactionProof>();
274 pNewTx->objectType = objType;
275 pNewTx->object = obj;
279 case CHAINOBJ_PROOF_ROOT:
283 pNewProof = new CChainObject<uint256>();
286 pNewProof->objectType = objType;
287 pNewProof->object = obj;
291 case CHAINOBJ_HEADER_REF:
293 CBlockHeaderProof obj;
295 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
298 pNewHeaderRef->objectType = objType;
299 pNewHeaderRef->object = obj;
303 case CHAINOBJ_PRIORBLOCKS:
305 CPriorBlocksCommitment obj;
307 pPriors = new CChainObject<CPriorBlocksCommitment>();
310 pPriors->objectType = objType;
311 pPriors->object = obj;
315 case CHAINOBJ_RESERVETRANSFER:
317 CReserveTransfer obj;
319 pExport = new CChainObject<CReserveTransfer>();
322 pExport->objectType = objType;
323 pExport->object = obj;
327 case CHAINOBJ_CROSSCHAINPROOF:
329 CCrossChainProof obj;
331 pCrossChainProof = new CChainObject<CCrossChainProof>();
332 if (pCrossChainProof)
334 pCrossChainProof->objectType = objType;
335 pCrossChainProof->object = obj;
339 case CHAINOBJ_COMPOSITEOBJECT:
341 CCrossChainProof obj;
343 pCrossChainProof = new CChainObject<CCrossChainProof>();
344 if (pCrossChainProof)
346 pCrossChainProof->objectType = CHAINOBJ_COMPOSITEOBJECT;
347 pCrossChainProof->object = obj;
355 //printf("%s: storing object, code %u\n", __func__, objType);
356 chainObjects.push_back(pobj);
359 catch(const std::exception& e)
368 printf("%s: ERROR: opret is likely corrupt\n", __func__);
369 LogPrintf("%s: ERROR: opret is likely corrupt\n", __func__);
370 DeleteOpRetObjects(chainObjects);
375 //printf("entering CCrossChainProof serialize\n");
376 int32_t proofSize = chainObjects.size();
377 READWRITE(VARINT(proofSize));
378 for (auto &oneVal : chainObjects)
380 DehydrateChainObject(s, oneVal);
387 return (version >= VERSION_FIRST || version <= VERSION_LAST);
392 return chainObjects.size() == 0;
395 const std::vector<uint16_t> TypeVector() const
397 std::vector<uint16_t> retVal;
398 for (auto &pChainObj : chainObjects)
402 retVal.push_back(pChainObj->objectType);
408 const CCrossChainProof &operator<<(const CPartialTransactionProof &partialTxProof)
410 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPartialTransactionProof>(CHAINOBJ_TRANSACTION_PROOF, partialTxProof)));
414 const CCrossChainProof &operator<<(const CBlockHeaderAndProof &headerRefProof)
416 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderAndProof>(CHAINOBJ_HEADER_REF, headerRefProof)));
420 const CCrossChainProof &operator<<(const CBlockHeaderProof &headerProof)
422 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderProof>(CHAINOBJ_HEADER, headerProof)));
426 const CCrossChainProof &operator<<(const CPriorBlocksCommitment &priorBlocks)
428 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPriorBlocksCommitment>(CHAINOBJ_PRIORBLOCKS, priorBlocks)));
432 const CCrossChainProof &operator<<(const uint256 &proofRoot)
434 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<uint256>(CHAINOBJ_PROOF_ROOT, proofRoot)));
438 const CCrossChainProof &operator<<(const CReserveTransfer &reserveTransfer)
440 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CReserveTransfer>(CHAINOBJ_RESERVETRANSFER, reserveTransfer)));
444 const CCrossChainProof &operator<<(const CCrossChainProof &crossChainProof)
446 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCrossChainProof>(CHAINOBJ_CROSSCHAINPROOF, crossChainProof)));
451 // this must remain cast/data compatible with CCompositeChainObject
452 class CCompositeChainObject : public CCrossChainProof
455 CCompositeChainObject() : CCrossChainProof() {}
456 CCompositeChainObject(const std::vector<CBaseChainObject *> &proofs, int Version=VERSION_CURRENT) :
457 CCrossChainProof(proofs, Version) { }
459 ADD_SERIALIZE_METHODS;
461 template <typename Stream, typename Operation>
462 inline void SerializationOp(Stream& s, Operation ser_action) {
463 READWRITE(*(CCrossChainProof *)this);
466 const CCompositeChainObject &operator<<(const CCompositeChainObject &compositeChainObject)
468 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCompositeChainObject>(CHAINOBJ_COMPOSITEOBJECT, compositeChainObject)));
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);
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)
488 catch(const std::exception& e)
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;
509 case CHAINOBJ_HEADER:
510 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
513 s >> pNewHeader->object;
514 pNewHeader->objectType = objType;
517 case CHAINOBJ_TRANSACTION_PROOF:
518 pNewTx = new CChainObject<CPartialTransactionProof>();
522 pNewTx->objectType = objType;
525 case CHAINOBJ_PROOF_ROOT:
526 pNewProof = new CChainObject<uint256>();
529 s >> pNewProof->object;
530 pNewProof->objectType = objType;
533 case CHAINOBJ_HEADER_REF:
534 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
537 s >> pNewHeaderRef->object;
538 pNewHeaderRef->objectType = objType;
541 case CHAINOBJ_PRIORBLOCKS:
542 pPriors = new CChainObject<CPriorBlocksCommitment>();
545 s >> pPriors->object;
546 pPriors->objectType = objType;
549 case CHAINOBJ_RESERVETRANSFER:
550 pExport = new CChainObject<CReserveTransfer>();
553 s >> pExport->object;
554 pExport->objectType = objType;
557 case CHAINOBJ_CROSSCHAINPROOF:
558 pCrossChainProof = new CChainObject<CCrossChainProof>();
559 if (pCrossChainProof)
561 s >> pCrossChainProof->object;
562 pCrossChainProof->objectType = objType;
565 case CHAINOBJ_COMPOSITEOBJECT:
566 pCompositeChainObject = new CChainObject<CCompositeChainObject>();
567 if (pCompositeChainObject)
569 s >> pCompositeChainObject->object;
570 pCompositeChainObject->objectType = objType;
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)
582 switch(pobj->objectType)
584 case CHAINOBJ_HEADER:
586 s << *(CChainObject<CBlockHeaderAndProof> *)pobj;
590 case CHAINOBJ_TRANSACTION_PROOF:
592 s << *(CChainObject<CPartialTransactionProof> *)pobj;
596 case CHAINOBJ_PROOF_ROOT:
598 s << *(CChainObject<uint256> *)pobj;
602 case CHAINOBJ_HEADER_REF:
604 s << *(CChainObject<CBlockHeaderProof> *)pobj;
608 case CHAINOBJ_PRIORBLOCKS:
610 s << *(CChainObject<CPriorBlocksCommitment> *)pobj;
614 case CHAINOBJ_RESERVETRANSFER:
616 s << *(CChainObject<CReserveTransfer> *)pobj;
619 case CHAINOBJ_CROSSCHAINPROOF:
621 s << *(CChainObject<CCrossChainProof> *)pobj;
624 case CHAINOBJ_COMPOSITEOBJECT:
626 s << *(CChainObject<CCompositeChainObject> *)pobj;
633 int8_t ObjTypeCode(const CBlockHeaderAndProof &obj);
635 int8_t ObjTypeCode(const CPartialTransactionProof &obj);
637 int8_t ObjTypeCode(const CBlockHeaderProof &obj);
639 int8_t ObjTypeCode(const CPriorBlocksCommitment &obj);
641 int8_t ObjTypeCode(const CReserveTransfer &obj);
643 int8_t ObjTypeCode(const CCrossChainProof &obj);
645 int8_t ObjTypeCode(const CCompositeChainObject &obj);
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);
650 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
652 std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript);
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
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)
662 CPoSSelector(uint32_t bits, uint32_t TargetSpacing)
665 nTargetSpacing = TargetSpacing;
668 ADD_SERIALIZE_METHODS;
670 template <typename Stream, typename Operation>
671 inline void SerializationOp(Stream& s, Operation ser_action) {
673 READWRITE(nTargetSpacing);
676 CPoSSelector(const std::vector<unsigned char> &asVector)
678 FromVector(asVector, *this);
681 std::vector<unsigned char> AsVector()
683 return ::AsVector(*this);
692 // Additional data for an output pool used for a PBaaS chain's reward for service, such as mining, staking, node or electrum service
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
700 CServiceReward() : nVersion(PBAAS_VERSION_INVALID), serviceType(SERVICE_INVALID) {}
702 CServiceReward(PBAAS_SERVICE_TYPES ServiceType, int32_t period) : nVersion(PBAAS_VERSION), serviceType(ServiceType), billingPeriod(period) {}
704 ADD_SERIALIZE_METHODS;
706 template <typename Stream, typename Operation>
707 inline void SerializationOp(Stream& s, Operation ser_action) {
708 READWRITE(serviceType);
709 READWRITE(billingPeriod);
712 CServiceReward(const std::vector<unsigned char> &asVector)
714 FromVector(asVector, *this);
717 CServiceReward(const UniValue &obj) : nVersion(PBAAS_VERSION)
719 serviceType = uni_get_str(find_value(obj, "servicetype")) == "notarization" ? SERVICE_NOTARIZATION : SERVICE_INVALID;
720 billingPeriod = uni_get_int(find_value(obj, "billingperiod"));
723 serviceType = SERVICE_INVALID;
727 CServiceReward(const CTransaction &tx, bool validate = false);
729 UniValue ToUniValue() const
731 UniValue obj(UniValue::VOBJ);
732 obj.push_back(Pair("servicetype", serviceType == SERVICE_NOTARIZATION ? "notarization" : "unknown"));
733 obj.push_back(Pair("billingperiod", billingPeriod));
737 std::vector<unsigned char> AsVector()
739 return ::AsVector(*this);
744 return serviceType != SERVICE_INVALID;
748 class CInputDescriptor
751 CScript scriptPubKey;
754 CInputDescriptor() : nValue(0) {}
755 CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {}
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
767 CRPCChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass) :
768 chainDefinition(chainDef), rpcHost{host}, rpcPort(port), rpcUserPass(userPass) {}
770 ADD_SERIALIZE_METHODS;
772 template <typename Stream, typename Operation>
773 inline void SerializationOp(Stream& s, Operation ser_action) {
774 READWRITE(chainDefinition);
777 READWRITE(rpcUserPass);
780 std::vector<unsigned char> AsVector()
782 return ::AsVector(*this);
787 return chainDefinition.IsValid();
792 return chainDefinition.GetID();
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
801 static const uint32_t MAX_MERGE_CHAINS = 15;
802 CBlock block; // full block to submit upon winning header
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) {}
808 ADD_SERIALIZE_METHODS;
810 template <typename Stream, typename Operation>
811 inline void SerializationOp(Stream& s, Operation ser_action) {
812 READWRITE(chainDefinition);
815 READWRITE(rpcUserPass);
819 std::vector<unsigned char> AsVector()
821 return ::AsVector(*this);
825 class CConnectedChains
828 CPBaaSMergeMinedChainData *GetChainInfo(uint160 chainID);
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
835 std::string notaryChainVersion;
836 int32_t notaryChainHeight;
837 CRPCChainData notaryChain; // notary chain information
839 // if this is a fractional, liquid currency, reserve definitions go here
840 std::map<uint160, CCurrencyDefinition> reserveCurrencies;
842 CCurrencyDefinition thisChain;
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
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
854 bool lastSubmissionFailed; // if we submit a failed block, make another
855 std::map<arith_uint256, CBlockHeader> qualifiedHeaders;
857 CCriticalSection cs_mergemining;
858 CSemaphore sem_submitthread;
860 CConnectedChains() : readyToStart(0), sem_submitthread(0), earnedNotarizationHeight(0), dirty(0), lastSubmissionFailed(0) {}
862 arith_uint256 LowestTarget()
864 if (mergeMinedTargets.size())
866 return mergeMinedTargets.begin()->first;
870 return arith_uint256(0);
874 void SubmissionThread();
875 static void SubmissionThreadStub();
876 std::vector<std::pair<std::string, UniValue>> SubmitQualifiedBlocks();
878 void QueueNewBlockHeader(CBlockHeader &bh);
879 void QueueEarnedNotarization(CBlock &blk, int32_t txIndex, int32_t height);
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();
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);
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 ¤cyID);
896 bool GetLastImport(const uint160 &systemID,
897 CTransaction &lastImport,
898 CPartialTransactionProof &crossChainExport,
899 CCrossChainImport &ccImport,
900 CCrossChainExport &ccCrossExport);
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);
911 CRPCChainData &NotaryChain()
916 uint32_t NotaryChainHeight();
918 CCurrencyDefinition &ThisChain()
923 int GetThisChainPort() const;
925 CCoinbaseCurrencyState GetCurrencyState(int32_t height);
927 bool CheckVerusPBaaSAvailable(UniValue &chainInfo, UniValue &chainDef);
928 bool CheckVerusPBaaSAvailable(); // may use RPC to call Verus
929 bool IsVerusPBaaSAvailable();
930 std::vector<CCurrencyDefinition> GetMergeMinedChains()
932 std::vector<CCurrencyDefinition> ret;
933 LOCK(cs_mergemining);
934 for (auto &chain : mergeMinedChains)
936 ret.push_back(chain.second.chainDefinition);
941 const std::map<uint160, CCurrencyDefinition> &ReserveCurrencies()
943 return reserveCurrencies;
946 bool LoadReserveCurrencies();
949 template <typename TOBJ>
950 CTxOut MakeCC1of1Vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector<CTxDestination> vDest, const TOBJ &obj)
952 assert(vDest.size() < 256);
955 CC *payoutCond = MakeCCcond1(evalcode, pk);
956 vout = CTxOut(nValue, CCPubKey(payoutCond));
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);
962 // add the object to the end of the script
963 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
967 template <typename TOBJ>
968 CTxOut MakeCC1ofAnyVout(uint8_t evalcode, CAmount nValue, std::vector<CTxDestination> vDest, const TOBJ &obj, const CPubKey &pk=CPubKey())
970 // if pk is valid, we will make sure that it is one of the signature options on this CC
975 cp = CCinit(&C, evalcode);
977 bool addPubKey = false;
978 for (i = 0; i < vDest.size(); i++)
980 CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), vDest[i]));
981 if ((oneKey.IsValid() && oneKey == pk) || CKeyID(GetDestinationID(vDest[i])) == pk.GetID())
983 // found, so don't add
987 // if not found, add the pubkey
988 if (i >= vDest.size())
990 vDest.push_back(CTxDestination(pk));
995 CC *payoutCond = MakeCCcondAny(evalcode, vDest);
996 vout = CTxOut(nValue, CCPubKey(payoutCond));
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);
1002 for (auto dest : vDest)
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))
1008 printf("Invalid destination %s\n", EncodeDestination(dest).c_str());
1012 // add the object to the end of the script
1013 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1017 template <typename TOBJ>
1018 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, const TOBJ &obj)
1021 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1022 vout = CTxOut(nValue,CCPubKey(payoutCond));
1023 cc_free(payoutCond);
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);
1029 // add the object to the end of the script
1030 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1034 template <typename TOBJ>
1035 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector<CTxDestination> vDest, const TOBJ &obj)
1038 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1039 vout = CTxOut(nValue,CCPubKey(payoutCond));
1040 cc_free(payoutCond);
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);
1046 // add the object to the end of the script
1047 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1051 bool IsVerusActive();
1052 bool IsVerusMainnetActive();
1054 // used to export coins from one chain to another, if they are not native, they are represented on the other
1056 bool ValidateCrossChainExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1057 bool IsCrossChainExportInput(const CScript &scriptSig);
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);
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);
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);
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);
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);
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);
1084 bool ValidateChainDefinition(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1085 bool IsChainDefinitionInput(const CScript &scriptSig);
1087 bool ValidateCurrencyState(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1088 bool IsCurrencyStateInput(const CScript &scriptSig);
1090 bool GetCCParams(const CScript &scr, COptCCParams &ccParams);
1092 bool SetPeerNodes(const UniValue &nodes);
1093 bool SetThisChain(const UniValue &chainDefinition);
1094 const uint256 &CurrencyDefHash(UniValue &chainDefinition);
1096 extern CConnectedChains ConnectedChains;
1097 extern uint160 ASSETCHAINS_CHAINID;
1098 CCoinbaseCurrencyState GetInitialCurrencyState(CCurrencyDefinition &chainDef);