/****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ #include "cc/eval.h" #include "cc/utils.h" #include "importcoin.h" #include "crosschain.h" #include "primitives/transaction.h" #include "cc/CCinclude.h" /* * CC Eval method for import coin. * * This method should control every parameter of the ImportCoin transaction, since it has no signature * to protect it from malleability. ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; int32_t GetSelfimportProof(std::string source,CMutableTransaction &mtx,CScript &scriptPubKey,TxProof &proof,uint64_t burnAmount,std::vector rawtx,uint256 txid,std::vector rawproof) // find burnTx with hash from "other" daemon { MerkleBranch newBranch; CMutableTransaction tmpmtx; CTransaction tx,vintx; uint256 blockHash; char destaddr[64],pkaddr[64]; tmpmtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),komodo_nextheight()); if ( source == "BEAM" ) { if ( ASSETCHAINS_BEAMPORT == 0 ) return(-1); // confirm via ASSETCHAINS_BEAMPORT that burnTx/hash is a valid BEAM burn // return(0); } else if ( source == "CODA" ) { if ( ASSETCHAINS_CODAPORT == 0 ) return(-1); // confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn // return(0); } else { if ( !E_UNMARSHAL(rawtx, ss >> tx) ) return(-1); scriptPubKey = tx.vout[0].scriptPubKey; mtx = tx; mtx.fOverwintered = tmpmtx.fOverwintered; mtx.nExpiryHeight = tmpmtx.nExpiryHeight; mtx.nVersionGroupId = tmpmtx.nVersionGroupId; mtx.nVersion = tmpmtx.nVersion; mtx.vout.clear(); mtx.vout.resize(1); mtx.vout[0].nValue = burnAmount; mtx.vout[0].scriptPubKey = scriptPubKey; if ( tx.GetHash() != txid ) return(-1); if ( source == "PUBKEY" ) { // make sure vin0 is signed by ASSETCHAINS_OVERRIDE_PUBKEY33 if ( myGetTransaction(tx.vin[0].prevout.hash,vintx,blockHash) == 0 ) return(-1); if ( tx.vin[0].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr,vintx.vout[tx.vin[0].prevout.n].scriptPubKey) != 0 ) { pubkey2addr(pkaddr,ASSETCHAINS_OVERRIDE_PUBKEY33); if ( strcmp(pkaddr,destaddr) == 0 ) { proof = std::make_pair(txid,newBranch); return(0); } fprintf(stderr,"mismatched vin0[%d] -> %s vs %s\n",tx.vin[0].prevout.n,destaddr,pkaddr); } } else if ( source == ASSETCHAINS_SELFIMPORT ) { // source is external coin is the assetchains symbol in the burnTx OP_RETURN // burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent } } return(-1); } // use proof from the above functions to validate the import int32_t CheckBEAMimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) { // check with dual-BEAM daemon via ASSETCHAINS_BEAMPORT for validity of burnTx return(-1); } int32_t CheckCODAimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) { // check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx return(-1); } int32_t CheckGATEWAYimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) { // ASSETCHAINS_SELFIMPORT is coin // check for valid burn from external coin blockchain and if valid return(0); return(-1); } int32_t CheckPUBKEYimport(TxProof proof,std::vector rawproof,CTransaction burnTx,std::vector payouts) { // if burnTx has ASSETCHAINS_PUBKEY vin, it is valid return(0); fprintf(stderr,"proof txid.%s\n",proof.first.GetHex().c_str()); return(0); return(-1); } bool Eval::ImportCoin(const std::vector params,const CTransaction &importTx,unsigned int nIn) { TxProof proof; CTransaction burnTx; std::vector payouts; uint64_t txfee = 10000; uint32_t targetCcid; std::string targetSymbol; uint256 payoutsHash; std::vector rawproof; if ( importTx.vout.size() < 2 ) return Invalid("too-few-vouts"); // params if (!UnmarshalImportTx(importTx, proof, burnTx, payouts)) return Invalid("invalid-params"); // Control all aspects of this transaction // It should not be at all malleable if (MakeImportCoinTransaction(proof, burnTx, payouts).GetHash() != importTx.GetHash()) return Invalid("non-canonical"); // burn params if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash,rawproof)) return Invalid("invalid-burn-tx"); // check burn amount { uint64_t burnAmount = burnTx.vout.back().nValue; if (burnAmount == 0) return Invalid("invalid-burn-amount"); uint64_t totalOut = 0; for (int i=0; i burnAmount || totalOut < burnAmount-txfee ) return Invalid("payout-too-high-or-too-low"); } // Check burntx shows correct outputs hash if (payoutsHash != SerializeHash(payouts)) return Invalid("wrong-payouts"); if (targetCcid < KOMODO_FIRSTFUNGIBLEID) return Invalid("chain-not-fungible"); // Check proof confirms existance of burnTx if ( targetCcid != 0xffffffff ) { if ( targetCcid != GetAssetchainsCC() || targetSymbol != GetAssetchainsSymbol() ) return Invalid("importcoin-wrong-chain"); uint256 target = proof.second.Exec(burnTx.GetHash()); if (!CheckMoMoM(proof.first, target)) return Invalid("momom-check-fail"); } else { if ( targetSymbol == "BEAM" ) { if ( ASSETCHAINS_BEAMPORT == 0 ) return Invalid("BEAM-import-without-port"); else if ( CheckBEAMimport(proof,rawproof,burnTx,payouts) < 0 ) return Invalid("BEAM-import-failure"); } else if ( targetSymbol == "CODA" ) { if ( ASSETCHAINS_CODAPORT == 0 ) return Invalid("CODA-import-without-port"); else if ( CheckCODAimport(proof,rawproof,burnTx,payouts) < 0 ) return Invalid("CODA-import-failure"); } else if ( targetSymbol == "PUBKEY" ) { if ( ASSETCHAINS_SELFIMPORT != "PUBKEY" ) return Invalid("PUBKEY-import-when-notPUBKEY"); else if ( CheckPUBKEYimport(proof,rawproof,burnTx,payouts) < 0 ) return Invalid("PUBKEY-import-failure"); } else { if ( targetSymbol != ASSETCHAINS_SELFIMPORT ) return Invalid("invalid-gateway-import-coin"); else if ( CheckGATEWAYimport(proof,rawproof,burnTx,payouts) < 0 ) return Invalid("GATEWAY-import-failure"); } } return Valid(); }