diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 320cd967d..4565b31b6 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -40,7 +40,10 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) { auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0; int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*othercond3=0,*cond; CPubKey unspendablepk; + CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; + int64_t utxovalues[64],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; + int32_t i,utxovout,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; + uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*othercond2=0,*othercond3=0,*cond; CPubKey unspendablepk; n = mtx.vout.size(); for (i=0; i 0 ) mtx.vout.push_back(CTxOut(0,opret)); PrecomputedTransactionData txdata(mtx); - n = mtx.vin.size(); + n = mtx.vin.size(); + //Reorder vins so that for multiple normal vins all other except vin0 goes to the end + //This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation. + if (normalvins>1) + { + for(i=1;i vopret; uint8_t *script,e,f; GetOpReturnData(scriptPubKey,vopret); script = (uint8_t *)vopret.data(); - if ( vopret.size() > 1 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num) != 0 ) + if ( vopret.size() > 1 && script[0] == EVAL_ORACLES ) { - if ( e == EVAL_ORACLES && (f == 'R' || f == 'S') ) + if (script[0] == EVAL_ORACLES && (script[1]== 'R' || script[1] == 'S') && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> oracletxid; ss >> pk; ss >> num)!=0) return(f); + else return(script[1]); } return(0); } @@ -567,9 +568,6 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio } } } - else if ( i != 0 ) - return eval->Invalid("vin0 not normal"); - } for (i=0; i origpubkey; CTransaction vintx; int32_t vout,n = 0; - std::vector > unspentOutputs; + char coinaddr[64],funcid; int64_t nValue,price,totalinputs = 0; uint256 tmporacletxid,tmpbatontxid,txid,hashBlock; std::vector origpubkey,data; CTransaction vintx; int32_t numvouts,vout,n = 0; + std::vector > unspentOutputs; CPubKey tmppk; int64_t tmpnum; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); //fprintf(stderr,"addoracleinputs from (%s)\n",coinaddr); @@ -677,19 +675,27 @@ int64_t AddOracleInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub txid = it->first.txhash; vout = (int32_t)it->first.index; //char str[65]; fprintf(stderr,"oracle check %s/v%d\n",uint256_str(str,txid),vout); - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && (numvouts=vintx.vout.size()-1)>0) { - // get valid CC payments - if ( (nValue= IsOraclesvout(cp,vintx,vout)) >= 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if ((funcid=DecodeOraclesOpRet(vintx.vout[numvouts].scriptPubKey,tmporacletxid,tmppk,tmpnum))!=0 && (funcid=='S' || funcid=='D')) { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } //else fprintf(stderr,"nValue %.8f or utxo memspent\n",(double)nValue/COIN); + if (funcid=='D' && DecodeOraclesData(vintx.vout[numvouts].scriptPubKey,tmporacletxid,tmpbatontxid,tmppk,data)==0) + fprintf(stderr,"invalid oraclesdata transaction \n"); + else if (tmporacletxid==oracletxid) + { + // get valid CC payments + if ( (nValue= IsOraclesvout(cp,vintx,vout)) >= 10000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( total != 0 && maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + n++; + if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) + break; + } //else fprintf(stderr,"nValue %.8f or utxo memspent\n",(double)nValue/COIN); + } + } } else fprintf(stderr,"couldnt find transaction\n"); } return(totalinputs); @@ -802,7 +808,7 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector da if ( batontxid != zeroid ) // not impossible to fail, but hopefully a very rare event mtx.vin.push_back(CTxIn(batontxid,1,CScript())); else fprintf(stderr,"warning: couldnt find baton utxo %s\n",batonaddr); - if ( (inputs= AddOracleInputs(cp,mtx,mypk,datafee,60)) > 0 ) + if ( (inputs= AddOracleInputs(cp,mtx,oracletxid,mypk,datafee,60)) > 0 ) { if ( inputs > datafee ) CCchange = (inputs - datafee); @@ -898,7 +904,7 @@ UniValue OracleInfo(uint256 origtxid) funding = LifetimeOraclesFunds(cp,oracletxid,pk); sprintf(numstr,"%.8f",(double)funding/COIN); obj.push_back(Pair("lifetime",numstr)); - funding = AddOracleInputs(cp,mtx,pk,0,0); + funding = AddOracleInputs(cp,mtx,oracletxid,pk,0,0); sprintf(numstr,"%.8f",(double)funding/COIN); obj.push_back(Pair("funds",numstr)); sprintf(numstr,"%.8f",(double)datafee/COIN);