From 2995bbcc794c99f39703c1ed220410065c03a878 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 31 Dec 2018 23:28:35 -1100 Subject: [PATCH] rework selfimport --- src/cc/import.cpp | 76 +++++++++++++++++++++++++++--------------- src/komodo_utils.h | 6 ---- src/rpc/crosschain.cpp | 39 +++++++--------------- 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 7902a74b3..d8006cca2 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -31,9 +31,12 @@ extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; +int32_t komodo_nextheight(); -int32_t GetSelfimportProof(TxProof &proof,CTransaction burnTx,uint256 hash) // find burnTx with hash from "other" daemon +int32_t GetSelfimportProof(CMutableTransaction &mtx,CScript &scriptPubKey,TxProof &proof,uint64_t burnAmount,std::vector rawtx,uint256 hash,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 ( ASSETCHAINS_SELFIMPORT == "BEAM" ) { // confirm via ASSETCHAINS_BEAMPORT that burnTx/hash is a valid BEAM burn @@ -44,15 +47,45 @@ int32_t GetSelfimportProof(TxProof &proof,CTransaction burnTx,uint256 hash) // f // confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn return(-1); } - else if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) + else { - // make sure vin0 is signed by ASSETCHAINS_OVERRIDE_PUBKEY33 - return(0); - } - else if ( ASSETCHAINS_SELFIMPORT == "GATEWAY" ) - { - // external coin is the assetchains symbol in the burnTx OP_RETURN + if ( !E_UNMARSHAL(rawtx, ss >> tx) ) return(-1); + scriptPubKey = tx.vout[0].scriptPubKey; + mtx = tx; + mtx.fOverwintered = tmptx.fOverwintered; + mtx.nExpiryHeight = tmptx.nExpiryHeight; + mtx.nVersionGroupId = tmptx.nVersionGroupId; + mtx.nVersion = tmptx.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 ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) + { + // make sure vin0 is signed by ASSETCHAINS_OVERRIDE_PUBKEY33 + if ( GetTransaction(tx.vin[0].prevout,vintx,blockHash,false) == 0 ) + return(-1); + if ( tx.vin[0].prevn < vintx.vout.size() && Getscriptaddress(destaddr,vintx.vout[tx.vin[0].prevn].scriptPubKey) != 0 ) + { + pubkey2addr(pkaddr,ASSETCHAINS_OVERRIDE_PUBKEY33.data()); + if ( strcmp(pkaddr,destaddr) == 0 ) + { + proof = std::make_pair(txid,newBranch); + return(0); + } + fprintf(stderr,"vin0[%d] -> %s vs %s\n",tx.vin[0].prevn,destaddr,pkaddr); + } + return(-1); + } + else + { + // ASSETCHAINS_SELFIMPORT and external coin is the assetchains symbol in the burnTx OP_RETURN + // burnAmount, rawtx and rawproof should be enough for gatewaysdeposit equivalent + return(-1); + } } else return(-1); return(0); @@ -81,20 +114,18 @@ int32_t CheckGATEWAYimport(std::string coin,TxProof proof,CTransaction burnTx,st int32_t CheckPUBKEYimport(TxProof proof,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().ToString().c_str()); return(0); return(-1); } -bool Eval::ImportCoin(const std::vector params, const CTransaction &importTx, unsigned int nIn) +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; if (importTx.vout.size() < 2) return Invalid("too-few-vouts"); - // params - TxProof proof; - CTransaction burnTx; - std::vector payouts; - if (!UnmarshalImportTx(importTx, proof, burnTx, payouts)) return Invalid("invalid-params"); @@ -102,15 +133,9 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp // It should not be at all malleable if (MakeImportCoinTransaction(proof, burnTx, payouts).GetHash() != importTx.GetHash()) return Invalid("non-canonical"); - // burn params - uint32_t targetCcid; - std::string targetSymbol; - uint256 payoutsHash; - if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash)) return Invalid("invalid-burn-tx"); - // check burn amount { uint64_t burnAmount = burnTx.vout.back().nValue; @@ -119,27 +144,24 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp uint64_t totalOut = 0; for (int i=0; i burnAmount) + if (totalOut > burnAmount || totalOut < burnAmount-txfee ) return Invalid("payout-too-high"); } - // 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()) + 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 ( ASSETCHAINS_SELFIMPORT == targetSymbol || ASSETCHAINS_SELFIMPORT == "GATEWAY" ) // various selfchain imports + else if ( ASSETCHAINS_SELFIMPORT == targetSymbol ) // various selfchain imports { if ( ASSETCHAINS_SELFIMPORT == "BEAM" ) { @@ -158,7 +180,7 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp } else { - if ( CheckGATEWAYimport(GetAssetchainsSymbol(),proof,burnTx,payouts) < 0 ) + if ( CheckGATEWAYimport(targetSymbol,proof,burnTx,payouts) < 0 ) return Invalid("GATEWAY-import-failure"); } } diff --git a/src/komodo_utils.h b/src/komodo_utils.h index f5d394c7e..a8823e5b3 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1798,12 +1798,6 @@ void komodo_args(char *argv0) ASSETCHAINS_SELFIMPORT = ""; exit(0); } - else if ( ASSETCHAINS_SELFIMPORT.size() > 0 && ASSETCHAINS_SELFIMPORT != "GATEWAY" ) - { - fprintf(stderr,"invalid -ac_import type\n"); - ASSETCHAINS_SELFIMPORT = ""; - exit(0); - } if ( ASSETCHAINS_SELFIMPORT.size() > 0 && ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID ) { fprintf(stderr,"selfimport chains cant be in a fungible cluster\n"); diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index c9a96165a..9ba93f3f4 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -46,9 +46,8 @@ int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); extern std::string ASSETCHAINS_SELFIMPORT; -int komodo_nextheight(); uint256 Parseuint256(char *hexstr); -int32_t GetSelfimportProof(TxProof &proof,CTransaction burnTx,uint256 hash); +int32_t GetSelfimportProof(CMutableTransaction &mtx,CScript &scriptPubKey,TxProof &proof,uint64_t burnAmount,std::vector rawtx,uint256 hash,std::vector rawproof); UniValue assetchainproof(const UniValue& params, bool fHelp) @@ -201,13 +200,7 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp) throw runtime_error("export_amount too small"); } if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) - { throw runtime_error("self-import chains cant be fungible"); - /*if ( ASSETCHAINS_SELFIMPORT == targetSymbol || ASSETCHAINS_SELFIMPORT == "GATEWAY" ) - { - ccid = 0xffffffff; - } // else maybe clusters of self-import chains can be supported?*/ - } CTxOut burnOut = MakeBurnOutput(burnAmount, ccid, targetSymbol, tx.vout); UniValue ret(UniValue::VOBJ); ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << tx.vout)))); @@ -284,33 +277,25 @@ UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp) UniValue selfimport(const UniValue& params, bool fHelp) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - TxProof proof; CTransaction burnTx,tx; CTxOut burnOut,savevout; uint64_t burnAmount; uint256 txid,blockHash; std::vector vouts; + CMutableTransaction mtx; + TxProof proof; CTransaction burnTx,tx; CTxOut burnOut; uint64_t burnAmount; uint256 txid,blockHash; std::vector vouts; std::vector rawtx,rawproof; CScript scriptPubKey; if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) throw runtime_error("selfimport only works on -ac_import chains"); - if (fHelp || params.size() != 2) - throw runtime_error("selfimport txid burnamount\n\n" + if (fHelp || params.size() < 3 || params.size() > 4) + throw runtime_error("selfimport rawtx txid burnamount\n\n" "creates signed selfimport transaction from txid"); - txid = Parseuint256((char *)params[0].get_str().c_str()); - burnAmount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - // txid is just used to specify the import recv address - // in reality it would be rawtx from the other chain and maybe better to specify address - if ( GetTransaction(txid,tx,blockHash,false) == 0 ) - throw runtime_error("selfimport couldnt find txid"); - savevout = tx.vout[0]; - mtx = tx; - mtx.vout.clear(); - mtx.vout.resize(1); - mtx.vout[0] = savevout; - mtx.vout[0].nValue = burnAmount; + rawtx = ParseHex(params[0].get_str().c_str()); + txid = Parseuint256((char *)params[1].get_str().c_str()); // allow for txid != hash(rawtx) + burnAmount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; + if ( params.size() == 4 ) + rawproof = ParseHex(params[3].get_str().c_str()); + if ( GetSelfimportProof(mtx,scriptPubKey,proof,burnAmount,rawtx,txid,rawproof) < 0 ) + throw std::runtime_error("Failed validating selfimport"); vouts = mtx.vout; burnOut = MakeBurnOutput(burnAmount,0xffffffff,ASSETCHAINS_SELFIMPORT,vouts); - mtx = tx; mtx.vout.clear(); mtx.vout.push_back(burnOut); burnTx = mtx; - if ( GetSelfimportProof(proof,tx,txid) < 0 ) - throw std::runtime_error("Failed validating selfimport"); return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(proof,burnTx,vouts))); }