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;
33 class TransactionBuilder;
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
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
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
49 // these are object types that can be stored and recognized in an opret array
50 enum CHAIN_OBJECT_TYPES
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
63 // the proof of an opret output, which is simply the types of objects and hashes of each
67 uint32_t orIndex; // index into the opret objects to begin with
68 std::vector<uint8_t> types;
69 std::vector<uint256> hashes;
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) {}
74 void AddObject(CHAIN_OBJECT_TYPES typeCode, uint256 objHash)
76 types.push_back(typeCode);
77 hashes.push_back(objHash);
80 template <typename CHAINOBJTYPE>
81 void AddObject(CHAINOBJTYPE &co, uint256 objHash)
83 types.push_back(ObjTypeCode(co));
84 hashes.push_back(objHash);
87 ADD_SERIALIZE_METHODS;
89 template <typename Stream, typename Operation>
90 inline void SerializationOp(Stream& s, Operation ser_action)
101 uint256 hash; // block hash
102 CPBaaSPreHeader preHeader; // non-canonical pre-header data of source chain
104 CHeaderRef() : hash() {}
105 CHeaderRef(uint256 &rHash, CPBaaSPreHeader ph) : hash(rHash), preHeader(ph) {}
106 CHeaderRef(const CBlockHeader &bh) : hash(bh.GetHash()), preHeader(bh) {}
108 ADD_SERIALIZE_METHODS;
110 template <typename Stream, typename Operation>
111 inline void SerializationOp(Stream& s, Operation ser_action)
114 READWRITE(preHeader);
117 uint256 GetHash() { return hash; }
120 class CPriorBlocksCommitment
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
126 CPriorBlocksCommitment() : priorBlocks() {}
127 CPriorBlocksCommitment(const std::vector<uint256> &priors, const uint256 &pastTypes) : priorBlocks(priors), pastBlockType(pastTypes) {}
129 ADD_SERIALIZE_METHODS;
131 template <typename Stream, typename Operation>
132 inline void SerializationOp(Stream& s, Operation ser_action)
134 READWRITE(priorBlocks);
135 READWRITE(pastBlockType);
139 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
141 class CBaseChainObject
144 uint16_t objectType; // type of object, such as blockheader, transaction, proof, tokentx, etc.
146 CBaseChainObject() : objectType(CHAINOBJ_INVALID) {}
147 CBaseChainObject(uint16_t objType) : objectType(objType) {}
149 ADD_SERIALIZE_METHODS;
151 template <typename Stream, typename Operation>
152 inline void SerializationOp(Stream& s, Operation ser_action)
154 READWRITE(objectType);
158 template <typename SERIALIZABLE>
159 class CChainObject : public CBaseChainObject
162 SERIALIZABLE object; // the actual object
164 CChainObject() : CBaseChainObject() {}
166 CChainObject(uint16_t objType, const SERIALIZABLE &rObject) : CBaseChainObject(objType), object(rObject) { }
168 ADD_SERIALIZE_METHODS;
170 template <typename Stream, typename Operation>
171 inline void SerializationOp(Stream& s, Operation ser_action)
173 READWRITE(*(CBaseChainObject *)this);
177 uint256 GetHash() const
179 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
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
199 std::vector<CBaseChainObject *> chainObjects; // this owns the memory associated with chainObjects and deletes it on destructions
201 CCrossChainProof() : version(VERSION_CURRENT) {}
202 CCrossChainProof(const CCrossChainProof &oldObj)
204 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
208 CCrossChainProof(const std::vector<CBaseChainObject *> &objects, int Version=VERSION_CURRENT) : version(Version), chainObjects(objects) { }
212 DeleteOpRetObjects(chainObjects);
213 version = VERSION_INVALID;
216 const CCrossChainProof &operator=(const CCrossChainProof &operand)
218 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
220 DeleteOpRetObjects(chainObjects);
225 ADD_SERIALIZE_METHODS;
227 template <typename Stream, typename Operation>
228 inline void SerializationOp(Stream& s, Operation ser_action) {
230 if (ser_action.ForRead())
233 READWRITE(VARINT(proofSize));
236 for (int i = 0; i < proofSize && !error; i++)
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;
257 case CHAINOBJ_HEADER:
259 CBlockHeaderAndProof obj;
261 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
264 pNewHeader->objectType = objType;
265 pNewHeader->object = obj;
269 case CHAINOBJ_TRANSACTION_PROOF:
271 CPartialTransactionProof obj;
273 pNewTx = new CChainObject<CPartialTransactionProof>();
276 pNewTx->objectType = objType;
277 pNewTx->object = obj;
281 case CHAINOBJ_PROOF_ROOT:
285 pNewProof = new CChainObject<uint256>();
288 pNewProof->objectType = objType;
289 pNewProof->object = obj;
293 case CHAINOBJ_HEADER_REF:
295 CBlockHeaderProof obj;
297 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
300 pNewHeaderRef->objectType = objType;
301 pNewHeaderRef->object = obj;
305 case CHAINOBJ_PRIORBLOCKS:
307 CPriorBlocksCommitment obj;
309 pPriors = new CChainObject<CPriorBlocksCommitment>();
312 pPriors->objectType = objType;
313 pPriors->object = obj;
317 case CHAINOBJ_RESERVETRANSFER:
319 CReserveTransfer obj;
321 pExport = new CChainObject<CReserveTransfer>();
324 pExport->objectType = objType;
325 pExport->object = obj;
329 case CHAINOBJ_CROSSCHAINPROOF:
331 CCrossChainProof obj;
333 pCrossChainProof = new CChainObject<CCrossChainProof>();
334 if (pCrossChainProof)
336 pCrossChainProof->objectType = objType;
337 pCrossChainProof->object = obj;
341 case CHAINOBJ_COMPOSITEOBJECT:
343 CCrossChainProof obj;
345 pCrossChainProof = new CChainObject<CCrossChainProof>();
346 if (pCrossChainProof)
348 pCrossChainProof->objectType = CHAINOBJ_COMPOSITEOBJECT;
349 pCrossChainProof->object = obj;
357 //printf("%s: storing object, code %u\n", __func__, objType);
358 chainObjects.push_back(pobj);
361 catch(const std::exception& e)
370 printf("%s: ERROR: opret is likely corrupt\n", __func__);
371 LogPrintf("%s: ERROR: opret is likely corrupt\n", __func__);
372 DeleteOpRetObjects(chainObjects);
377 //printf("entering CCrossChainProof serialize\n");
378 int32_t proofSize = chainObjects.size();
379 READWRITE(VARINT(proofSize));
380 for (auto &oneVal : chainObjects)
382 DehydrateChainObject(s, oneVal);
389 return (version >= VERSION_FIRST || version <= VERSION_LAST);
394 return chainObjects.size() == 0;
397 const std::vector<uint16_t> TypeVector() const
399 std::vector<uint16_t> retVal;
400 for (auto &pChainObj : chainObjects)
404 retVal.push_back(pChainObj->objectType);
410 const CCrossChainProof &operator<<(const CPartialTransactionProof &partialTxProof)
412 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPartialTransactionProof>(CHAINOBJ_TRANSACTION_PROOF, partialTxProof)));
416 const CCrossChainProof &operator<<(const CBlockHeaderAndProof &headerRefProof)
418 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderAndProof>(CHAINOBJ_HEADER_REF, headerRefProof)));
422 const CCrossChainProof &operator<<(const CBlockHeaderProof &headerProof)
424 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderProof>(CHAINOBJ_HEADER, headerProof)));
428 const CCrossChainProof &operator<<(const CPriorBlocksCommitment &priorBlocks)
430 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPriorBlocksCommitment>(CHAINOBJ_PRIORBLOCKS, priorBlocks)));
434 const CCrossChainProof &operator<<(const uint256 &proofRoot)
436 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<uint256>(CHAINOBJ_PROOF_ROOT, proofRoot)));
440 const CCrossChainProof &operator<<(const CReserveTransfer &reserveTransfer)
442 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CReserveTransfer>(CHAINOBJ_RESERVETRANSFER, reserveTransfer)));
446 const CCrossChainProof &operator<<(const CCrossChainProof &crossChainProof)
448 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCrossChainProof>(CHAINOBJ_CROSSCHAINPROOF, crossChainProof)));
453 // this must remain cast/data compatible with CCompositeChainObject
454 class CCompositeChainObject : public CCrossChainProof
457 CCompositeChainObject() : CCrossChainProof() {}
458 CCompositeChainObject(const std::vector<CBaseChainObject *> &proofs, int Version=VERSION_CURRENT) :
459 CCrossChainProof(proofs, Version) { }
461 ADD_SERIALIZE_METHODS;
463 template <typename Stream, typename Operation>
464 inline void SerializationOp(Stream& s, Operation ser_action) {
465 READWRITE(*(CCrossChainProof *)this);
468 const CCompositeChainObject &operator<<(const CCompositeChainObject &compositeChainObject)
470 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCompositeChainObject>(CHAINOBJ_COMPOSITEOBJECT, compositeChainObject)));
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);
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)
490 catch(const std::exception& e)
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;
511 case CHAINOBJ_HEADER:
512 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
515 s >> pNewHeader->object;
516 pNewHeader->objectType = objType;
519 case CHAINOBJ_TRANSACTION_PROOF:
520 pNewTx = new CChainObject<CPartialTransactionProof>();
524 pNewTx->objectType = objType;
527 case CHAINOBJ_PROOF_ROOT:
528 pNewProof = new CChainObject<uint256>();
531 s >> pNewProof->object;
532 pNewProof->objectType = objType;
535 case CHAINOBJ_HEADER_REF:
536 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
539 s >> pNewHeaderRef->object;
540 pNewHeaderRef->objectType = objType;
543 case CHAINOBJ_PRIORBLOCKS:
544 pPriors = new CChainObject<CPriorBlocksCommitment>();
547 s >> pPriors->object;
548 pPriors->objectType = objType;
551 case CHAINOBJ_RESERVETRANSFER:
552 pExport = new CChainObject<CReserveTransfer>();
555 s >> pExport->object;
556 pExport->objectType = objType;
559 case CHAINOBJ_CROSSCHAINPROOF:
560 pCrossChainProof = new CChainObject<CCrossChainProof>();
561 if (pCrossChainProof)
563 s >> pCrossChainProof->object;
564 pCrossChainProof->objectType = objType;
567 case CHAINOBJ_COMPOSITEOBJECT:
568 pCompositeChainObject = new CChainObject<CCompositeChainObject>();
569 if (pCompositeChainObject)
571 s >> pCompositeChainObject->object;
572 pCompositeChainObject->objectType = objType;
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)
584 switch(pobj->objectType)
586 case CHAINOBJ_HEADER:
588 s << *(CChainObject<CBlockHeaderAndProof> *)pobj;
592 case CHAINOBJ_TRANSACTION_PROOF:
594 s << *(CChainObject<CPartialTransactionProof> *)pobj;
598 case CHAINOBJ_PROOF_ROOT:
600 s << *(CChainObject<uint256> *)pobj;
604 case CHAINOBJ_HEADER_REF:
606 s << *(CChainObject<CBlockHeaderProof> *)pobj;
610 case CHAINOBJ_PRIORBLOCKS:
612 s << *(CChainObject<CPriorBlocksCommitment> *)pobj;
616 case CHAINOBJ_RESERVETRANSFER:
618 s << *(CChainObject<CReserveTransfer> *)pobj;
621 case CHAINOBJ_CROSSCHAINPROOF:
623 s << *(CChainObject<CCrossChainProof> *)pobj;
626 case CHAINOBJ_COMPOSITEOBJECT:
628 s << *(CChainObject<CCompositeChainObject> *)pobj;
635 int8_t ObjTypeCode(const CBlockHeaderAndProof &obj);
637 int8_t ObjTypeCode(const CPartialTransactionProof &obj);
639 int8_t ObjTypeCode(const CBlockHeaderProof &obj);
641 int8_t ObjTypeCode(const CPriorBlocksCommitment &obj);
643 int8_t ObjTypeCode(const CReserveTransfer &obj);
645 int8_t ObjTypeCode(const CCrossChainProof &obj);
647 int8_t ObjTypeCode(const CCompositeChainObject &obj);
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);
652 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
654 std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript);
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
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)
664 CPoSSelector(uint32_t bits, uint32_t TargetSpacing)
667 nTargetSpacing = TargetSpacing;
670 ADD_SERIALIZE_METHODS;
672 template <typename Stream, typename Operation>
673 inline void SerializationOp(Stream& s, Operation ser_action) {
675 READWRITE(nTargetSpacing);
678 CPoSSelector(const std::vector<unsigned char> &asVector)
680 FromVector(asVector, *this);
683 std::vector<unsigned char> AsVector()
685 return ::AsVector(*this);
694 class CInputDescriptor
697 CScript scriptPubKey;
700 CInputDescriptor() : nValue(0) {}
701 CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {}
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
713 CRPCChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass) :
714 chainDefinition(chainDef), rpcHost{host}, rpcPort(port), rpcUserPass(userPass) {}
716 ADD_SERIALIZE_METHODS;
718 template <typename Stream, typename Operation>
719 inline void SerializationOp(Stream& s, Operation ser_action) {
720 READWRITE(chainDefinition);
723 READWRITE(rpcUserPass);
726 std::vector<unsigned char> AsVector()
728 return ::AsVector(*this);
733 return chainDefinition.IsValid();
738 return chainDefinition.GetID();
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
747 static const uint32_t MAX_MERGE_CHAINS = 15;
748 CBlock block; // full block to submit upon winning header
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) {}
754 ADD_SERIALIZE_METHODS;
756 template <typename Stream, typename Operation>
757 inline void SerializationOp(Stream& s, Operation ser_action) {
758 READWRITE(chainDefinition);
761 READWRITE(rpcUserPass);
765 std::vector<unsigned char> AsVector()
767 return ::AsVector(*this);
771 class CConnectedChains
774 CPBaaSMergeMinedChainData *GetChainInfo(uint160 chainID);
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
781 std::string notaryChainVersion;
782 int32_t notaryChainHeight;
783 CRPCChainData notaryChain; // notary chain information
785 // if this is a fractional, liquid currency, reserve definitions go here
786 std::map<uint160, CCurrencyDefinition> reserveCurrencies;
788 CCurrencyDefinition thisChain;
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
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
799 bool lastSubmissionFailed; // if we submit a failed block, make another
800 std::map<arith_uint256, CBlockHeader> qualifiedHeaders;
802 CCriticalSection cs_mergemining;
803 CSemaphore sem_submitthread;
805 CConnectedChains() : readyToStart(0), sem_submitthread(0), earnedNotarizationHeight(0), dirty(0), lastSubmissionFailed(0) {}
807 arith_uint256 LowestTarget()
809 if (mergeMinedTargets.size())
811 return mergeMinedTargets.begin()->first;
815 return arith_uint256(0);
819 void SubmissionThread();
820 static void SubmissionThreadStub();
821 std::vector<std::pair<std::string, UniValue>> SubmitQualifiedBlocks();
823 void QueueNewBlockHeader(CBlockHeader &bh);
824 void QueueEarnedNotarization(CBlock &blk, int32_t txIndex, int32_t height);
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();
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);
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 ¤cyID);
840 CCurrencyDefinition UpdateCachedCurrency(const uint160 ¤cyID, uint32_t height);
842 bool NewImportNotarization(const CCurrencyDefinition &_curDef,
844 const CTransaction &lastImportTx,
845 uint32_t exportHeight,
846 const CTransaction &exportTx,
847 CMutableTransaction &mnewTx,
848 CCoinbaseCurrencyState &oldCurState,
849 CCoinbaseCurrencyState &newCurState);
851 bool GetLastImport(const uint160 &systemID,
852 CTransaction &lastImport,
853 CPartialTransactionProof &crossChainExport,
854 CCrossChainImport &ccImport,
855 CCrossChainExport &ccCrossExport);
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,
863 TransactionBuilder &exportBuilder,
864 int32_t &inputsConsumed,
865 const CPBaaSNotarization &lastNotarization,
866 CPBaaSNotarization &newNotarization,
867 const ChainTransferData *addInputTx=nullptr);
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);
878 CRPCChainData &NotaryChain()
883 uint32_t NotaryChainHeight();
885 CCurrencyDefinition &ThisChain()
890 int GetThisChainPort() const;
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 ¤cyState,
898 int32_t curDefHeight);
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 ¤cyID, int32_t height); // gets currency state
904 CCurrencyDefinition GetDestinationCurrency(const CReserveTransfer &rt) const;
906 bool CheckVerusPBaaSAvailable(UniValue &chainInfo, UniValue &chainDef);
907 bool CheckVerusPBaaSAvailable(); // may use RPC to call Verus
908 bool IsVerusPBaaSAvailable();
909 std::vector<CCurrencyDefinition> GetMergeMinedChains()
911 std::vector<CCurrencyDefinition> ret;
912 LOCK(cs_mergemining);
913 for (auto &chain : mergeMinedChains)
915 ret.push_back(chain.second.chainDefinition);
920 const std::map<uint160, CCurrencyDefinition> &ReserveCurrencies()
922 return reserveCurrencies;
925 bool LoadReserveCurrencies();
928 template <typename TOBJ>
929 CTxOut MakeCC1of1Vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector<CTxDestination> vDest, const TOBJ &obj)
931 assert(vDest.size() < 256);
934 CC *payoutCond = MakeCCcond1(evalcode, pk);
935 vout = CTxOut(nValue, CCPubKey(payoutCond));
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);
941 // add the object to the end of the script
942 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
946 template <typename TOBJ>
947 CTxOut MakeCC1ofAnyVout(uint8_t evalcode, CAmount nValue, std::vector<CTxDestination> vDest, const TOBJ &obj, const CPubKey &pk=CPubKey())
949 // if pk is valid, we will make sure that it is one of the signature options on this CC
954 cp = CCinit(&C, evalcode);
956 bool addPubKey = false;
957 for (i = 0; i < vDest.size(); i++)
959 CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), vDest[i]));
960 if ((oneKey.IsValid() && oneKey == pk) || CKeyID(GetDestinationID(vDest[i])) == pk.GetID())
962 // found, so don't add
966 // if not found, add the pubkey
967 if (i >= vDest.size())
969 vDest.push_back(CTxDestination(pk));
974 CC *payoutCond = MakeCCcondAny(evalcode, vDest);
975 vout = CTxOut(nValue, CCPubKey(payoutCond));
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);
981 for (auto dest : vDest)
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))
987 printf("Invalid destination %s\n", EncodeDestination(dest).c_str());
991 // add the object to the end of the script
992 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
996 template <typename TOBJ>
997 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, const TOBJ &obj)
1000 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1001 vout = CTxOut(nValue,CCPubKey(payoutCond));
1002 cc_free(payoutCond);
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);
1008 // add the object to the end of the script
1009 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1013 template <typename TOBJ>
1014 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector<CTxDestination> vDest, const TOBJ &obj)
1017 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1018 vout = CTxOut(nValue,CCPubKey(payoutCond));
1019 cc_free(payoutCond);
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);
1025 // add the object to the end of the script
1026 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1030 bool IsVerusActive();
1031 bool IsVerusMainnetActive();
1033 // used to export coins from one chain to another, if they are not native, they are represented on the other
1035 bool ValidateCrossChainExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1036 bool IsCrossChainExportInput(const CScript &scriptSig);
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);
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);
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);
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);
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);
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);
1063 bool ValidateChainDefinition(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1064 bool IsChainDefinitionInput(const CScript &scriptSig);
1066 bool ValidateCurrencyState(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1067 bool IsCurrencyStateInput(const CScript &scriptSig);
1069 bool GetCCParams(const CScript &scr, COptCCParams &ccParams);
1071 bool SetPeerNodes(const UniValue &nodes);
1072 bool SetThisChain(const UniValue &chainDefinition);
1073 const uint256 &CurrencyDefHash(UniValue &chainDefinition);
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);