From b897d56363f0cd41ec580ab53f5cc52433217521 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Fri, 22 Mar 2019 16:54:01 +0800 Subject: [PATCH 1/6] . --- src/cc/CCPayments.h | 2 +- src/cc/payments.cpp | 23 +++++++++++++++++++++-- src/wallet/rpcwallet.cpp | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/cc/CCPayments.h b/src/cc/CCPayments.h index 247a0f2ec..56d36f74e 100644 --- a/src/cc/CCPayments.h +++ b/src/cc/CCPayments.h @@ -29,6 +29,6 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr); -UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr); +UniValue PaymentsList(struct CCcontract_info *cp); #endif diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index d1e11dae5..8148be180 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -152,8 +152,23 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & { // one of two addresses // change must go to 1of2 txidaddr + // change is/must be in vout[0] // only 'F' or 1of2 txidaddr can be spent // all vouts must match exactly + BOOST_FOREACH(const CTxIn& vin, tx) + { + uint256 blockhash; CTransaction txin; + if ( myGetTransaction(vin.prevout.hash,txin,blockhash) ) + { + fprintf(stderr, "vin txid.%s\n", txin.GetHex().c_str()); + } + } + + BOOST_FOREACH(const CTxOut& vout, tx) + { + fprintf(stderr, "vout txid.%s\n", vout.hash.GetHex().c_str()); + } + return(true); } // end of consensus code @@ -377,6 +392,10 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr) mtx.vout[i+1].nValue *= amount; mtx.vout[i+1].nValue /= totalallocations; } +<<<<<<< Updated upstream +======= + //fprintf(stderr,"addinputs %.8f\n",(double)amount/COIN); +>>>>>>> Stashed changes if ( (inputsum= AddPaymentsInputs(cp,mtx,txidpk,amount+PAYMENTS_TXFEE,60,createtxid,latestheight)) >= amount ) { std::string rawtx; @@ -388,7 +407,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr) rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,onlyopret); if ( params != 0 ) free_json(params); - return(payments_rawtxresult(result,rawtx,0)); + return(payments_rawtxresult(result,rawtx,1)); } else { @@ -664,7 +683,7 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr) return(result); } -UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr) +UniValue PaymentsList(struct CCcontract_info *cp) { std::vector > addressIndex; uint256 txid,hashBlock; UniValue result(UniValue::VOBJ),a(UniValue::VARR); char markeraddr[64],str[65]; CPubKey Paymentspk; CTransaction tx; int32_t lockedblocks,minrelease,totalallocations; std::vector txidoprets; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 062ef6148..80ad2afe0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5653,7 +5653,7 @@ UniValue payments_list(const UniValue& params, bool fHelp) const CKeyStore& keystore = *pwalletMain; LOCK2(cs_main, pwalletMain->cs_wallet); cp = CCinit(&C,EVAL_PAYMENTS); - return(PaymentsList(cp,"")); + return(PaymentsList(cp)); } UniValue oraclesaddress(const UniValue& params, bool fHelp) From 550f698a5693219c67fd60859ca99f29d1493632 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Fri, 22 Mar 2019 17:15:19 +0800 Subject: [PATCH 2/6] fix --- src/cc/payments.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 8148be180..8b1156004 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -155,18 +155,18 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // change is/must be in vout[0] // only 'F' or 1of2 txidaddr can be spent // all vouts must match exactly - BOOST_FOREACH(const CTxIn& vin, tx) + BOOST_FOREACH(const CTxIn& vin, tx.vin) { uint256 blockhash; CTransaction txin; if ( myGetTransaction(vin.prevout.hash,txin,blockhash) ) { - fprintf(stderr, "vin txid.%s\n", txin.GetHex().c_str()); + fprintf(stderr, "vin txid.%s\n", txin.GetHash().GetHex().c_str()); } } - BOOST_FOREACH(const CTxOut& vout, tx) + BOOST_FOREACH(const CTxOut& vout, tx.vout) { - fprintf(stderr, "vout txid.%s\n", vout.hash.GetHex().c_str()); + fprintf(stderr, "vout txid.%s\n", vout.GetHash().GetHex().c_str()); } return(true); @@ -392,10 +392,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr) mtx.vout[i+1].nValue *= amount; mtx.vout[i+1].nValue /= totalallocations; } -<<<<<<< Updated upstream -======= //fprintf(stderr,"addinputs %.8f\n",(double)amount/COIN); ->>>>>>> Stashed changes if ( (inputsum= AddPaymentsInputs(cp,mtx,txidpk,amount+PAYMENTS_TXFEE,60,createtxid,latestheight)) >= amount ) { std::string rawtx; From a0a3e141ba8ad699a9f48670ab29b6d749f76cb1 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Fri, 22 Mar 2019 17:25:21 +0800 Subject: [PATCH 3/6] fix --- src/cc/payments.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 8b1156004..d63f23515 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -397,8 +397,8 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr) { std::string rawtx; if ( (CCchange= (inputsum - amount)) >= PAYMENTS_TXFEE ) - mtx.vout[0].nValue = CCchange; - mtx.vout.push_back(CTxOut(0,CScript() << ParseHex(HexStr(txidpk)) << OP_CHECKSIG)); + mtx.vout[0].nValue = CCchange-PAYMENTS_TXFEE; + mtx.vout.push_back(CTxOut(PAYMENTS_TXFEE,CScript() << ParseHex(HexStr(txidpk)) << OP_CHECKSIG)); GetCCaddress1of2(cp,destaddr,Paymentspk,txidpk); CCaddr1of2set(cp,Paymentspk,txidpk,cp->CCpriv,destaddr); rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,onlyopret); From 3bd5bc32327544206378dd44c29a494c80b0b3c2 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sat, 23 Mar 2019 14:32:43 +0800 Subject: [PATCH 4/6] initial validation commit ONLY validates non OP_RETURN --- src/cc/CCPayments.h | 2 +- src/cc/payments.cpp | 162 +++++++++++++++++++++++++++++++++++++++----- src/main.cpp | 2 +- 3 files changed, 147 insertions(+), 19 deletions(-) diff --git a/src/cc/CCPayments.h b/src/cc/CCPayments.h index 56d36f74e..247a0f2ec 100644 --- a/src/cc/CCPayments.h +++ b/src/cc/CCPayments.h @@ -29,6 +29,6 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr); UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr); -UniValue PaymentsList(struct CCcontract_info *cp); +UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr); #endif diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 6bd575835..93272fad7 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -148,27 +148,155 @@ int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t return(0); } +void pub2createtxid(char *str) +{ + int i,n; + char *rev; + n = (int32_t)strlen(str); + rev = (char *)malloc(n + 1); + for (i=0; i txidoprets; + int32_t i; bool fHasOpret = false; + CPubKey txidpk,Paymentspk; + int64_t change; + + //the nValue 0 vout at the end of the tx (last one if no opret) + //it is a pay to pubkey vout + //the "pubkey" is just 0x02 + if ( tx.vout.size() < 2 ) + return(false); + if ( tx.vout.back().scriptPubKey[0] == OP_RETURN ) + { + scriptpubkey = HexStr(tx.vout[tx.vout.size()-2].scriptPubKey.begin()+2, tx.vout[tx.vout.size()-2].scriptPubKey.end()-1); + fHasOpret = true; + } else scriptpubkey = HexStr(tx.vout[tx.vout.size()-1].scriptPubKey.begin()+2,tx.vout[tx.vout.size()-1].scriptPubKey.end()-1); + strcpy(temp, scriptpubkey.c_str()); + pub2createtxid(temp); + createtxid = Parseuint256(temp); + //printf("createtxid.%s\n",createtxid.ToString().c_str()); + + // use the createtxid to fetch the tx and all of the plans info. + if ( myGetTransaction(createtxid,tmptx,blockhash) != 0 ) + { + if ( tmptx.vout.size() > 0 && DecodePaymentsOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 ) + { + if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 ) + return(false); + Paymentspk = GetUnspendable(cp,0); + //fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() ); + + // Get all the script pubkeys and allocations + std::vector allocations; + std::vector scriptPubKeys; + int32_t checkallocations = 0; + i = 0; + BOOST_FOREACH(const uint256& txidopret, txidoprets) + { + CTransaction tx0; std::vector scriptPubKey,opret; int32_t allocation; + if ( myGetTransaction(txidopret,tx0,blockhash) != 0 && tx0.vout.size() > 1 && DecodePaymentsTxidOpRet(tx0.vout[tx0.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' ) + { + scriptPubKeys.push_back(CScript(scriptPubKey.begin(), scriptPubKey.end())); + allocations.push_back(allocation); + //fprintf(stderr, "i.%i scriptpubkey.%s allocation.%i\n",i,scriptPubKeys[i].ToString().c_str(),allocation); + checkallocations += allocation; + } + i++; + } + + // sanity check to make sure we got all the required info + if ( allocations.size() == 0 || scriptPubKeys.size() == 0 || allocations.size() != scriptPubKeys.size() ) + return(false); + + //fprintf(stderr, "totalallocations.%i checkallocations.%i\n",totalallocations, checkallocations); + if ( totalallocations != checkallocations ) + return(false); + + txidpk = CCtxidaddr(txidaddr,createtxid); + GetCCaddress1of2(cp,coinaddr,Paymentspk,txidpk); + //fprintf(stderr, "coinaddr.%s\n", coinaddr); + + // make sure change is in vout 0 and is paying to the contract address. + if ( (change= IsPaymentsvout(cp,tx,0,coinaddr)) == 0 ) + return(false); + + // Check vouts go to the right place and pay the right amounts. + int64_t amount = 0, checkamount; int32_t n = 0; + checkamount = tx.GetValueOut() - change - PAYMENTS_TXFEE; + for (i = 1; i < (fHasOpret ? tx.vout.size()-2 : tx.vout.size()-1); i++) { + std::string destscriptPubKey = HexStr(scriptPubKeys[n].begin(),scriptPubKeys[n].end()); + std::string voutscriptPubKey = HexStr(tx.vout[i].scriptPubKey.begin(),tx.vout[i].scriptPubKey.end()); + if ( destscriptPubKey != voutscriptPubKey ) + { + fprintf(stderr, "pays wrong destination destscriptPubKey.%s voutscriptPubKey.%s\n", destscriptPubKey.c_str(), voutscriptPubKey.c_str()); + return(false); + } + int64_t test = allocations[n]; + test *= checkamount; + test /= totalallocations; + if ( test != tx.vout[i].nValue ) + { + fprintf(stderr, "vout.%i test.%li vs nVlaue.%li\n",i, test, tx.vout[i].nValue); + return(false); + } + amount += tx.vout[i].nValue; + n++; + } + if ( checkamount != amount ) + return(false); + + if ( amount < minrelease*COIN ) + { + fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amount, (int64_t)minrelease*COIN ); + return(false); + } + + i = 0; + BOOST_FOREACH(const CTxIn& vin, tx.vin) + { + CTransaction txin; + if ( myGetTransaction(vin.prevout.hash,txin,blockhash) ) + { + // check the vin comes from the CC address's + if ( IsPaymentsvout(cp,txin,i,coinaddr) != 0 ) + { + fprintf(stderr, "vin.%i is not a payments CC vout\n", i); + return(false); + } + // check the chain depth vs locked blcoks requirement. + CBlockIndex* pblockindex = mapBlockIndex[blockhash]; + if ( pblockindex->GetHeight() > chainActive.LastTip()->GetHeight()-lockedblocks ) + { + fprintf(stderr, "vin.%i is not elegible to be spent yet height.%i vs elegible_ht.%i\n", i, pblockindex->GetHeight(), chainActive.LastTip()->GetHeight()-lockedblocks); + return(false); + } + //fprintf(stderr, "vin txid.%s\n", txin.GetHash().GetHex().c_str()); + } + i++; + } + } + } + // one of two addresses? only seems to ever use the 1! // change must go to 1of2 txidaddr // change is/must be in vout[0] // only 'F' or 1of2 txidaddr can be spent // all vouts must match exactly - BOOST_FOREACH(const CTxIn& vin, tx.vin) - { - uint256 blockhash; CTransaction txin; - if ( myGetTransaction(vin.prevout.hash,txin,blockhash) ) - { - fprintf(stderr, "vin txid.%s\n", txin.GetHash().GetHex().c_str()); - } - } - - BOOST_FOREACH(const CTxOut& vout, tx.vout) - { - fprintf(stderr, "vout txid.%s\n", vout.GetHash().GetHex().c_str()); - } - return(true); } // end of consensus code @@ -411,7 +539,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr) free_json(params); result.push_back(Pair("amount",ValueFromAmount(amount))); result.push_back(Pair("newamount",ValueFromAmount(newamount))); - return(payments_rawtxresult(result,rawtx,0)); + return(payments_rawtxresult(result,rawtx,1)); } else { @@ -691,7 +819,7 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr) return(result); } -UniValue PaymentsList(struct CCcontract_info *cp) +UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr) { std::vector > addressIndex; uint256 txid,hashBlock; UniValue result(UniValue::VOBJ),a(UniValue::VARR); char markeraddr[64],str[65]; CPubKey Paymentspk; CTransaction tx; int32_t lockedblocks,minrelease,totalallocations; std::vector txidoprets; diff --git a/src/main.cpp b/src/main.cpp index e520ad83f..9930e733c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7045,7 +7045,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } std::vector payload; vRecv >> payload; - komodo_netevent(payload); + //komodo_netevent(payload); return(true); } else if (strCommand == "verack") From 1f19c7c98710347b98300eaecafdd7ee3ec82029 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sat, 23 Mar 2019 15:39:33 +0800 Subject: [PATCH 5/6] push fixes to sync PAY --- src/cc/payments.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 93272fad7..aece40b67 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -181,7 +181,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & //it is a pay to pubkey vout //the "pubkey" is just 0x02 if ( tx.vout.size() < 2 ) - return(false); + return(eval->Invalid("not enough vouts")); if ( tx.vout.back().scriptPubKey[0] == OP_RETURN ) { scriptpubkey = HexStr(tx.vout[tx.vout.size()-2].scriptPubKey.begin()+2, tx.vout[tx.vout.size()-2].scriptPubKey.end()-1); @@ -198,7 +198,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ( tmptx.vout.size() > 0 && DecodePaymentsOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 ) { if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 ) - return(false); + return(eval->Invalid("negative values")); Paymentspk = GetUnspendable(cp,0); //fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() ); @@ -222,11 +222,11 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // sanity check to make sure we got all the required info if ( allocations.size() == 0 || scriptPubKeys.size() == 0 || allocations.size() != scriptPubKeys.size() ) - return(false); + return(eval->Invalid("missing data cannot validate")); //fprintf(stderr, "totalallocations.%i checkallocations.%i\n",totalallocations, checkallocations); if ( totalallocations != checkallocations ) - return(false); + return(eval->Invalid("allocation missmatch")); txidpk = CCtxidaddr(txidaddr,createtxid); GetCCaddress1of2(cp,coinaddr,Paymentspk,txidpk); @@ -234,7 +234,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & // make sure change is in vout 0 and is paying to the contract address. if ( (change= IsPaymentsvout(cp,tx,0,coinaddr)) == 0 ) - return(false); + return(eval->Invalid("change is in wrong vout or is wrong tx type")); // Check vouts go to the right place and pay the right amounts. int64_t amount = 0, checkamount; int32_t n = 0; @@ -245,7 +245,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ( destscriptPubKey != voutscriptPubKey ) { fprintf(stderr, "pays wrong destination destscriptPubKey.%s voutscriptPubKey.%s\n", destscriptPubKey.c_str(), voutscriptPubKey.c_str()); - return(false); + return(eval->Invalid("pays wrong address")); } int64_t test = allocations[n]; test *= checkamount; @@ -253,18 +253,19 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ( test != tx.vout[i].nValue ) { fprintf(stderr, "vout.%i test.%li vs nVlaue.%li\n",i, test, tx.vout[i].nValue); - return(false); + //return(eval->Invalid("amounts do not match")); } amount += tx.vout[i].nValue; n++; } + // This is a backup check to make sure there are no extra vouts paying something else! if ( checkamount != amount ) - return(false); + return(eval->Invalid("amounts do not match")); if ( amount < minrelease*COIN ) { fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amount, (int64_t)minrelease*COIN ); - return(false); + //return(eval->Invalid("amount is too small")); } i = 0; @@ -274,24 +275,26 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & if ( myGetTransaction(vin.prevout.hash,txin,blockhash) ) { // check the vin comes from the CC address's - if ( IsPaymentsvout(cp,txin,i,coinaddr) != 0 ) + char destaddr[64]; + Getscriptaddress(destaddr,txin.vout[vin.prevout.n].scriptPubKey); + if ( strcmp(destaddr,coinaddr) != 0 ) { - fprintf(stderr, "vin.%i is not a payments CC vout\n", i); - return(false); + fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s vout.%i\n", i, txin.GetHash().ToString().c_str(), vin.prevout.n); + return(eval->Invalid("vin is not paymentsCC type")); } // check the chain depth vs locked blcoks requirement. CBlockIndex* pblockindex = mapBlockIndex[blockhash]; if ( pblockindex->GetHeight() > chainActive.LastTip()->GetHeight()-lockedblocks ) { fprintf(stderr, "vin.%i is not elegible to be spent yet height.%i vs elegible_ht.%i\n", i, pblockindex->GetHeight(), chainActive.LastTip()->GetHeight()-lockedblocks); - return(false); + return(eval->Invalid("vin not elegible")); } //fprintf(stderr, "vin txid.%s\n", txin.GetHash().GetHex().c_str()); } i++; } - } - } + } else return(eval->Invalid("create transaction cannot decode")); + } else fprintf(stderr, "cannot get contract txn\n");//return(eval->Invalid("Could not get contract transaction")); // one of two addresses? only seems to ever use the 1! // change must go to 1of2 txidaddr // change is/must be in vout[0] From 0844c8290e15ac3f89848562bf1c93e114c8e146 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sat, 23 Mar 2019 15:50:02 +0800 Subject: [PATCH 6/6] missed return --- src/cc/payments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index aece40b67..7e2db0381 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -290,7 +290,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return(eval->Invalid("vin not elegible")); } //fprintf(stderr, "vin txid.%s\n", txin.GetHash().GetHex().c_str()); - } + } else return(eval->Invalid("cant get vin transaction")); i++; } } else return(eval->Invalid("create transaction cannot decode"));