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
61 CHAINOBJ_NOTARYSIGNATURE = 9 // notary signature
64 // the proof of an opret output, which is simply the types of objects and hashes of each
68 uint32_t orIndex; // index into the opret objects to begin with
69 std::vector<uint8_t> types;
70 std::vector<uint256> hashes;
72 COpRetProof() : orIndex(0), types(0), hashes(0) {}
73 COpRetProof(std::vector<uint8_t> &rTypes, std::vector<uint256> &rHashes, uint32_t opretIndex = 0) : types(rTypes), hashes(rHashes), orIndex(opretIndex) {}
75 void AddObject(CHAIN_OBJECT_TYPES typeCode, uint256 objHash)
77 types.push_back(typeCode);
78 hashes.push_back(objHash);
81 template <typename CHAINOBJTYPE>
82 void AddObject(CHAINOBJTYPE &co, uint256 objHash)
84 types.push_back(ObjTypeCode(co));
85 hashes.push_back(objHash);
88 ADD_SERIALIZE_METHODS;
90 template <typename Stream, typename Operation>
91 inline void SerializationOp(Stream& s, Operation ser_action)
102 uint256 hash; // block hash
103 CPBaaSPreHeader preHeader; // non-canonical pre-header data of source chain
105 CHeaderRef() : hash() {}
106 CHeaderRef(uint256 &rHash, CPBaaSPreHeader ph) : hash(rHash), preHeader(ph) {}
107 CHeaderRef(const CBlockHeader &bh) : hash(bh.GetHash()), preHeader(bh) {}
109 ADD_SERIALIZE_METHODS;
111 template <typename Stream, typename Operation>
112 inline void SerializationOp(Stream& s, Operation ser_action)
115 READWRITE(preHeader);
118 uint256 GetHash() { return hash; }
121 class CPriorBlocksCommitment
124 std::vector<uint256> priorBlocks; // prior block commitments, which are node hashes that include merkle root, block hash, and compact power
125 uint256 pastBlockType; // 1 = POS, 0 = POW indicators for past blocks, enabling selective, pseudorandom proofs of past blocks by type
127 CPriorBlocksCommitment() : priorBlocks() {}
128 CPriorBlocksCommitment(const std::vector<uint256> &priors, const uint256 &pastTypes) : priorBlocks(priors), pastBlockType(pastTypes) {}
130 ADD_SERIALIZE_METHODS;
132 template <typename Stream, typename Operation>
133 inline void SerializationOp(Stream& s, Operation ser_action)
135 READWRITE(priorBlocks);
136 READWRITE(pastBlockType);
140 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
142 class CBaseChainObject
145 uint16_t objectType; // type of object, such as blockheader, transaction, proof, tokentx, etc.
147 CBaseChainObject() : objectType(CHAINOBJ_INVALID) {}
148 CBaseChainObject(uint16_t objType) : objectType(objType) {}
150 ADD_SERIALIZE_METHODS;
152 template <typename Stream, typename Operation>
153 inline void SerializationOp(Stream& s, Operation ser_action)
155 READWRITE(objectType);
159 template <typename SERIALIZABLE>
160 class CChainObject : public CBaseChainObject
163 SERIALIZABLE object; // the actual object
165 CChainObject() : CBaseChainObject() {}
167 CChainObject(uint16_t objType, const SERIALIZABLE &rObject) : CBaseChainObject(objType), object(rObject) { }
169 ADD_SERIALIZE_METHODS;
171 template <typename Stream, typename Operation>
172 inline void SerializationOp(Stream& s, Operation ser_action)
174 READWRITE(*(CBaseChainObject *)this);
178 uint256 GetHash() const
180 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
187 // each notarization will have an opret object that contains various kind of proof of the notarization itself
188 // as well as recent POW and POS headers and entropy sources.
189 class CCrossChainProof
200 std::vector<CBaseChainObject *> chainObjects; // this owns the memory associated with chainObjects and deletes it on destructions
202 CCrossChainProof() : version(VERSION_CURRENT) {}
203 CCrossChainProof(const CCrossChainProof &oldObj)
205 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
209 CCrossChainProof(const std::vector<CBaseChainObject *> &objects, int Version=VERSION_CURRENT) : version(Version), chainObjects(objects) { }
213 DeleteOpRetObjects(chainObjects);
214 version = VERSION_INVALID;
217 const CCrossChainProof &operator=(const CCrossChainProof &operand)
219 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
221 DeleteOpRetObjects(chainObjects);
226 ADD_SERIALIZE_METHODS;
228 template <typename Stream, typename Operation>
229 inline void SerializationOp(Stream& s, Operation ser_action) {
231 if (ser_action.ForRead())
234 READWRITE(VARINT(proofSize));
237 for (int i = 0; i < proofSize && !error; i++)
244 CChainObject<CBlockHeaderAndProof> *pNewHeader;
245 CChainObject<CPartialTransactionProof> *pNewTx;
246 CChainObject<uint256> *pNewProof;
247 CChainObject<CBlockHeaderProof> *pNewHeaderRef;
248 CChainObject<CPriorBlocksCommitment> *pPriors;
249 CChainObject<CReserveTransfer> *pExport;
250 CChainObject<CCrossChainProof> *pCrossChainProof;
251 CChainObject<CNotaryEvidence> *pNotarySignature;
252 CBaseChainObject *pobj;
259 case CHAINOBJ_HEADER:
261 CBlockHeaderAndProof obj;
263 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
266 pNewHeader->objectType = objType;
267 pNewHeader->object = obj;
271 case CHAINOBJ_TRANSACTION_PROOF:
273 CPartialTransactionProof obj;
275 pNewTx = new CChainObject<CPartialTransactionProof>();
278 pNewTx->objectType = objType;
279 pNewTx->object = obj;
283 case CHAINOBJ_PROOF_ROOT:
287 pNewProof = new CChainObject<uint256>();
290 pNewProof->objectType = objType;
291 pNewProof->object = obj;
295 case CHAINOBJ_HEADER_REF:
297 CBlockHeaderProof obj;
299 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
302 pNewHeaderRef->objectType = objType;
303 pNewHeaderRef->object = obj;
307 case CHAINOBJ_PRIORBLOCKS:
309 CPriorBlocksCommitment obj;
311 pPriors = new CChainObject<CPriorBlocksCommitment>();
314 pPriors->objectType = objType;
315 pPriors->object = obj;
319 case CHAINOBJ_RESERVETRANSFER:
321 CReserveTransfer obj;
323 pExport = new CChainObject<CReserveTransfer>();
326 pExport->objectType = objType;
327 pExport->object = obj;
331 case CHAINOBJ_CROSSCHAINPROOF:
333 CCrossChainProof obj;
335 pCrossChainProof = new CChainObject<CCrossChainProof>();
336 if (pCrossChainProof)
338 pCrossChainProof->objectType = objType;
339 pCrossChainProof->object = obj;
343 case CHAINOBJ_COMPOSITEOBJECT:
345 CCrossChainProof obj;
347 pCrossChainProof = new CChainObject<CCrossChainProof>();
348 if (pCrossChainProof)
350 pCrossChainProof->objectType = CHAINOBJ_COMPOSITEOBJECT;
351 pCrossChainProof->object = obj;
355 case CHAINOBJ_NOTARYSIGNATURE:
359 pNotarySignature = new CChainObject<CNotaryEvidence>();
360 if (pNotarySignature)
362 pNotarySignature->objectType = CHAINOBJ_NOTARYSIGNATURE;
363 pNotarySignature->object = obj;
371 //printf("%s: storing object, code %u\n", __func__, objType);
372 chainObjects.push_back(pobj);
375 catch(const std::exception& e)
384 printf("%s: ERROR: opret is likely corrupt\n", __func__);
385 LogPrintf("%s: ERROR: opret is likely corrupt\n", __func__);
386 DeleteOpRetObjects(chainObjects);
391 //printf("entering CCrossChainProof serialize\n");
392 int32_t proofSize = chainObjects.size();
393 READWRITE(VARINT(proofSize));
394 for (auto &oneVal : chainObjects)
396 DehydrateChainObject(s, oneVal);
403 return (version >= VERSION_FIRST || version <= VERSION_LAST);
408 return chainObjects.size() == 0;
411 const std::vector<uint16_t> TypeVector() const
413 std::vector<uint16_t> retVal;
414 for (auto &pChainObj : chainObjects)
418 retVal.push_back(pChainObj->objectType);
424 const CCrossChainProof &operator<<(const CPartialTransactionProof &partialTxProof)
426 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPartialTransactionProof>(CHAINOBJ_TRANSACTION_PROOF, partialTxProof)));
430 const CCrossChainProof &operator<<(const CBlockHeaderAndProof &headerRefProof)
432 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderAndProof>(CHAINOBJ_HEADER_REF, headerRefProof)));
436 const CCrossChainProof &operator<<(const CBlockHeaderProof &headerProof)
438 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CBlockHeaderProof>(CHAINOBJ_HEADER, headerProof)));
442 const CCrossChainProof &operator<<(const CPriorBlocksCommitment &priorBlocks)
444 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CPriorBlocksCommitment>(CHAINOBJ_PRIORBLOCKS, priorBlocks)));
448 const CCrossChainProof &operator<<(const uint256 &proofRoot)
450 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<uint256>(CHAINOBJ_PROOF_ROOT, proofRoot)));
454 const CCrossChainProof &operator<<(const CReserveTransfer &reserveTransfer)
456 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CReserveTransfer>(CHAINOBJ_RESERVETRANSFER, reserveTransfer)));
460 const CCrossChainProof &operator<<(const CCrossChainProof &crossChainProof)
462 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCrossChainProof>(CHAINOBJ_CROSSCHAINPROOF, crossChainProof)));
467 // this must remain cast/data compatible with CCompositeChainObject
468 class CCompositeChainObject : public CCrossChainProof
471 CCompositeChainObject() : CCrossChainProof() {}
472 CCompositeChainObject(const std::vector<CBaseChainObject *> &proofs, int Version=VERSION_CURRENT) :
473 CCrossChainProof(proofs, Version) { }
475 ADD_SERIALIZE_METHODS;
477 template <typename Stream, typename Operation>
478 inline void SerializationOp(Stream& s, Operation ser_action) {
479 READWRITE(*(CCrossChainProof *)this);
482 const CCompositeChainObject &operator<<(const CCompositeChainObject &compositeChainObject)
484 chainObjects.push_back(static_cast<CBaseChainObject *>(new CChainObject<CCompositeChainObject>(CHAINOBJ_COMPOSITEOBJECT, compositeChainObject)));
489 // returns a pointer to a base chain object, which can be cast to the
490 // object type indicated in its objType member
491 uint256 GetChainObjectHash(const CBaseChainObject &bo);
493 // returns a pointer to a base chain object, which can be cast to the
494 // object type indicated in its objType member
495 template <typename OStream>
496 CBaseChainObject *RehydrateChainObject(OStream &s)
504 catch(const std::exception& e)
510 CChainObject<CBlockHeaderAndProof> *pNewHeader;
511 CChainObject<CPartialTransactionProof> *pNewTx;
512 CChainObject<uint256> *pNewProof;
513 CChainObject<CBlockHeaderProof> *pNewHeaderRef;
514 CChainObject<CPriorBlocksCommitment> *pPriors;
515 CChainObject<CReserveTransfer> *pExport;
516 CChainObject<CCrossChainProof> *pCrossChainProof;
517 CChainObject<CCompositeChainObject> *pCompositeChainObject;
518 CBaseChainObject *retPtr;
525 case CHAINOBJ_HEADER:
526 pNewHeader = new CChainObject<CBlockHeaderAndProof>();
529 s >> pNewHeader->object;
530 pNewHeader->objectType = objType;
533 case CHAINOBJ_TRANSACTION_PROOF:
534 pNewTx = new CChainObject<CPartialTransactionProof>();
538 pNewTx->objectType = objType;
541 case CHAINOBJ_PROOF_ROOT:
542 pNewProof = new CChainObject<uint256>();
545 s >> pNewProof->object;
546 pNewProof->objectType = objType;
549 case CHAINOBJ_HEADER_REF:
550 pNewHeaderRef = new CChainObject<CBlockHeaderProof>();
553 s >> pNewHeaderRef->object;
554 pNewHeaderRef->objectType = objType;
557 case CHAINOBJ_PRIORBLOCKS:
558 pPriors = new CChainObject<CPriorBlocksCommitment>();
561 s >> pPriors->object;
562 pPriors->objectType = objType;
565 case CHAINOBJ_RESERVETRANSFER:
566 pExport = new CChainObject<CReserveTransfer>();
569 s >> pExport->object;
570 pExport->objectType = objType;
573 case CHAINOBJ_CROSSCHAINPROOF:
574 pCrossChainProof = new CChainObject<CCrossChainProof>();
575 if (pCrossChainProof)
577 s >> pCrossChainProof->object;
578 pCrossChainProof->objectType = objType;
581 case CHAINOBJ_COMPOSITEOBJECT:
582 pCompositeChainObject = new CChainObject<CCompositeChainObject>();
583 if (pCompositeChainObject)
585 s >> pCompositeChainObject->object;
586 pCompositeChainObject->objectType = objType;
593 // returns a pointer to a base chain object, which can be cast to the
594 // object type indicated in its objType member
595 template <typename OStream>
596 bool DehydrateChainObject(OStream &s, const CBaseChainObject *pobj)
598 switch(pobj->objectType)
600 case CHAINOBJ_HEADER:
602 s << *(CChainObject<CBlockHeaderAndProof> *)pobj;
606 case CHAINOBJ_TRANSACTION_PROOF:
608 s << *(CChainObject<CPartialTransactionProof> *)pobj;
612 case CHAINOBJ_PROOF_ROOT:
614 s << *(CChainObject<uint256> *)pobj;
618 case CHAINOBJ_HEADER_REF:
620 s << *(CChainObject<CBlockHeaderProof> *)pobj;
624 case CHAINOBJ_PRIORBLOCKS:
626 s << *(CChainObject<CPriorBlocksCommitment> *)pobj;
630 case CHAINOBJ_RESERVETRANSFER:
632 s << *(CChainObject<CReserveTransfer> *)pobj;
635 case CHAINOBJ_CROSSCHAINPROOF:
637 s << *(CChainObject<CCrossChainProof> *)pobj;
640 case CHAINOBJ_COMPOSITEOBJECT:
642 s << *(CChainObject<CCompositeChainObject> *)pobj;
649 int8_t ObjTypeCode(const CBlockHeaderAndProof &obj);
651 int8_t ObjTypeCode(const CPartialTransactionProof &obj);
653 int8_t ObjTypeCode(const CBlockHeaderProof &obj);
655 int8_t ObjTypeCode(const CPriorBlocksCommitment &obj);
657 int8_t ObjTypeCode(const CReserveTransfer &obj);
659 int8_t ObjTypeCode(const CCrossChainProof &obj);
661 int8_t ObjTypeCode(const CCompositeChainObject &obj);
663 // this adds an opret to a mutable transaction that provides the necessary evidence of a signed, cheating stake transaction
664 CScript StoreOpRetArray(const std::vector<CBaseChainObject *> &objPtrs);
666 void DeleteOpRetObjects(std::vector<CBaseChainObject *> &ora);
668 std::vector<CBaseChainObject *> RetrieveOpRetArray(const CScript &opRetScript);
670 // This data structure is used on an output that provides proof of stake validation for other crypto conditions
671 // with rate limited spends based on a PoS contest
675 uint32_t nBits; // PoS difficulty target
676 uint32_t nTargetSpacing; // number of 1/1000ths of a block between selections (e.g. 1 == 1000 selections per block)
678 CPoSSelector(uint32_t bits, uint32_t TargetSpacing)
681 nTargetSpacing = TargetSpacing;
684 ADD_SERIALIZE_METHODS;
686 template <typename Stream, typename Operation>
687 inline void SerializationOp(Stream& s, Operation ser_action) {
689 READWRITE(nTargetSpacing);
692 CPoSSelector(const std::vector<unsigned char> &asVector)
694 FromVector(asVector, *this);
697 std::vector<unsigned char> AsVector()
699 return ::AsVector(*this);
708 class CInputDescriptor
711 CScript scriptPubKey;
714 CInputDescriptor() : nValue(0) {}
715 CInputDescriptor(CScript script, CAmount value, CTxIn input) : scriptPubKey(script), nValue(value), txIn(input) {}
716 bool operator<(const CInputDescriptor &op) const;
718 ADD_SERIALIZE_METHODS;
720 template <typename Stream, typename Operation>
721 inline void SerializationOp(Stream& s, Operation ser_action) {
722 READWRITE(scriptPubKey);
731 CCurrencyDefinition chainDefinition; // chain information for the specific chain
732 std::string rpcHost; // host of the chain's daemon
733 int32_t rpcPort; // port of the chain's daemon
734 std::string rpcUserPass; // user and password for this daemon
735 int64_t lastConnectTime; // set whenever we check valid
738 CRPCChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass) :
739 chainDefinition(chainDef), rpcHost{host}, rpcPort(port), rpcUserPass(userPass), lastConnectTime(0) {}
741 ADD_SERIALIZE_METHODS;
743 template <typename Stream, typename Operation>
744 inline void SerializationOp(Stream& s, Operation ser_action) {
745 READWRITE(chainDefinition);
748 READWRITE(rpcUserPass);
749 READWRITE(lastConnectTime);
752 std::vector<unsigned char> AsVector()
754 return ::AsVector(*this);
759 return chainDefinition.IsValid();
762 int64_t SetLastConnection(int64_t setTime)
764 return (lastConnectTime = setTime);
767 int64_t LastConnectionTime() const
769 return lastConnectTime;
772 uint160 GetID() const
774 return chainDefinition.GetID();
778 // Each merge mined chain gets an entry that includes information required to connect to a live daemon
779 // for that block, cross notarize, and validate notarizations.
780 class CPBaaSMergeMinedChainData : public CRPCChainData
783 static const uint32_t MAX_MERGE_CHAINS = 15;
784 CBlock block; // full block to submit upon winning header
786 CPBaaSMergeMinedChainData() {}
787 CPBaaSMergeMinedChainData(CCurrencyDefinition &chainDef, std::string host, int32_t port, std::string userPass, CBlock &blk) :
788 CRPCChainData(chainDef, host, port, userPass), block(blk) {}
790 ADD_SERIALIZE_METHODS;
792 template <typename Stream, typename Operation>
793 inline void SerializationOp(Stream& s, Operation ser_action) {
794 READWRITE(chainDefinition);
797 READWRITE(rpcUserPass);
801 std::vector<unsigned char> AsVector()
803 return ::AsVector(*this);
810 virtual bool ValidateDestination(const std::string &destination) const = 0;
811 virtual CTransferDestination ToTransferDestination(const std::string &destination) const = 0;
812 virtual std::set<uint160> FeeCurrencies() const = 0;
813 virtual const CCurrencyDefinition &GetConverter() const = 0;
816 class CEthGateway : public CGateway
818 virtual bool ValidateDestination(const std::string &destination) const;
819 virtual CTransferDestination ToTransferDestination(const std::string &destination) const;
820 virtual std::set<uint160> FeeCurrencies() const;
821 virtual const CCurrencyDefinition &GetConverter() const;
824 // This is the data for a PBaaS notarization transaction, either of a PBaaS chain into the Verus chain, or the Verus
825 // chain into a PBaaS chain.
827 // Part of a transaction with an opret that contains only the hashes and proofs, without the source
828 // headers, transactions, and objects. This type of notarizatoin is mined into a block by the miner, and is created on the PBaaS
831 // Notarizations include the following elements in order:
832 // Latest block header being notarized, or a header ref for a merge-mined header
833 // Proof of the header using the latest MMR root
834 // Cross notarization transaction less its op_ret
835 // Proof of the cross notarization using the latest MMR root
836 class CPBaaSNotarization
844 FINAL_CONFIRMATIONS = 9,
845 DEFAULT_NOTARIZATION_FEE = 10000, // price of a notarization fee in native or launch system currency
846 BLOCK_NOTARIZATION_MODULO = 10, // incentive to earn one valid notarization during this many blocks
847 MIN_BLOCKS_BEFORE_NOTARY_FINALIZED = 15, // 15 blocks must go by before notary signatures or confirming evidence can be provided
848 MAX_NODES = 2, // only provide 2 nodes per notarization
849 MIN_NOTARIZATION_OUTPUT = 0, // minimum amount for notarization output
851 //static const int FINAL_CONFIRMATIONS = 10;
852 //static const int MIN_BLOCKS_BETWEEN_NOTARIZATIONS = 8;
857 FLAG_DEFINITION_NOTARIZATION = 1, // initial notarization on definition of currency/system/chain
858 FLAG_PRE_LAUNCH = 2, // pre-launch notarization
859 FLAG_START_NOTARIZATION = 4, // first notarization after pre-launch
860 FLAG_LAUNCH_CONFIRMED = 8,
861 FLAG_REFUNDING = 0x10,
862 FLAG_ACCEPTED_MIRROR = 0x20, // if this is set, this notarization is a mirror of an earned notarization on another chain
863 FLAG_BLOCKONE_NOTARIZATION = 0x40, // block 1 notarizations are auto-finalized, the blockchain itself will be worthless if it is wrong
864 FLAG_SAME_CHAIN = 0x80, // set if all currency information is verifiable on this chain
865 FLAG_LAUNCH_COMPLETE = 0x100 // set if all currency information is verifiable on this chain
869 uint32_t flags; // notarization options
870 CTransferDestination proposer; // paid when this gets used on import (miner/staker, shares this with 1 notary for each validation)
872 uint160 currencyID; // the primary currency this notarization represents for the system, may be gateway or external chain
873 uint32_t notarizationHeight; // <= height on the current system as of this notarization (can't be confirmed earlier)
874 CCoinbaseCurrencyState currencyState; // state of the currency being notarized as of this notarization
876 CUTXORef prevNotarization; // reference of the prior notarization on this system with which we agree
877 uint256 hashPrevNotarization; // hash of the prior notarization on this system with which we agree, even one not accepted yet
878 uint32_t prevHeight; // height of previous notarization we agree with
880 std::map<uint160, CCoinbaseCurrencyState> currencyStates; // currency state of other currencies to be co-notarized for gateways
881 std::map<uint160, CProofRoot> proofRoots; // if cross-chain notarization, includes valid proof root of systemID at notarizationHeight + others verified
883 std::vector<CNodeData> nodes; // if cross chain notarization, network nodes
885 CPBaaSNotarization() : nVersion(PBAAS_VERSION_INVALID), flags(0), notarizationHeight(0), prevHeight(0) {}
887 CPBaaSNotarization(const uint160 ¤cyid,
888 const CCoinbaseCurrencyState CurrencyState,
890 const CUTXORef &prevnotarization,
892 const std::vector<CNodeData> &Nodes=std::vector<CNodeData>(),
893 const std::map<uint160, CCoinbaseCurrencyState> &CurrencyStates=std::map<uint160, CCoinbaseCurrencyState>(),
894 const CTransferDestination &Proposer=CTransferDestination(),
895 const std::map<uint160, CProofRoot> &ProofRoots=std::map<uint160, CProofRoot>(),
896 uint32_t version=VERSION_CURRENT,
897 uint32_t Flags=FLAGS_NONE) :
901 currencyID(currencyid),
902 notarizationHeight(height),
903 currencyState(CurrencyState),
904 prevNotarization(prevnotarization),
905 prevHeight(prevheight),
906 currencyStates(CurrencyStates),
907 proofRoots(ProofRoots),
912 CPBaaSNotarization(const std::vector<unsigned char> &asVector)
914 ::FromVector(asVector, *this);
917 CPBaaSNotarization(const CTransaction &tx, int32_t *pOutIdx=nullptr);
919 CPBaaSNotarization(const CScript &scriptPubKey);
921 CPBaaSNotarization(const UniValue &obj);
923 ADD_SERIALIZE_METHODS;
925 template <typename Stream, typename Operation>
926 inline void SerializationOp(Stream& s, Operation ser_action) {
927 READWRITE(VARINT(nVersion));
928 READWRITE(VARINT(flags));
930 READWRITE(currencyID);
931 READWRITE(currencyState);
932 READWRITE(notarizationHeight);
933 READWRITE(prevNotarization);
934 READWRITE(hashPrevNotarization);
935 READWRITE(prevHeight);
937 std::vector<std::pair<uint160, CCoinbaseCurrencyState>> vecCurrencyStates;
938 if (ser_action.ForRead())
940 READWRITE(vecCurrencyStates);
941 for (auto &oneRoot : vecCurrencyStates)
943 currencyStates.insert(oneRoot);
948 for (auto &oneRoot : currencyStates)
950 vecCurrencyStates.push_back(oneRoot);
952 READWRITE(vecCurrencyStates);
955 std::vector<std::pair<uint160, CProofRoot>> vecProofRoots;
957 if (ser_action.ForRead())
959 READWRITE(vecProofRoots);
960 for (auto &oneRoot : vecProofRoots)
962 proofRoots.insert(oneRoot);
967 for (auto &oneRoot : proofRoots)
969 vecProofRoots.push_back(oneRoot);
971 READWRITE(vecProofRoots);
977 std::vector<unsigned char> AsVector()
979 return ::AsVector(*this);
984 return nVersion >= VERSION_FIRST && nVersion <= VERSION_LAST && !currencyID.IsNull();
987 static std::string NotaryNotarizationKeyName()
989 return "vrsc::system.notarization.notarization";
992 static std::string LaunchNotarizationKeyName()
994 return "vrsc::system.currency.launch.notarization";
997 static std::string LaunchPrelaunchKeyName()
999 return "vrsc::system.currency.launch.prelaunch";
1002 static std::string LaunchRefundKeyName()
1004 return "vrsc::system.currency.launch.refund";
1007 static std::string LaunchConfirmKeyName()
1009 return "vrsc::system.currency.launch.confirm";
1012 static std::string LaunchCompleteKeyName()
1014 return "vrsc::system.currency.launch.complete";
1017 static uint160 NotaryNotarizationKey()
1019 static uint160 nameSpace;
1020 static uint160 notaryNotarizationKey = CVDXF::GetDataKey(NotaryNotarizationKeyName(), nameSpace);
1021 return notaryNotarizationKey;
1024 static uint160 LaunchNotarizationKey()
1026 static uint160 nameSpace;
1027 static uint160 signatureKey = CVDXF::GetDataKey(LaunchNotarizationKeyName(), nameSpace);
1028 return signatureKey;
1031 static uint160 LaunchPrelaunchKey()
1033 static uint160 nameSpace;
1034 static uint160 signatureKey = CVDXF::GetDataKey(LaunchPrelaunchKeyName(), nameSpace);
1035 return signatureKey;
1038 static uint160 LaunchRefundKey()
1040 static uint160 nameSpace;
1041 static uint160 signatureKey = CVDXF::GetDataKey(LaunchRefundKeyName(), nameSpace);
1042 return signatureKey;
1045 static uint160 LaunchConfirmKey()
1047 static uint160 nameSpace;
1048 static uint160 signatureKey = CVDXF::GetDataKey(LaunchConfirmKeyName(), nameSpace);
1049 return signatureKey;
1052 static uint160 LaunchCompleteKey()
1054 static uint160 nameSpace;
1055 static uint160 signatureKey = CVDXF::GetDataKey(LaunchCompleteKeyName(), nameSpace);
1056 return signatureKey;
1059 // if false, *this is unmodifed, otherwise, it is set to the last valid notarization in the requested range
1060 bool GetLastNotarization(const uint160 ¤cyID,
1061 int32_t startHeight=0,
1062 int32_t endHeight=0,
1063 uint256 *txIDOut=nullptr,
1064 CTransaction *txOut=nullptr);
1066 // if false, no matching, unspent notarization found
1067 bool GetLastUnspentNotarization(const uint160 ¤cyID,
1070 CTransaction *txOut=nullptr);
1072 bool NextNotarizationInfo(const CCurrencyDefinition &sourceSystem,
1073 const CCurrencyDefinition &destCurrency,
1074 uint32_t lastExportHeight,
1075 uint32_t currentHeight,
1076 std::vector<CReserveTransfer> &exportTransfers,
1077 uint256 &transferHash,
1078 CPBaaSNotarization &newNotarization,
1079 std::vector<CTxOut> &importOutputs,
1080 CCurrencyValueMap &importedCurrency,
1081 CCurrencyValueMap &gatewayDepositsUsed,
1082 CCurrencyValueMap &spentCurrencyOut) const;
1084 static bool CreateEarnedNotarization(const CRPCChainData &externalSystem,
1085 const CTransferDestination &Proposer,
1086 CValidationState &state,
1087 std::vector<CTxOut> &txOutputs,
1088 CPBaaSNotarization ¬arization);
1090 // accepts enough information to build a local accepted notarization transaction
1091 // miner fees are deferred until an import that uses this notarization, in which case
1092 // Proposer will get a share of the fees, if they are large enough. any miner,
1093 // who is mining the bridge can make such a notarization.
1094 static bool CreateAcceptedNotarization(const CCurrencyDefinition &externalSystem,
1095 const CPBaaSNotarization ¬arization,
1096 const CNotaryEvidence ¬aryEvidence,
1097 CValidationState &state,
1098 TransactionBuilder &txBuilder);
1100 static bool ConfirmOrRejectNotarizations(const CWallet *pWallet,
1101 const CRPCChainData &externalSystem,
1102 CValidationState &state,
1103 TransactionBuilder &txBuilder,
1106 static std::vector<uint256> SubmitFinalizedNotarizations(const CRPCChainData &externalSystem,
1107 CValidationState &state);
1109 bool CheckProof(const uint160 &systemID, const CMMRProof &transactionBlockProof, uint256 checkHash)
1111 auto proofRootIt = proofRoots.find(systemID);
1112 if (proofRootIt == proofRoots.end())
1116 return transactionBlockProof.CheckProof(checkHash) == proofRootIt->second.stateRoot;
1119 CProofRoot GetProofRoot(const uint160 &systemID) const
1121 auto proofRootIt = proofRoots.find(systemID);
1122 if (proofRootIt == proofRoots.end())
1124 return CProofRoot();
1126 return proofRootIt->second;
1129 void SetLaunchComplete(bool setTrue=true)
1133 flags |= FLAG_LAUNCH_COMPLETE;
1137 flags &= ~FLAG_LAUNCH_COMPLETE;
1141 bool IsLaunchComplete() const
1143 return flags & FLAG_LAUNCH_COMPLETE;
1146 void SetSameChain(bool setTrue=true)
1150 flags |= FLAG_SAME_CHAIN;
1154 flags &= ~FLAG_SAME_CHAIN;
1158 bool IsSameChain() const
1160 return flags & FLAG_SAME_CHAIN;
1163 bool IsMirror() const
1165 return flags & FLAG_ACCEPTED_MIRROR;
1168 // both sets the mirror flag and also transforms the notarization
1169 // between mirror states. returns false if could not change state to requested.
1170 bool SetMirror(bool setTrue=true);
1172 bool IsDefinitionNotarization() const
1174 return flags & FLAG_DEFINITION_NOTARIZATION;
1177 void SetDefinitionNotarization(bool setTrue=true)
1181 flags |= FLAG_DEFINITION_NOTARIZATION;
1185 flags &= ~FLAG_DEFINITION_NOTARIZATION;
1189 bool IsBlockOneNotarization() const
1191 return flags & FLAG_BLOCKONE_NOTARIZATION;
1194 void SetBlockOneNotarization(bool setTrue=true)
1198 flags |= FLAG_BLOCKONE_NOTARIZATION;
1202 flags &= ~FLAG_BLOCKONE_NOTARIZATION;
1206 bool IsPreLaunch() const
1208 return flags & FLAG_PRE_LAUNCH;
1211 void SetPreLaunch(bool setTrue=true)
1215 flags |= FLAG_PRE_LAUNCH;
1219 flags &= ~FLAG_PRE_LAUNCH;
1223 bool IsLaunchCleared() const
1225 return flags & FLAG_START_NOTARIZATION;
1228 void SetLaunchCleared(bool setTrue=true)
1232 flags |= FLAG_START_NOTARIZATION;
1236 flags &= ~FLAG_START_NOTARIZATION;
1240 bool IsLaunchConfirmed() const
1242 return flags & FLAG_LAUNCH_CONFIRMED;
1245 void SetLaunchConfirmed(bool setTrue=true)
1249 flags |= FLAG_LAUNCH_CONFIRMED;
1253 flags &= ~FLAG_LAUNCH_CONFIRMED;
1257 bool IsRefunding() const
1259 return flags & FLAG_REFUNDING;
1262 void SetRefunding(bool setTrue=true)
1266 flags |= FLAG_REFUNDING;
1270 flags &= ~FLAG_REFUNDING;
1274 UniValue ToUniValue() const;
1277 class CNotarySystemInfo
1282 VERSION_INVALID = 0,
1283 VERSION_CURRENT = 1,
1288 enum ENotarySystemTypes
1296 uint32_t notarySystemVersion;
1297 uint32_t notarySystemType;
1298 uint32_t height; // height of last notarization
1299 CRPCChainData notaryChain; // notary chain information and connectivity for PBaaS protocol
1300 CCurrencyDefinition notaryConverter; // fractional currency to convert between this native currency and the notary currency
1301 CPBaaSNotarization lastConfirmedNotarization;
1303 CNotarySystemInfo() : notarySystemVersion(VERSION_INVALID), height(0) {}
1305 CNotarySystemInfo(uint32_t Height,
1306 const CRPCChainData &NotaryChain,
1307 const CCurrencyDefinition &NotaryConverter,
1308 const CPBaaSNotarization &lastNotarization,
1309 uint32_t NotarySystemType=TYPE_PBAAS,
1310 uint32_t notaryVersion=VERSION_CURRENT) :
1311 notarySystemVersion(notaryVersion),
1312 notarySystemType(NotarySystemType),
1314 notaryChain(NotaryChain),
1315 notaryConverter(NotaryConverter),
1316 lastConfirmedNotarization(lastNotarization)
1320 class CConnectedChains
1323 CPBaaSMergeMinedChainData *GetChainInfo(uint160 chainID);
1326 std::map<uint160, CPBaaSMergeMinedChainData> mergeMinedChains;
1327 std::multimap<arith_uint256, CPBaaSMergeMinedChainData *> mergeMinedTargets;
1329 std::map<uint160, std::pair<CCurrencyDefinition, const CGateway *>> gateways; // gateway currencies, which bridge to other blockchains/systems
1331 // incoming export transactions from one currency & system and a UTXORef to a valid notarization each depends upon
1332 // indexed by the target, destination currency
1333 std::map<uint160, std::pair<uint32_t, std::pair<CUTXORef, CPartialTransactionProof>>> incomingBridgeTransfers;
1335 // currency definition cache, needs LRU
1336 std::map<uint160, CCurrencyDefinition> currencyDefCache; // protected by cs_main, which is used for lookup
1338 // make earned notarizations on one or more notary chains
1339 // On Verus, this can be set to ETH and Ethereum chain data will be pushed to us through Alan (Bridgekeeper) and the RPC API
1340 std::map<uint160, CNotarySystemInfo> notarySystems;
1342 CCurrencyDefinition thisChain;
1344 std::vector<CNodeData> defaultPeerNodes; // updated by notarizations
1345 std::vector<CTxOut> latestMiningOutputs; // accessible from all merge miners - can be invalid
1346 int64_t lastAggregation = 0; // adjusted time of last aggregation
1348 int32_t earnedNotarizationHeight; // zero or the height of one or more potential submissions
1349 CBlock earnedNotarizationBlock;
1350 int32_t earnedNotarizationIndex; // index of earned notarization in block
1353 bool lastSubmissionFailed; // if we submit a failed block, make another
1354 std::map<arith_uint256, CBlockHeader> qualifiedHeaders;
1356 CCriticalSection cs_mergemining;
1357 CSemaphore sem_submitthread;
1359 CConnectedChains() : readyToStart(0), sem_submitthread(0), earnedNotarizationHeight(0), dirty(0), lastSubmissionFailed(0) {}
1361 arith_uint256 LowestTarget()
1363 if (mergeMinedTargets.size())
1365 return mergeMinedTargets.begin()->first;
1369 return arith_uint256(0);
1373 void SubmissionThread();
1374 static void SubmissionThreadStub();
1375 std::vector<std::pair<std::string, UniValue>> SubmitQualifiedBlocks();
1377 void QueueNewBlockHeader(CBlockHeader &bh);
1378 void QueueEarnedNotarization(CBlock &blk, int32_t txIndex, int32_t height);
1379 void CheckImports();
1380 void SignAndCommitImportTransactions(const CTransaction &lastImportTx, const std::vector<CTransaction> &transactions);
1381 // send new imports from this chain to the specified chain, which generally will be the notary chain
1382 void ProcessLocalImports();
1384 bool AddMergedBlock(CPBaaSMergeMinedChainData &blkData);
1385 bool RemoveMergedBlock(uint160 chainID);
1386 bool GetChainInfo(uint160 chainID, CRPCChainData &rpcChainData);
1387 void PruneOldChains(uint32_t pruneBefore);
1388 uint32_t CombineBlocks(CBlockHeader &bh);
1390 // returns false if destinations are empty or first is not either pubkey or pubkeyhash
1391 bool SetLatestMiningOutputs(const std::vector<CTxOut> &minerOutputs);
1392 void AggregateChainTransfers(const CTxDestination &feeOutput, uint32_t nHeight);
1393 CCurrencyDefinition GetCachedCurrency(const uint160 ¤cyID);
1394 CCurrencyDefinition UpdateCachedCurrency(const uint160 ¤cyID, uint32_t height);
1396 bool GetLastImport(const uint160 ¤cyID,
1397 CTransaction &lastImport,
1398 int32_t &outputNum);
1400 bool GetLastSourceImport(const uint160 ¤cyID,
1401 CTransaction &lastImport,
1402 int32_t &outputNum);
1404 bool GetUnspentSystemExports(const CCoinsViewCache &view,
1405 const uint160 systemID,
1406 std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1408 bool GetUnspentCurrencyExports(const CCoinsViewCache &view,
1409 const uint160 currencyID,
1410 std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1412 // get the exports to a specific system on this chain from a specific height up to a specific height
1413 bool GetSystemExports(const uint160 &systemID, // transactions exported to system
1414 std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> &exports,
1415 uint32_t fromHeight,
1417 bool withProofs=false);
1419 // gets both the launch notarization and its partial transaction proof if launching to a new system
1420 bool GetLaunchNotarization(const CCurrencyDefinition &curDef,
1421 std::pair<CInputDescriptor, CPartialTransactionProof> ¬arizationTx,
1422 CPBaaSNotarization &launchNotarization,
1423 CPBaaSNotarization ¬aryNotarization);
1425 // get the exports to a specific system on this chain from a specific height up to a specific height
1426 bool GetCurrencyExports(const uint160 ¤cyID, // transactions exported to system
1427 std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> &exports,
1428 uint32_t fromHeight,
1431 bool GetPendingSystemExports(const uint160 systemID,
1432 uint32_t fromHeight,
1433 multimap<uint160, pair<int, CInputDescriptor>> &exportOutputs);
1435 bool GetPendingCurrencyExports(const uint160 currencyID,
1436 uint32_t fromHeight,
1437 std::vector<pair<int, CInputDescriptor>> &exportOutputs);
1439 // given exports on this chain, provide the proofs of those export outputs
1440 bool GetExportProofs(uint32_t height,
1441 std::vector<std::pair<std::pair<CInputDescriptor,CPartialTransactionProof>,std::vector<CReserveTransfer>>> &exports);
1443 static bool GetReserveDeposits(const uint160 ¤cyID, const CCoinsViewCache &view, std::vector<CInputDescriptor> &reserveDeposits);
1445 static bool CurrencyExportStatus(const CCurrencyValueMap &totalExports,
1446 const uint160 &sourceSystemID,
1447 const uint160 &destSystemID,
1448 CCurrencyValueMap &newReserveDeposits,
1449 CCurrencyValueMap &exportBurn);
1451 static bool CurrencyImportStatus(const CCurrencyValueMap &totalExports,
1452 const uint160 &sourceSystemID,
1453 const uint160 &destSystemID,
1454 CCurrencyValueMap &newReserveDeposits,
1455 CCurrencyValueMap &exportBurn);
1457 bool CreateNextExport(const CCurrencyDefinition &_curDef,
1458 const std::vector<ChainTransferData> &txInputs,
1459 const std::vector<CInputDescriptor> &priorExports,
1460 const CTxDestination &feeOutput,
1461 uint32_t sinceHeight,
1463 int32_t inputStartNum,
1464 int32_t &inputsConsumed,
1465 std::vector<CTxOut> &exportOutputs,
1466 std::vector<CReserveTransfer> &exportTransfers,
1467 const CPBaaSNotarization &lastNotarization,
1468 const CUTXORef &lastNotarizationUTXO,
1469 CPBaaSNotarization &newNotarization,
1470 int &newNotarizationOutNum,
1471 bool onlyIfRequired=true,
1472 const ChainTransferData *addInputTx=nullptr);
1474 // create a set of imports on the current chain for a set of exports
1475 bool CreateLatestImports(const CCurrencyDefinition &sourceSystemDef, // transactions imported from system
1476 const CUTXORef &confirmedSourceNotarization,
1477 const std::vector<std::pair<std::pair<CInputDescriptor,CPartialTransactionProof>,std::vector<CReserveTransfer>>> &exports,
1478 std::map<uint160, std::vector<std::pair<int, CTransaction>>> &newImports);
1480 // returns the first notary system, if there is more than one
1481 const CRPCChainData &FirstNotaryChain() const
1483 if (notarySystems.size())
1485 return notarySystems.begin()->second.notaryChain;
1487 static CRPCChainData invalidChain;
1488 return invalidChain;
1491 // returns the map of notary systems
1492 const std::map<uint160, CNotarySystemInfo> &NotarySystems() const
1494 return notarySystems;
1497 uint32_t NotaryChainHeight();
1499 CCurrencyDefinition &ThisChain()
1504 const std::map<uint160, std::pair<CCurrencyDefinition, const CGateway *>> &Gateways() const
1509 std::pair<CCurrencyDefinition, const CGateway *> GetGateway(const uint160 &gatewayID) const
1511 auto it = gateways.find(gatewayID);
1512 if (it != gateways.end())
1516 return std::make_pair(CCurrencyDefinition(), nullptr);
1519 int GetThisChainPort() const;
1521 // start with existing currency state and currency definitino and add
1522 // all pre-launch activity to bring them both up to date
1523 CCoinbaseCurrencyState AddPrelaunchConversions(CCurrencyDefinition &curDef,
1524 const CCoinbaseCurrencyState ¤cyState,
1527 int32_t curDefHeight);
1529 CCoinbaseCurrencyState GetCurrencyState(int32_t height); // gets this chain's native currency state by block height
1530 CCoinbaseCurrencyState GetCurrencyState(CCurrencyDefinition &curDef, int32_t height, int32_t curDefHeight=0); // gets currency state
1531 CCoinbaseCurrencyState GetCurrencyState(const uint160 ¤cyID, int32_t height); // gets currency state
1533 CCurrencyDefinition GetDestinationCurrency(const CReserveTransfer &rt) const;
1535 bool CheckVerusPBaaSAvailable(UniValue &chainInfo, UniValue &chainDef);
1536 bool CheckVerusPBaaSAvailable(); // may use RPC to call Verus
1537 bool IsVerusPBaaSAvailable();
1538 bool IsNotaryAvailable(bool callToCheck=false);
1539 std::vector<CCurrencyDefinition> GetMergeMinedChains()
1541 std::vector<CCurrencyDefinition> ret;
1542 LOCK(cs_mergemining);
1543 for (auto &chain : mergeMinedChains)
1545 ret.push_back(chain.second.chainDefinition);
1550 bool GetNotaryCurrencies(const CRPCChainData notaryChain,
1551 const std::set<uint160> ¤cyIDs,
1552 std::map<uint160, std::pair<CCurrencyDefinition,CPBaaSNotarization>> ¤cyDefs);
1553 bool GetNotaryIDs(const CRPCChainData notaryChain, const std::set<uint160> &idIDs, std::map<uint160,CIdentity> &identities);
1556 template <typename TOBJ>
1557 CTxOut MakeCC1of1Vout(uint8_t evalcode, CAmount nValue, CPubKey pk, std::vector<CTxDestination> vDest, const TOBJ &obj)
1559 assert(vDest.size() < 256);
1562 CC *payoutCond = MakeCCcond1(evalcode, pk);
1563 vout = CTxOut(nValue, CCPubKey(payoutCond));
1564 cc_free(payoutCond);
1566 std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1567 COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
1569 // add the object to the end of the script
1570 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1574 template <typename TOBJ>
1575 CTxOut MakeCC1ofAnyVout(uint8_t evalcode, CAmount nValue, std::vector<CTxDestination> vDest, const TOBJ &obj, const CPubKey &pk=CPubKey())
1577 // if pk is valid, we will make sure that it is one of the signature options on this CC
1581 CCcontract_info *cp;
1582 cp = CCinit(&C, evalcode);
1584 bool addPubKey = false;
1585 for (i = 0; i < vDest.size(); i++)
1587 CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), vDest[i]));
1588 if ((oneKey.IsValid() && oneKey == pk) || CKeyID(GetDestinationID(vDest[i])) == pk.GetID())
1590 // found, so don't add
1594 // if not found, add the pubkey
1595 if (i >= vDest.size())
1597 vDest.push_back(CTxDestination(pk));
1602 CC *payoutCond = MakeCCcondAny(evalcode, vDest);
1603 vout = CTxOut(nValue, CCPubKey(payoutCond));
1604 cc_free(payoutCond);
1606 std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1607 COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 0, (uint8_t)(vDest.size()), vDest, vvch);
1609 for (auto dest : vDest)
1611 CPubKey oneKey(boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), dest));
1612 std::vector<unsigned char> bytes = GetDestinationBytes(dest);
1613 if ((!oneKey.IsValid() && bytes.size() != 20) || (bytes.size() != 33 && bytes.size() != 20))
1615 printf("Invalid destination %s\n", EncodeDestination(dest).c_str());
1619 // add the object to the end of the script
1620 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1624 template <typename TOBJ>
1625 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, const TOBJ &obj)
1628 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1629 vout = CTxOut(nValue,CCPubKey(payoutCond));
1630 cc_free(payoutCond);
1632 std::vector<CPubKey> vpk({pk1, pk2});
1633 std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1634 COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, 2, vpk, vvch);
1636 // add the object to the end of the script
1637 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1641 template <typename TOBJ>
1642 CTxOut MakeCC1of2Vout(uint8_t evalcode, CAmount nValue, CPubKey pk1, CPubKey pk2, std::vector<CTxDestination> vDest, const TOBJ &obj)
1645 CC *payoutCond = MakeCCcond1of2(evalcode, pk1, pk2);
1646 vout = CTxOut(nValue,CCPubKey(payoutCond));
1647 cc_free(payoutCond);
1649 std::vector<CPubKey> vpk({pk1, pk2});
1650 std::vector<std::vector<unsigned char>> vvch({::AsVector((const TOBJ)obj)});
1651 COptCCParams vParams = COptCCParams(COptCCParams::VERSION_V2, evalcode, 1, (uint8_t)(vDest.size()), vDest, vvch);
1653 // add the object to the end of the script
1654 vout.scriptPubKey << vParams.AsVector() << OP_DROP;
1658 bool IsVerusActive();
1659 bool IsVerusMainnetActive();
1661 // used to export coins from one chain to another, if they are not native, they are represented on the other
1663 bool ValidateCrossChainExport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1664 bool IsCrossChainExportInput(const CScript &scriptSig);
1666 // used to validate import of coins from one chain to another. if they are not native and are supported,
1667 // they are represented o the chain as tokens
1668 bool ValidateCrossChainImport(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1669 bool IsCrossChainImportInput(const CScript &scriptSig);
1671 bool ValidateNotaryEvidence(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1672 bool IsNotaryEvidenceInput(const CScript &scriptSig);
1674 // used as a proxy token output for a reserve currency on its fractional reserve chain
1675 bool ValidateReserveOutput(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1676 bool IsReserveOutputInput(const CScript &scriptSig);
1678 // used to transfer a reserve currency between chains
1679 bool ValidateReserveTransfer(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1680 bool IsReserveTransferInput(const CScript &scriptSig);
1682 // used as exchange tokens between reserves and fractional reserves
1683 bool ValidateReserveExchange(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1684 bool IsReserveExchangeInput(const CScript &scriptSig);
1686 // used to deposit reserves into a reserve UTXO set
1687 bool ValidateReserveDeposit(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1688 bool IsReserveDepositInput(const CScript &scriptSig);
1690 bool ValidateChainDefinition(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1691 bool IsChainDefinitionInput(const CScript &scriptSig);
1693 bool ValidateCurrencyState(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn, bool fulfilled);
1694 bool IsCurrencyStateInput(const CScript &scriptSig);
1696 bool GetCCParams(const CScript &scr, COptCCParams &ccParams);
1698 bool SetPeerNodes(const UniValue &nodes);
1699 bool SetThisChain(const UniValue &chainDefinition);
1700 const uint256 &CurrencyDefHash(UniValue &chainDefinition);
1702 extern CConnectedChains ConnectedChains;
1703 extern uint160 ASSETCHAINS_CHAINID;
1704 CCoinbaseCurrencyState GetInitialCurrencyState(const CCurrencyDefinition &chainDef);