From 0acaa3517fce93f24a8050dfea7f5aa51524a27d Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Thu, 18 Apr 2019 14:23:12 +0200 Subject: [PATCH] Adding validation for importgateway CC (#22) --- src/cc/gateways.cpp | 29 ++-- src/cc/import.cpp | 303 +++++++++++++++------------------------ src/cc/importgateway.cpp | 8 +- src/importcoin.cpp | 12 +- src/importcoin.h | 4 +- src/rpc/crosschain.cpp | 1 + src/wallet/rpcwallet.cpp | 1 + 7 files changed, 143 insertions(+), 215 deletions(-) diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index e15735d70..3334255d4 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -571,8 +571,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("invalid gatewaysbind OP_RETURN data!"); else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for gatewaysbind!"); - else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 ) - return eval->Invalid("vin.1 is CC for gatewaysbind!"); else if ( ConstrainVout(tmptx.vout[0],1,gatewaystokensaddr,totalsupply)==0) return eval->Invalid("invalid tokens to gateways vout for gatewaysbind!"); else if ( ConstrainVout(tmptx.vout[1],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0) @@ -599,6 +597,11 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid(validationError); } else if ( DecodeOraclesCreateOpRet(tmptx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' ) + { + sprintf(validationError,"invalid oraclescreate OP_RETURN data\n"); + return eval->Invalid(validationError); + } + else if (refcoin!=name) { sprintf(validationError,"mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str()); return eval->Invalid(validationError); @@ -632,10 +635,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("invalid gatewaysdeposittxid!"); else if (IsCCInput(tx.vin[0].scriptSig) != 0) return eval->Invalid("vin.0 is normal for gatewaysclaim!"); - else if (IsCCInput(tx.vin[1].scriptSig) == 0) - return eval->Invalid("vin.1 is CC for gatewaysclaim!"); - else if ((*cp->ismyvin)(tx.vin[2].scriptSig) == 0 || myGetTransaction(tx.vin[2].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[2].prevout.n].nValue!=CC_MARKER_VALUE) - return eval->Invalid("vin.2 is CC marker for gatewaysclaim or invalid marker amount!"); + else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewaysclaim or invalid marker amount!"); else if (_GetCCaddress(destaddr,EVAL_TOKENS,pubkey)==0 || ConstrainVout(tx.vout[0],1,destaddr,amount)==0) return eval->Invalid("invalid vout tokens to destpub for gatewaysclaim!"); else if (numvouts>2 && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || ConstrainVout(tx.vout[1],1,gatewaystokensaddr,tmptx.vout[tx.vin[1].prevout.n].nValue-amount)==0)) @@ -695,8 +696,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("refcoin different than in bind tx"); else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for gatewaysWithdraw!"); - else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 ) - return eval->Invalid("vin.1 is CC for gatewaysWithdraw!"); else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0) return eval->Invalid("invalid marker vout for gatewaysWithdraw!"); else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0) @@ -717,8 +716,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); else if (IsCCInput(tx.vin[0].scriptSig) != 0) return eval->Invalid("vin.0 is normal for gatewayspartialsign!"); - else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) - return eval->Invalid("vin.1 is CC marker for gatewayspartialsign or invalid marker amount!"); + else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewayspartialsign or invalid marker amount!"); else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 ) return eval->Invalid("vout.0 invalid marker for gatewayspartialsign!"); else if (K>M) @@ -739,8 +738,6 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("refcoin different than in bind tx"); else if ( IsCCInput(tmptx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for gatewaysWithdraw!"); - else if ( IsCCInput(tmptx.vin[1].scriptSig) == 0 ) - return eval->Invalid("vin.1 is CC for gatewaysWithdraw!"); else if ( ConstrainVout(tmptx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE)==0) return eval->Invalid("invalid marker vout for gatewaysWithdraw!"); else if ( ConstrainVout(tmptx.vout[1],1,gatewaystokensaddr,amount)==0) @@ -761,8 +758,8 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & return eval->Invalid("gatewaysbind tx is not yet confirmed(notarised)!"); else if (IsCCInput(tx.vin[0].scriptSig) != 0) return eval->Invalid("vin.0 is normal for gatewayscompletesigning!"); - else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) - return eval->Invalid("vin.1 is CC marker for gatewayscompletesigning or invalid marker amount!"); + else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewayscompletesigning or invalid marker amount!"); else if (ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,CC_MARKER_VALUE) == 0 ) return eval->Invalid("vout.0 invalid marker for gatewayscompletesigning!"); else if (KInvalid("gatewaysbind tx is not yet confirmed(notarised)!"); else if ( IsCCInput(tx.vin[0].scriptSig) != 0 ) return eval->Invalid("vin.0 is normal for gatewaysmarkdone!"); - else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 || myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE) - return eval->Invalid("vin.1 is CC marker for gatewaysmarkdone or invalid marker amount!"); + else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE) + return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC marker for gatewaysmarkdone or invalid marker amount!"); else if (KInvalid("invalid number of signs!"); break; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index b847e07d2..ea22f5e42 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -32,35 +32,13 @@ extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid); int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid); -uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); +uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); +int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); char *nonportable_path(char *str); char *portable_path(char *str); void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); void *filestr(long *allocsizep,char *_fname); -// ac_import=chain support: -// encode opret for gateways import -CScript EncodeImportTxOpRet(uint32_t targetCCid, std::string coin, std::vector publishers, std::vectortxids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vectorproof, CPubKey destpub, int64_t amount) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount); - return(opret); -} - -CScript EncodeGatewaysImportTxOpRet(uint32_t targetCCid, std::string coin, uint256 bindtxid, std::vector publishers, std::vectortxids, int32_t height, uint256 cointxid, int32_t claimvout, std::string rawburntx, std::vectorproof, CPubKey destpub, int64_t amount) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << targetCCid << coin << bindtxid << publishers << txids << height << cointxid << claimvout << rawburntx << proof << destpub << amount); - return(opret); -} - -CScript EncodeCodaImportTxOpRet(uint32_t targetCCid, std::string coin, std::string burntx, uint256 bindtxid, CPubKey destpub, int64_t amount) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << targetCCid << burntx << bindtxid << destpub << amount); - return(opret); -} - cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { char cmdstr[5000],fname[256],*jsonstr; @@ -81,106 +59,6 @@ cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2, return(retjson); } -bool ImportCoinGatewaysVerify(CTransaction oracletx, int32_t claimvout, std::string refcoin, uint256 burntxid, const std::string rawburntx, std::vectorproof, uint256 merkleroot) -{ - std::vector txids; - uint256 proofroot; - std::string name, description, format; - int32_t i, numvouts; - - if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey, name, description, format) != 'C' || name != refcoin) - { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "ImportCoinGatewaysVerify mismatched oracle name=" << name.c_str() << " != " << refcoin.c_str() << std::endl); - return false; - } - - LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "verified proof for burntxid=" << burntxid.GetHex() << " in trusted merkleroot" << std::endl); - return true; -} - -// make import tx with burntx and its proof of existence -// std::string MakeGatewaysImportTx(uint64_t txfee, uint256 oracletxid, int32_t height, std::string refcoin, std::vector proof, std::string rawburntx, int32_t ivout, uint256 burntxid,std::string destaddr) -// { -// CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); -// CTransaction oracletx,regtx; CPubKey regpk; -// uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts; -// std::string name,desc,format; std::vector vouts; -// std::vector pubkeys; std::vectortxids; -// char markeraddr[64]; int64_t datafee; -// std::vector > unspentOutputs; - -// if (!E_UNMARSHAL(ParseHex(rawburntx), ss >> burntx)) -// return std::string(""); -// CAmount amount = GetCoinImportValue(burntx); // equal to int64_t -// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx height=" << height << " coin=" << refcoin << " amount=" << (double)amount / COIN << " pubkeys num=" << pubkeys.size() << std::endl); -// if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0) -// { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx cant find oracletxid=" << oracletxid.GetHex() << std::endl); -// return(""); -// } -// if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C') -// { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl); -// return(""); -// } -// if (name!=refcoin || format!="Ihh") -// { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl); -// return(""); -// } -// CCtxidaddr(markeraddr,oracletxid); -// SetCCunspents(unspentOutputs,markeraddr,true); -// for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) -// { -// txid = it->first.txhash; -// if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0 -// && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid ) -// { -// pubkeys.push_back(regpk); -// n++; -// } -// } -// merkleroot = zeroid; -// for (i = m = 0; i < n; i++) -// { -// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx using pubkeys[" << i << "]=" << HexStr(pubkeys[i]) << std::endl); -// if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid) -// { -// if (merkleroot == zeroid) -// merkleroot = mhash, m = 1; -// else if (mhash == merkleroot) -// m ++; -// txids.push_back(txid); -// } -// } -// LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeGatewaysImportTx burntxid=" << burntxid.GetHex() << " nodes m=" << m << " of n=" << n << std::endl); -// if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot -// { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl ); -// return(""); -// } -// proofroot = BitcoinGetProofMerkleRoot(proof, txids); -// if (proofroot != merkleroot) -// { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl); -// return(""); -// } -// // check the burntxid is in the proof: -// if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) { -// LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeGatewaysImportTx invalid proof for this burntxid=" << burntxid.GetHex() << std::endl); -// return(""); -// } -// burntx.vout.push_back(MakeBurnOutput(amount,0xffffffff,refcoin,vouts,proof,oracletxid,height)); -// std::vector leaftxids; -// BitcoinGetProofMerkleRoot(proof, leaftxids); -// MerkleBranch newBranch(0, leaftxids); -// TxProof txProof = std::make_pair(burntxid, newBranch); -// CTxDestination dest = DecodeDestination(destaddr.c_str()); -// CScript scriptPubKey = GetScriptForDestination(dest); -// vouts.push_back(CTxOut(amount,scriptPubKey)); -// return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof, burntx, vouts))); -// } - // makes source tx for self import tx std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx) { @@ -452,71 +330,118 @@ int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector proof, - uint256 bindtxid,std::vector publishers,std::vector txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub) + uint256 bindtxid,std::vector publishers,std::vector txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount) { - // CTransaction oracletx,regtx; CPubKey regpk; - // uint256 proofroot,txid,tmporacletxid,merkleroot,mhash,hashBlock; int32_t i,m,n=0,numvouts; - // std::string name,desc,format; std::vector vouts; - // std::vector pubkeys; std::vectortxids; - // char markeraddr[64]; int64_t datafee; - // std::vector > unspentOutputs; + CTransaction oracletx,bindtx,regtx; int32_t i,m,n=0,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype; + uint256 txid,oracletxid,tmporacletxid,merkleroot,mhash,hashBlock; + std::string name,desc,format,coin; std::vector vouts; CPubKey regpk; + std::vector pubkeys,tmppubkeys,tmppublishers; char markeraddr[64],deposit[64],destaddr[64],tmpdest[64]; int64_t datafee; + std::vector > unspentOutputs; + // ASSETCHAINS_SELFIMPORT is coin // check for valid burn from external coin blockchain and if valid return(0); - // if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0) - // { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl); - // return(-1); - // } - // if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C') - // { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl); - // return(-1); - // } - // if (name!=refcoin || format!="Ihh") - // { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl); - // return(-1); - // } - // CCtxidaddr(markeraddr,oracletxid); - // SetCCunspents(unspentOutputs,markeraddr,true); - // for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - // { - // txid = it->first.txhash; - // if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0 - // && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid ) - // { - // pubkeys.push_back(regpk); - // n++; - // } - // } - // merkleroot = zeroid; - // for (i = m = 0; i < n; i++) - // { - // if ((mhash = CCOraclesReverseScan("importcoind-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid) - // { - // if (merkleroot == zeroid) - // merkleroot = mhash, m = 1; - // else if (mhash == merkleroot) - // m ++; - // txids.push_back(txid); - // } - // } - // if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot - // { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl ); - // return(-1); - // } - // proofroot = BitcoinGetProofMerkleRoot(proof, txids); - // if (proofroot != merkleroot) - // { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport mismatched proof merkleroot=" << proofroot.GetHex() << " and oracles merkleroot=" << merkleroot.GetHex() << std::endl); - // return(-1); - // } - // // check the burntxid is in the proof: - // if (std::find(txids.begin(), txids.end(), burnTx.GetHash()) == txids.end()) { - // LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid proof for this burntxid=" << burnTx.GetHash().GetHex() << std::endl); - // return(-1); - // } + if (GetTransaction(bindtxid, bindtx, hashBlock, false) == 0 || (numvouts = bindtx.vout.size()) <= 0) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find bindtxid=" << bindtxid.GetHex() << std::endl); + return(-1); + } + else if (DecodeImportGatewayBindOpRet(deposit,bindtx.vout[numvouts - 1].scriptPubKey,coin,oracletxid,M,N,tmppubkeys,taddr,prefix,prefix2,wiftype) != 'B') + { + LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckGATEWAYimport invalid bind tx. bindtxid=" << bindtxid.GetHex() << std::endl); + return(-1); + } + else if (refcoin!=coin) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid coin " << refcoin << "!=" << coin << std::endl); + return(-1); + } + else if ( N == 0 || N > 15 || M > N ) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid N or M " << std::endl); + return(-1); + } + else if (tmppubkeys.size()!=N) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport not enough pubkeys for given N " << std::endl); + return(-1); + } + else if (komodo_txnotarizedconfirmed(bindtxid) == false) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport bindtx not yet confirmed/notarized" << std::endl); + return(-1); + } + else if (GetTransaction(oracletxid, oracletx, hashBlock, false) == 0 || (numvouts = oracletx.vout.size()) <= 0) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport cant find oracletxid=" << oracletxid.GetHex() << std::endl); + return(-1); + } + else if (DecodeOraclesCreateOpRet(oracletx.vout[numvouts - 1].scriptPubKey,name,desc,format) != 'C') + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle tx. oracletxid=" << oracletxid.GetHex() << std::endl); + return(-1); + } + else if (name!=refcoin || format!="Ihh") + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport invalid oracle name or format tx. oracletxid=" << oracletxid.GetHex() << " name=" << name << " format=" << format << std::endl); + return(-1); + } + CCtxidaddr(markeraddr,oracletxid); + SetCCunspents(unspentOutputs,markeraddr,false); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + if ( GetTransaction(txid,regtx,hashBlock,false) != 0 && regtx.vout.size() > 0 + && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,tmporacletxid,regpk,datafee) == 'R' && oracletxid == tmporacletxid ) + { + pubkeys.push_back(regpk); + n++; + } + } + if (pubkeys.size()!=tmppubkeys.size()) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of bind and oracle pubkeys " << tmppubkeys.size() << "!=" << pubkeys.size() << std::endl); + return(-1); + } + merkleroot = zeroid; + for (i = m = 0; i < n; i++) + { + if ((mhash = CCOraclesReverseScan("importgateway-1",txid, height, oracletxid, OraclesBatontxid(oracletxid, pubkeys[i]))) != zeroid) + { + if (merkleroot == zeroid) + merkleroot = mhash, m = 1; + else if (mhash == merkleroot) + m ++; + tmppublishers.push_back(pubkeys[i]); + } + } + if (publishers.size()!=tmppublishers.size()) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport different number of publishers for burtx in oracle" << std::endl); + return(-1); + } + else if (merkleroot == zeroid || m < n / 2) // none or less than half oracle nodes sent merkleroot + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport couldnt find merkleroot for block height=" << height << "coin=" << refcoin.c_str() << " oracleid=" << oracletxid.GetHex() << " m=" << m << " vs n=" << n << std::endl ); + return(-1); + } + else if ( ImportGatewayVerify(deposit,oracletxid,burnvout,refcoin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount ) + { + CCerror = strprintf("burntxid didnt validate !"); + LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); + return(-1); + } + else if (importTx.vout[0].nValue!=amount) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import amount different than in burntx" << std::endl); + return(-1); + } + Getscriptaddress(destaddr,importTx.vout[0].scriptPubKey); + Getscriptaddress(tmpdest,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG); + if (strcmp(destaddr,tmpdest)!=0) + { + LOGSTREAM("importgateway", CCLOG_INFO, stream << "CheckGATEWAYimport import coins destination different than in burntx" << std::endl); + return(-1); + } return(0); } @@ -581,8 +506,8 @@ int32_t CheckPUBKEYimport(TxProof proof,std::vector rawproof,CTransacti */ bool Eval::ImportCoin(const std::vector params,const CTransaction &importTx,unsigned int nIn) { - TxProof proof; CTransaction burnTx; std::vector payouts; uint64_t txfee = 10000; int32_t height,burnvout; std::vector publishers; - uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid; std::vector rawproof; + TxProof proof; CTransaction burnTx; std::vector payouts; int64_t txfee = 10000, amount; int32_t height,burnvout; std::vector publishers; + uint32_t targetCcid; std::string targetSymbol,srcaddr,destaddr,receipt,rawburntx; uint256 payoutsHash,bindtxid,burntxid; std::vector rawproof; std::vector txids; CPubKey destpub; if ( importTx.vout.size() < 2 ) @@ -649,7 +574,7 @@ bool Eval::ImportCoin(const std::vector params,const CTransaction &impo { if ( targetSymbol != ASSETCHAINS_SELFIMPORT ) return Invalid("invalid-gateway-import-coin"); - else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,height,burnvout,rawburntx,destpub) < 0 ) + else if ( UnmarshalBurnTx(burnTx,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount)==0 || CheckGATEWAYimport(importTx,burnTx,targetSymbol,rawproof,bindtxid,publishers,txids,burntxid,height,burnvout,rawburntx,destpub,amount) < 0 ) return Invalid("GATEWAY-import-failure"); } } diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp index f7bd9b669..c3d318ca5 100644 --- a/src/cc/importgateway.cpp +++ b/src/cc/importgateway.cpp @@ -212,7 +212,7 @@ int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvo } if (std::find(txids.begin(), txids.end(), burntxid) == txids.end()) { - LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify invalid proof for this burntxid" << std::endl); + LOGSTREAM("importgateway",CCLOG_INFO, stream << "ImportGatewayVerify invalid proof for this burntxid " << burntxid.GetHex() << std::endl); return 0; } if ( DecodeHexTx(tx,deposithex) != 0 ) @@ -611,18 +611,18 @@ std::string ImportGatewayDeposit(uint64_t txfee,uint256 bindtxid,int32_t height, LOGSTREAM("importgateway",CCLOG_INFO, stream << "burntxid." << burntxid.GetHex() << " m." << m << " of n." << n << std::endl); if ( merkleroot == zeroid || m < n/2 ) { - CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,coin.c_str(),uint256_str(str,oracletxid),m,n); + CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,refcoin.c_str(),uint256_str(str,oracletxid),m,n); LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); return(""); } - if ( ImportGatewayVerify(burnaddr,oracletxid,claimvout,coin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount ) + if ( ImportGatewayVerify(burnaddr,oracletxid,claimvout,refcoin,burntxid,rawburntx,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount ) { CCerror = strprintf("burntxid didnt validate!"); LOGSTREAM("importgateway",CCLOG_INFO, stream << CCerror << std::endl); return(""); } vouts.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG)); - burntx.vout.push_back(MakeBurnOutput((CAmount)amount,0xffffffff,refcoin,vouts,proof,bindtxid,publishers,txids,height,claimvout,rawburntx,destpub)); + burntx.vout.push_back(MakeBurnOutput((CAmount)amount,0xffffffff,refcoin,vouts,proof,bindtxid,publishers,txids,burntxid,height,claimvout,rawburntx,destpub,amount)); std::vector leaftxids; BitcoinGetProofMerkleRoot(proof, leaftxids); MerkleBranch newBranch(0, leaftxids); diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 051129020..6702a78dd 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -53,7 +53,7 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb } CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, - uint256 bindtxid,std::vector publishers,std::vector txids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub) + uint256 bindtxid,std::vector publishers,std::vector txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount) { std::vector opret; opret = E_MARSHAL(ss << VARINT(targetCCid); @@ -63,10 +63,12 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb ss << bindtxid; ss << publishers; ss << txids; + ss << burntxid; ss << height; ss << burnvout; ss << rawburntx; - ss << destpub); + ss << destpub; + ss << amount); return CTxOut(value, CScript() << OP_RETURN << opret); } @@ -125,7 +127,7 @@ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::strin ss >> receipt)); } -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub) +bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount) { std::vector burnOpret,rawproof; bool isEof=true; uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol; @@ -139,10 +141,12 @@ bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector> bindtxid; ss >> publishers; ss >> txids; + ss >> burntxid; ss >> height; ss >> burnvout; ss >> rawburntx; - ss >> destpub)); + ss >> destpub; + ss >> amount)); } diff --git a/src/importcoin.h b/src/importcoin.h index 8cb8dbc58..0fcc350d0 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -30,13 +30,13 @@ CTransaction MakeImportCoinTransaction(const TxProof proof, CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof); CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, - uint256 bindtxid,std::vector publishers,std::vectortxids,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub); + uint256 bindtxid,std::vector publishers,std::vectortxids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount); CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof,std::string srcaddr, std::string receipt); bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector &rawproof); bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt); -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub); +bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount); bool UnmarshalImportTx(const CTransaction importTx, TxProof &proof, CTransaction &burnTx,std::vector &payouts); bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state); diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index c7992a953..cacf4357e 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -631,6 +631,7 @@ UniValue importgatewaypartialsign(const UniValue& params, bool fHelp) coin = params[1].get_str(); parthex = params[2].get_str(); hex = ImportGatewayPartialSign(0,txid,coin,parthex); + RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a21de63f4..847205ec1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6594,6 +6594,7 @@ UniValue gatewayspartialsign(const UniValue& params, bool fHelp) coin = params[1].get_str(); parthex = params[2].get_str(); hex = GatewaysPartialSign(0,txid,coin,parthex); + RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success"));