diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 36fea57bf..f05b522fa 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -62,7 +62,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) } else { - komodo_interestsum(); + //komodo_interestsum(); komodo_longestchain(); MilliSleep(20000); } diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 5c933bd77..4bc1adc42 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -17,15 +17,17 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs) { - char coinaddr[64],destaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t j,vout,n = 0; + char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t j,vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); - + threshold = total/maxinputs; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; + if ( it->second.satoshis < threshold ) + continue; for (j=0; j #include #include "../komodo_defs.h" +#include "../utlist.h" +#include "../uthash.h" extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE; extern uint32_t ASSETCHAINS_CC; +extern char ASSETCHAINS_SYMBOL[]; extern std::string CCerror; #define SMALLVAL 0.000000000000001 @@ -95,8 +98,8 @@ int32_t is_hexstr(char *str,int32_t n); bool myAddtomempool(CTransaction &tx); //uint64_t myGettxout(uint256 hash,int32_t n); bool myIsutxo_spentinmempool(uint256 txid,int32_t vout); +bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); -bool mySendrawtransaction(std::string res); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); @@ -134,6 +137,7 @@ bool IsCCInput(CScript const& scriptSig); int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); uint256 revuint256(uint256 txid); +bool pubkey2addr(char *destaddr,uint8_t *pubkey33); char *uint256_str(char *dest,uint256 txid); char *pubkey33_str(char *dest,uint8_t *pubkey33); uint256 Parseuint256(char *hexstr); diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index be8776a8e..0b78c61d4 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -33,9 +33,8 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip UpdateTransaction(mtx,vini,sigdata); return(true); } else fprintf(stderr,"signing error for SignTx vini.%d %.8f\n",vini,(double)utxovalue/COIN); -#else - return(false); #endif + return(false); } std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret) @@ -327,21 +326,26 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t * int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs) { - int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=1024; int64_t above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; + int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=64; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; #ifdef ENABLE_WALLET const CKeyStore& keystore = *pwalletMain; assert(pwalletMain != NULL); LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos)); + threshold = total/maxinputs; + if ( maxinputs > maxutxos ) + maxutxos = maxinputs; + sum = 0; BOOST_FOREACH(const COutput& out, vecOutputs) { - if ( out.fSpendable != 0 ) + if ( out.fSpendable != 0 && out.tx->vout[out.i].nValue >= threshold ) { txid = out.tx->GetHash(); vout = out.i; - if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) + if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) { + //fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout); if ( mtx.vin.size() > 0 ) { for (i=0; itxid = txid; up->nValue = out.tx->vout[out.i].nValue; up->vout = vout; + sum += up->nValue; //fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos); - if ( n >= maxutxos ) + if ( n >= maxutxos || sum >= total ) break; } } diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index d4de992f7..889b6fdd4 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -74,6 +74,7 @@ CC* GetCryptoCondition(CScript const& scriptSig) std::vector ffbin; if (scriptSig.GetOp(pc, opcode, ffbin)) return cc_readFulfillmentBinary((uint8_t*)ffbin.data(), ffbin.size()-1); + else return(0); } bool IsCCInput(CScript const& scriptSig) @@ -390,7 +391,7 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) } else if ( hashBlock == zeroid ) { - fprintf(stderr,"CCduration no hashBlock for txid %s\n",uint256_str(str,txid)); + //fprintf(stderr,"CCduration no hashBlock for txid %s\n",uint256_str(str,txid)); return(0); } else if ( (pindex= mapBlockIndex[hashBlock]) == 0 || (txtime= pindex->nTime) == 0 || (txheight= pindex->nHeight) <= 0 ) @@ -400,7 +401,8 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) } else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nTime < txtime || pindex->nHeight <= txheight ) { - fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s hts.(%d %d)\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid),txheight,(int32_t)pindex->nHeight); + if ( pindex->nTime < txtime ) + fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s hts.(%d %d)\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid),txheight,(int32_t)pindex->nHeight); return(0); } numblocks = (pindex->nHeight - txheight); diff --git a/src/cc/MofN.cpp b/src/cc/MofN.cpp index 84952176f..c22c48263 100644 --- a/src/cc/MofN.cpp +++ b/src/cc/MofN.cpp @@ -128,6 +128,7 @@ bool MofNValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) int64_t AddMofNInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { + // add threshold check char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 1ddbdc4f8..a421f9e44 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -249,8 +249,8 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx } fprintf(stderr,"fillbuy validated\n"); break; - case 'e': // selloffer - break; // disable swaps + //case 'e': // selloffer + // break; // disable swaps case 's': // selloffer //vin.0: normal input //vin.1+: valid CC output for sale @@ -322,6 +322,7 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx fprintf(stderr,"fill validated\n"); break; case 'E': // fillexchange + return eval->Invalid("unexpected assets fillexchange funcid"); break; // disable asset swaps //vin.0: normal input //vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0] @@ -371,6 +372,10 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx } fprintf(stderr,"fill validated\n"); break; + default: + fprintf(stderr,"illegal assets funcid.(%c)\n",funcid); + return eval->Invalid("unexpected assets funcid"); + break; } return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); } diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 7b5f106d0..d0d8db0bb 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -120,6 +120,7 @@ bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t int64_t AddAuctionInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { + // add threshold check char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index d92186d26..672e426a8 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -348,8 +348,12 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & return eval->Invalid("invalid amount, refund amount and funds in channel must match!"); } break; + default: + fprintf(stderr,"illegal channels funcid.(%c)\n",funcid); + return eval->Invalid("unexpected channels funcid"); + break; } - } + } else return eval->Invalid("unexpected channels missing funcid"); retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); if ( retval != 0 ) fprintf(stderr,"Channel tx validated\n"); @@ -692,7 +696,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid) UniValue ChannelsInfo(uint256 channeltxid) { UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid; - struct CCcontract_info *cp,C; char myCCaddr[65],addr[65],str1[256],str2[256]; int32_t vout,numvouts,param1,numpayments; + struct CCcontract_info *cp,C; char myCCaddr[65],addr[65],str1[512],str2[256]; int32_t vout,numvouts,param1,numpayments; int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; std::vector > txids; @@ -768,4 +772,4 @@ UniValue ChannelsInfo(uint256 channeltxid) } } return(result); -} \ No newline at end of file +} diff --git a/src/cc/dapps/diceloop b/src/cc/dapps/diceloop new file mode 100755 index 000000000..44550b46a --- /dev/null +++ b/src/cc/dapps/diceloop @@ -0,0 +1,6 @@ +while true +do +./c dicestatus KMDICE 5be49570c56d036abb08b6d084da93a8a86f58fc48db4a1086be95540d752d6f + +sleep 10 +done diff --git a/src/cc/dapps/sendmany b/src/cc/dapps/sendmany new file mode 100755 index 000000000..45560b505 --- /dev/null +++ b/src/cc/dapps/sendmany @@ -0,0 +1,3 @@ +export addr="RXgCPfi6wccRr3Eai3X9duTTkAirhcQLNo" +./komodo-cli -ac_name=KMDICE sendmany "" "{\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023,\"$addr\":0.023}" + diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index c5bebeba0..95056509d 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -88,86 +88,409 @@ WARNING: there is an attack vector that precludes betting any large amounts, it Actually a much better solution to this is possible, which allows to retain the realtime response aspect of dice CC, which is critical to its usage. +What is needed is for the dealer node to track the entropy tx that was already broadcast into the mempool with its entropy revealed. Then before processing a dicebet, it is checked against the already revealed list. If it is found, the dicebet is refunded with proof that a different dicebet was already used to reveal the entropy + change to hashtables + validate refund */ #include "../compat/endian.h" -static uint256 bettxids[128]; +#define MAX_ENTROPYUSED 8192 +#define DICE_MINUTXOS 7777 +extern int32_t KOMODO_INSYNC; + + +static uint256 bettxids[MAX_ENTROPYUSED],entropytxids[MAX_ENTROPYUSED][2]; // change to hashtable +static CTransaction betTxs[MAX_ENTROPYUSED]; + +pthread_mutex_t DICE_MUTEX,DICEREVEALED_MUTEX; + +struct dicefinish_utxo { uint256 txid; int32_t vout; }; struct dicefinish_info { - uint256 fundingtxid,bettxid; + struct dicefinish_info *prev,*next; + uint256 fundingtxid,bettxid,entropyused,txid; uint64_t sbits; + int64_t winamount; int32_t iswin; -}; + uint32_t bettxid_ready,revealed; + CTransaction betTx; + std::string rawtx; + uint8_t funcid; +} *DICEFINISH_LIST; -bool mySendrawtransaction(std::string res) +int32_t _dicehash_find(uint256 bettxid) { - CTransaction tx; char str[65]; + int32_t i; + for (i=0; i 64 && is_hexstr((char *)res.c_str(),0) > 64 ) { if ( DecodeHexTx(tx,res) != 0 ) { - fprintf(stderr,"%s\n%s\n",res.c_str(),uint256_str(str,tx.GetHash())); - LOCK(cs_main); - if ( myAddtomempool(tx) != 0 ) + if ( ptr != 0 ) + ptr->txid = tx.GetHash(); + //fprintf(stderr,"%s\n%s\n",res.c_str(),uint256_str(str,tx.GetHash())); + if ( funcid == 'R' || (retval= DiceEntropyUsed(oldbetTx,oldbettxid,entropyused,bettxid,betTx)) >= 0 ) { - RelayTransaction(tx); - fprintf(stderr,"added to mempool and broadcast\n"); - return(true); - } else fprintf(stderr,"error adding to mempool\n"); + //LOCK(cs_main); + if ( myAddtomempool(tx) != 0 ) + { + RelayTransaction(tx); + if ( retval == 0 ) + { + if ( ptr != 0 ) + ptr->revealed = (uint32_t)time(NULL); + pthread_mutex_lock(&DICEREVEALED_MUTEX); + _dicerevealed_add(entropyused,bettxid,betTx); + pthread_mutex_unlock(&DICEREVEALED_MUTEX); + fprintf(stderr,"added.%c to mempool.[%d] and broadcast entropyused.%s bettxid.%s -> %s\n",funcid,i,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str()); + } else fprintf(stderr,"rebroadcast.%c to mempool.[%d] and broadcast entropyused.%s bettxid.%s -> %s\n",funcid,i,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str()); + return(true); + } + else + { + RelayTransaction(tx); + fprintf(stderr,"rebroadcast.%c and clear [%d] and broadcast entropyused.%s bettxid.%s -> %s\n",funcid,i,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str()); + if ( ptr->rawtx.empty() == 0 ) + ptr->rawtx.clear(); + ptr->txid = zeroid; + //fprintf(stderr,"error adding funcid.%c E.%s bet.%s -> %s to mempool, probably Disable replacement feature size.%d\n",funcid,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str(),(int32_t)ptr->rawtx.size()); + } + } else fprintf(stderr,"error duplicate entropyused different bettxid\n"); } else fprintf(stderr,"error decoding hex\n"); } return(false); } -void *dicefinish(void *_ptr) +int32_t dicefinish_utxosget(int32_t &total,struct dicefinish_utxo *utxos,int32_t max,char *coinaddr) { - char str[65],str2[65],name[32]; std::string res; int32_t i,result,duplicate=0; struct dicefinish_info *ptr; - ptr = (struct dicefinish_info *)_ptr; - sleep(3); // wait for bettxid to be in mempool - for (i=0; ibettxid ) + int32_t n = 0; int64_t threshold = 2 * 10000; + total = 0; + std::vector > unspentOutputs; + SetCCunspents(unspentOutputs,coinaddr); + { + LOCK(mempool.cs); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - duplicate = 1; - break; - } - if ( duplicate == 0 ) - { - for (i=0; ifirst.txhash,(int32_t)it->first.index) == 0 ) { - bettxids[i] = ptr->bettxid; - break; + if ( it->second.satoshis < threshold || it->second.satoshis > 10*threshold ) + continue; + total++; + if ( n < max ) + { + if ( utxos != 0 ) + { + utxos[n].txid = it->first.txhash; + utxos[n].vout = (int32_t)it->first.index; + } + n++; + } } - if ( i == sizeof(bettxids)/sizeof(*bettxids) ) - bettxids[rand() % i] = ptr->bettxid; + } } - unstringbits(name,ptr->sbits); - //fprintf(stderr,"duplicate.%d dicefinish.%d %s funding.%s bet.%s\n",duplicate,ptr->iswin,name,uint256_str(str,ptr->fundingtxid),uint256_str(str2,ptr->bettxid)); - if ( duplicate == 0 ) + total -= n; + return(n); +} + +int32_t dice_betspent(char *debugstr,uint256 bettxid) +{ + CSpentIndexValue value,value2; + CSpentIndexKey key(bettxid,0); + CSpentIndexKey key2(bettxid,1); + if ( GetSpentIndex(key,value) != 0 || GetSpentIndex(key2,value2) != 0 ) { - res = DiceBetFinish(&result,0,name,ptr->fundingtxid,ptr->bettxid,ptr->iswin); - if ( result > 0 ) - mySendrawtransaction(res); + //fprintf(stderr,"%s txid.%s already spent\n",debugstr,bettxid.GetHex().c_str()); + return(1); + } + { + //LOCK(mempool.cs); + if ( myIsutxo_spentinmempool(bettxid,0) != 0 || myIsutxo_spentinmempool(bettxid,1) != 0 ) + { + fprintf(stderr,"%s bettxid.%s already spent in mempool\n",debugstr,bettxid.GetHex().c_str()); + return(-1); + } } - free(ptr); return(0); } -void DiceQueue(int32_t iswin,uint64_t sbits,uint256 fundingtxid,uint256 bettxid) +void dicefinish_delete(struct dicefinish_info *ptr) { - struct dicefinish_info *ptr = (struct dicefinish_info *)calloc(1,sizeof(*ptr)); - ptr->fundingtxid = fundingtxid; - ptr->bettxid = bettxid; - ptr->sbits = sbits; - ptr->iswin = iswin; - if ( ptr != 0 && pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,dicefinish,(void *)ptr) != 0 ) + pthread_mutex_lock(&DICE_MUTEX); + _dicehash_clear(ptr->bettxid); + pthread_mutex_unlock(&DICE_MUTEX); + DL_DELETE(DICEFINISH_LIST,ptr); + free(ptr); +} + +void *dicefinish(void *_ptr) +{ + std::vector mypk; struct CCcontract_info *cp,C; char name[32],coinaddr[64],CCaddr[64]; std::string res; int32_t newht,newblock,numblocks,lastheight=0,vin0_needed,n,m,num,iter,result; struct dicefinish_info *ptr,*tmp; uint32_t now; struct dicefinish_utxo *utxos; uint256 hashBlock; CTransaction betTx,finishTx; + mypk = Mypubkey(); + pubkey2addr(coinaddr,mypk.data()); + cp = CCinit(&C,EVAL_DICE); + GetCCaddress(cp,CCaddr,GetUnspendable(cp,0)); + fprintf(stderr,"start dicefinish thread %s CCaddr.%s\n",coinaddr,CCaddr); + if ( (newht= KOMODO_INSYNC) == 0 ) + sleep(7); + sleep(3); + while ( 1 ) { - //fprintf(stderr,"DiceQueue.%d\n",iswin); - } // small memory leak per DiceQueue + if ( newht != 0 && lastheight != newht ) + { + lastheight = newht; + newblock = 1; + fprintf(stderr,"dicefinish process lastheight.%d <- newht.%d\n",lastheight,newht); + } else newblock = 0; + now = (uint32_t)time(NULL); + for (iter=-1; iter<=1; iter+=2) + { + vin0_needed = 0; + DL_FOREACH_SAFE(DICEFINISH_LIST,ptr,tmp) + { + if ( ptr->iswin != iter ) + continue; + if ( ptr->revealed != 0 && now > ptr->revealed+3600 ) + { + fprintf(stderr,"purge %s\n",ptr->bettxid.GetHex().c_str()); + dicefinish_delete(ptr); + continue; + } + if ( ptr->bettxid_ready == 0 ) + { + if ( myGetTransaction(ptr->bettxid,betTx,hashBlock) != 0 && hashBlock != zeroid ) + ptr->bettxid_ready = (uint32_t)time(NULL); + else if ( mytxid_inmempool(ptr->bettxid) != 0 ) + ptr->bettxid_ready = (uint32_t)time(NULL); + } + else if ( myGetTransaction(ptr->bettxid,betTx,hashBlock) == 0 ) + { + fprintf(stderr,"ORPHANED bettxid.%s\n",ptr->bettxid.GetHex().c_str()); + dicefinish_delete(ptr); + continue; + } + else if ( ptr->txid != zeroid ) + { + if ( myGetTransaction(ptr->txid,finishTx,hashBlock) == 0 ) + { + fprintf(stderr,"ORPHANED finish txid.%s\n",ptr->txid.GetHex().c_str()); + if ( ptr->rawtx.empty() == 0 ) + ptr->rawtx.clear(); + ptr->txid = zeroid; + } + } + if ( ptr->bettxid_ready != 0 ) + { + if ( newblock != 0 && ptr->txid != zeroid ) + { + CCduration(numblocks,ptr->txid); + fprintf(stderr,"duration finish txid.%s\n",ptr->txid.GetHex().c_str()); + if ( numblocks == 0 ) + mySenddicetransaction(ptr->rawtx,ptr->entropyused,ptr->bettxid,ptr->betTx,ptr->funcid,ptr); + else continue; + } + if ( ptr->txid == zeroid ) + vin0_needed++; + } + } + if ( vin0_needed > 0 ) + { + num = 0; + //fprintf(stderr,"iter.%d vin0_needed.%d\n",iter,vin0_needed); + utxos = (struct dicefinish_utxo *)calloc(vin0_needed,sizeof(*utxos)); + if ( (n= dicefinish_utxosget(num,utxos,vin0_needed,coinaddr)) > 0 ) + { + //fprintf(stderr,"iter.%d vin0_needed.%d got %d\n",iter,vin0_needed,n); + m = 0; + DL_FOREACH_SAFE(DICEFINISH_LIST,ptr,tmp) + { + if ( ptr->iswin != iter ) + continue; + if ( ptr->revealed != 0 && time(NULL) > ptr->revealed+3600 ) + { + fprintf(stderr,"purge2 %s\n",ptr->bettxid.GetHex().c_str()); + dicefinish_delete(ptr); + continue; + } + if ( ptr->txid != zeroid ) + { + CCduration(numblocks,ptr->txid); + //fprintf(stderr,"numblocks %s %d\n",ptr->txid.GetHex().c_str(),numblocks); + if ( numblocks > 0 ) + continue; + } + if ( ptr->bettxid_ready != 0 && ptr->rawtx.size() == 0 && dice_betspent((char *)"dicefinish",ptr->bettxid) <= 0 && ptr->txid == zeroid ) + { + unstringbits(name,ptr->sbits); + result = 0; + res = DiceBetFinish(ptr->funcid,ptr->entropyused,&result,0,name,ptr->fundingtxid,ptr->bettxid,ptr->iswin,utxos[m].txid,utxos[m].vout); + if ( result > 0 ) + { + ptr->rawtx = res; + mySenddicetransaction(ptr->rawtx,ptr->entropyused,ptr->bettxid,ptr->betTx,ptr->funcid,ptr); + } + else if ( result != -2 ) + { + fprintf(stderr,"error doing the dicefinish %d of %d process %s %s using %s/v%d need %.8f\n",m,n,iter<0?"loss":"win",ptr->bettxid.GetHex().c_str(),utxos[m].txid.GetHex().c_str(),utxos[m].vout,(double)(iter<0 ? 0 : ptr->winamount)/COIN); + if ( ptr->rawtx.empty() == 0 ) + ptr->rawtx.clear(); + ptr->txid = zeroid; + } + if ( ++m >= n ) + break; + } + } + } + else if ( newblock != 0 ) + dicefinish_utxosget(num,0,0,coinaddr); + free(utxos); + if ( newblock != 0 && num < DICE_MINUTXOS ) + { + char *cmd = (char *)malloc(100 * 128); + sprintf(cmd,"./komodo-cli -ac_name=%s sendmany \"\" \"{\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002}\"",ASSETCHAINS_SYMBOL,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr); + fprintf(stderr,"num normal 0.0002 utxos.%d < %d\n",num,DICE_MINUTXOS); + if ( system(cmd) != 0 ) + fprintf(stderr,"system error issuing.(%s)\n",cmd); + free(cmd); + if ( (rand() % 100) == 0 ) + { + fprintf(stderr,"make 0.023 utxos\n"); + if ( system("cc/dapps/sendmany") != 0 ) + fprintf(stderr,"system error issuing.(cc/dapps/sendmany)\n"); + } + } + } + } + if ( (newht= KOMODO_INSYNC) == 0 || newht == lastheight ) + sleep(3); + else usleep(500000); + } + return(0); +} + +void DiceQueue(int32_t iswin,uint64_t sbits,uint256 fundingtxid,uint256 bettxid,CTransaction betTx) +{ + static int32_t didinit; + struct dicefinish_info *ptr; int32_t i,duplicate=0; uint64_t txfee = 10000; + if ( didinit == 0 ) + { + if ( pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,dicefinish,0) == 0 ) + { + pthread_mutex_init(&DICE_MUTEX,NULL); + pthread_mutex_init(&DICEREVEALED_MUTEX,NULL); + didinit = 1; + } + else + { + fprintf(stderr,"error launching dicefinish thread\n"); + return; + } + } + //if ( dice_betspent((char *)"DiceQueue",bettxid) != 0 ) + // return; + pthread_mutex_lock(&DICE_MUTEX); + if ( _dicehash_find(bettxid) == 0 ) + { + _dicehash_add(bettxid); + ptr = (struct dicefinish_info *)calloc(1,sizeof(*ptr)); + ptr->fundingtxid = fundingtxid; + ptr->bettxid = bettxid; + ptr->betTx = betTx; + ptr->sbits = sbits; + ptr->iswin = iswin; + ptr->winamount = betTx.vout[1].nValue * ((betTx.vout[2].nValue - txfee)+1); + DL_APPEND(DICEFINISH_LIST,ptr); + fprintf(stderr,"queued iswin.%d %.8f -> %.8f %s\n",iswin,(double)betTx.vout[1].nValue/COIN,(double)ptr->winamount/COIN,bettxid.GetHex().c_str()); + } + else + { + fprintf(stderr,"DiceQueue status bettxid.%s already in list\n",bettxid.GetHex().c_str()); + //_dicehash_clear(bettxid); + } + pthread_mutex_unlock(&DICE_MUTEX); } CPubKey DiceFundingPk(CScript scriptPubKey) @@ -224,12 +547,15 @@ int32_t dice_5nibbles(uint8_t *fivevals) return(((int32_t)fivevals[0]<<16) + ((int32_t)fivevals[1]<<12) + ((int32_t)fivevals[2]<<8) + ((int32_t)fivevals[3]<<4) + ((int32_t)fivevals[4])); } -uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks,uint256 houseentropy,uint256 bettorentropy) +uint64_t DiceCalc(int64_t bet,int64_t vout2,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks,uint256 houseentropy,uint256 bettorentropy) { - uint8_t buf[64],_house[32],_bettor[32],_hash[32],hash[32],hash16[64]; uint64_t winnings; arith_uint256 house,bettor; char str[65],str2[65]; int32_t i,modval; - if ( odds < 10000 ) + uint8_t buf[64],_house[32],_bettor[32],_hash[32],hash[32],hash16[64]; uint64_t odds,winnings; arith_uint256 house,bettor; char str[65],str2[65]; int32_t i,modval; + if ( vout2 <= 10000 ) + { + fprintf(stderr,"unexpected vout2.%llu\n",(long long)vout2); return(0); - else odds -= 10000; + } + else odds = (vout2 - 10000); if ( bet < minbet || bet > maxbet ) { CCerror = strprintf("bet size violation %.8f",(double)bet/COIN); @@ -242,7 +568,6 @@ uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t fprintf(stderr,"%s\n", CCerror.c_str() ); return(0); } - //fprintf(stderr,"calc house entropy %s vs bettor %s\n",uint256_str(str,houseentropy),uint256_str(str2,bettorentropy)); endiancpy(buf,(uint8_t *)&houseentropy,32); endiancpy(&buf[32],(uint8_t *)&bettorentropy,32); @@ -254,6 +579,7 @@ uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t vcalc_sha256(0,(uint8_t *)&_bettor,buf,64); endiancpy((uint8_t *)&bettor,_bettor,32); winnings = 0; + //fprintf(stderr,"calc house entropy %s vs bettor %s\n",uint256_str(str,*(uint256 *)&house),uint256_str(str2,*(uint256 *)&bettor)); if ( odds > 1 ) { if ( 0 ) @@ -323,8 +649,10 @@ CScript EncodeDiceOpRet(uint8_t funcid,uint64_t sbits,uint256 fundingtxid,uint25 uint8_t DecodeDiceOpRet(uint256 txid,const CScript &scriptPubKey,uint64_t &sbits,uint256 &fundingtxid,uint256 &hash,uint256 &proof) { std::vector vopret; uint8_t *script,e,f,funcid; int64_t minbet,maxbet,maxodds,timeoutblocks; + //script = (uint8_t *)scriptPubKey.data(); + //fprintf(stderr,"decode %02x %02x %02x\n",script[0],script[1],script[2]); GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() > 2 ) + if ( vopret.size() > 2 )//&& script[0] == 0x6a ) { script = (uint8_t *)vopret.data(); if ( script[0] == EVAL_DICE ) @@ -340,7 +668,7 @@ uint8_t DecodeDiceOpRet(uint256 txid,const CScript &scriptPubKey,uint64_t &sbits } else if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> sbits; ss >> fundingtxid; ss >> hash; ss >> proof) != 0 ) { - if ( e == EVAL_DICE && (f == 'B' || f == 'W' || f == 'L' || f == 'T' || f == 'E') ) + if ( e == EVAL_DICE && (f == 'R' || f == 'B' || f == 'W' || f == 'L' || f == 'T' || f == 'E') ) return(f); else fprintf(stderr,"mismatched e.%02x f.(%c)\n",e,f); } @@ -385,7 +713,7 @@ int64_t DiceAmounts(uint64_t &inputs,uint64_t &outputs,struct CCcontract_info *c return eval->Invalid("always should find vin, but didnt"); else { - if ( (assetoshis= IsDicevout(cp,vinTx,tx.vin[i].prevout.n,refsbits,reffundingtxid)) != 0 ) + if ( (assetoshis= IsDicevout(cp,vinTx,(int32_t)tx.vin[i].prevout.n,refsbits,reffundingtxid)) != 0 ) inputs += assetoshis; } } @@ -419,7 +747,7 @@ int32_t DiceIsWinner(uint256 &entropy,uint256 txid,CTransaction tx,CTransaction if ( hentropy == hentropy2 ) { winnings = DiceCalc(tx.vout[1].nValue,tx.vout[2].nValue,minbet,maxbet,maxodds,timeoutblocks,entropy,bettorentropy); - char str[65]; fprintf(stderr,"%s winnings %.8f bet %.8f at odds %d:1\n",uint256_str(str,tx.GetHash()),(double)winnings/COIN,(double)tx.vout[1].nValue/COIN,(int32_t)(tx.vout[2].nValue-10000)); + //char str[65]; fprintf(stderr,"%s winnings %.8f bet %.8f at odds %d:1\n",uint256_str(str,tx.GetHash()),(double)winnings/COIN,(double)tx.vout[1].nValue/COIN,(int32_t)(tx.vout[2].nValue-10000)); //fprintf(stderr,"I am house entropy %.8f entropy.(%s) vs %s -> winnings %.8f\n",(double)vinTx.vout[0].nValue/COIN,uint256_str(str,entropy),uint256_str(str2,hash),(double)winnings/COIN); if ( winnings == 0 ) { @@ -433,7 +761,7 @@ int32_t DiceIsWinner(uint256 &entropy,uint256 txid,CTransaction tx,CTransaction } } else fprintf(stderr,"hentropy != hentropy2\n"); } else fprintf(stderr,"funcid.%c sbits %llx vs %llx cmp.%d\n",funcid,(long long)sbits,(long long)vinsbits,fundingtxid == vinfundingtxid); - } //else fprintf(stderr,"notmine or not CC\n"); + } //else fprintf(stderr,"notmine.%d or not CC.%d\n",DiceIsmine(vinTx.vout[1].scriptPubKey) != 0,vinTx.vout[0].scriptPubKey.IsPayToCryptoCondition() != 0); return(0); } @@ -447,7 +775,7 @@ bool DiceVerifyTimeout(CTransaction &betTx,int32_t timeoutblocks) bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) { - uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64]; + uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,refsbits=0,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64]; numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; @@ -456,7 +784,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) else { txid = tx.GetHash(); - if ( (funcid= DecodeDiceOpRet(txid,tx.vout[numvouts-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 ) + if ( (funcid= DecodeDiceOpRet(txid,tx.vout[numvouts-1].scriptPubKey,refsbits,fundingtxid,hash,proof)) != 0 ) { if ( eval->GetTxUnconfirmed(fundingtxid,fundingTx,hashBlock) == 0 ) return eval->Invalid("cant find fundingtxid"); @@ -465,6 +793,11 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) if ( maxodds > 9999 ) return eval->Invalid("maxodds too big"); fundingPubKey = fundingTx.vout[1].scriptPubKey; + if ( sbits != refsbits ) + { + fprintf(stderr,"VALIDATION ERROR: sbits %llx != refsbits %llx\n",(long long)sbits,(long long)refsbits); + //return eval->Invalid("mismatched diceplan"); + } switch ( funcid ) { case 'F': @@ -503,20 +836,23 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) return eval->Invalid("always should find vin.0, but didnt for bet"); else if ( vinTx.vout[1].scriptPubKey != fundingPubKey ) return eval->Invalid("entropy tx not fundingPubKey for bet"); - else if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,vinTx.vout[tx.vin[0].prevout.n].nValue) == 0 ) + else if ( ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,(int64_t)vinTx.vout[tx.vin[0].prevout.n].nValue) == 0 ) + { + fprintf(stderr,"%s prevout.%d %.8f\n",tx.vin[0].prevout.hash.GetHex().c_str(),(int32_t)tx.vin[0].prevout.n,(double)vinTx.vout[tx.vin[0].prevout.n].nValue/COIN); return eval->Invalid("vout[0] != entropy nValue for bet"); + } else if ( ConstrainVout(tx.vout[1],1,cp->unspendableCCaddr,0) == 0 ) return eval->Invalid("vout[1] constrain violation for bet"); - else if ( tx.vout[2].nValue > txfee+maxodds || tx.vout[2].nValue < txfee ) + else if ( tx.vout[2].nValue > txfee+maxodds || tx.vout[2].nValue <= txfee ) return eval->Invalid("vout[2] nValue violation for bet"); else if ( eval->GetTxUnconfirmed(vinTx.vin[0].prevout.hash,vinofvinTx,hashBlock) == 0 || vinofvinTx.vout.size() < 1 ) return eval->Invalid("always should find vinofvin.0, but didnt for bet"); else if ( vinTx.vin[0].prevout.hash != fundingtxid ) { - if ( vinofvinTx.vout[vinTx.vin[0].prevout.n].scriptPubKey != fundingPubKey ) + if ( (int32_t)vinTx.vin[0].prevout.n < 0 || vinofvinTx.vout[vinTx.vin[0].prevout.n].scriptPubKey != fundingPubKey ) { uint8_t *ptr0,*ptr1; int32_t i; char str[65]; - fprintf(stderr,"bidTx.%s\n",uint256_str(str,txid)); + fprintf(stderr,"betTx.%s\n",uint256_str(str,txid)); fprintf(stderr,"entropyTx.%s v%d\n",uint256_str(str,tx.vin[0].prevout.hash),(int32_t)tx.vin[0].prevout.n); fprintf(stderr,"entropyTx vin0 %s v%d\n",uint256_str(str,vinTx.vin[0].prevout.hash),(int32_t)vinTx.vin[0].prevout.n); ptr0 = (uint8_t *)vinofvinTx.vout[vinTx.vin[0].prevout.n].scriptPubKey.data(); @@ -533,7 +869,13 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) if ( (iswin= DiceIsWinner(entropy,txid,tx,vinTx,hash,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) { // will only happen for fundingPubKey - DiceQueue(iswin,sbits,fundingtxid,txid); + if ( KOMODO_INSYNC != 0 ) + DiceQueue(iswin,sbits,fundingtxid,txid,tx); + } + else + { + //fprintf(stderr,"why does node1 get VALIDATION ERROR: invalid dicebet bettxid %s\n",txid.GetHex().c_str()); + //return eval->Invalid("invalid dicebet bettxid"); } break; // make sure all funding txid are from matching sbits and fundingtxid!! @@ -586,7 +928,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) return eval->Invalid("vout[2] payut mismatch for win/timeout"); else if ( inputs != (outputs + tx.vout[2].nValue) && inputs != (outputs + tx.vout[2].nValue+txfee) ) { - fprintf(stderr,"inputs %.8f != outputs %.8f + %.8f\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[2].nValue/COIN); + fprintf(stderr,"inputs %.8f != outputs %.8f (%.8f %.8f %.8f %.8f)\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[0].nValue/COIN,(double)tx.vout[1].nValue/COIN,(double)tx.vout[2].nValue/COIN,(double)tx.vout[3].nValue/COIN); return eval->Invalid("CC funds mismatch for win/timeout"); } else if ( tx.vout[3].scriptPubKey != fundingPubKey ) @@ -610,8 +952,29 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) else if ( DiceVerifyTimeout(vinTx,timeoutblocks) == 0 ) return eval->Invalid("invalid timeout claim for timeout"); break; + case 'R': + if ( eval->GetTxUnconfirmed(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("always should find vin.0, but didnt for refund"); + else if ( vinTx.vout[tx.vin[0].prevout.n].scriptPubKey != fundingPubKey ) + { + char fundingaddr[64],cmpaddr[64]; + Getscriptaddress(fundingaddr,fundingPubKey); + Getscriptaddress(cmpaddr,vinTx.vout[tx.vin[0].prevout.n].scriptPubKey); + if ( strcmp(cmpaddr,fundingaddr) != 0 ) + { + fprintf(stderr,"cmpaddr.%s != fundingaddr.%s\n",cmpaddr,fundingaddr); + return eval->Invalid("vin.0 not from fundingPubKey for refund"); + } + } + if ( (rand() % 1000) == 0 ) + fprintf(stderr,"add more validation for refunds\n"); + break; + default: + fprintf(stderr,"illegal dice funcid.(%c)\n",funcid); + return eval->Invalid("unexpected dice funcid"); + break; } - } + } else return eval->Invalid("unexpected dice missing funcid"); return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); } return(true); @@ -619,15 +982,18 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint64_t total,int32_t maxinputs,uint64_t refsbits,uint256 reffundingtxid) { - char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hash,proof,hashBlock,fundingtxid; CTransaction tx; int32_t j,vout,n = 0; uint8_t funcid; + char coinaddr[64],str[65]; uint64_t threshold,sbits,nValue,totalinputs = 0; uint256 txid,hash,proof,hashBlock,fundingtxid; CTransaction tx; int32_t j,vout,n = 0; uint8_t funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + if ( maxinputs > 0 ) + threshold = total / maxinputs; + else threshold = total / 64; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; - if ( it->second.satoshis < 1000000 ) + if ( vout != 0 || it->second.satoshis < threshold ) continue; //fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); for (j=0; j 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) { if ( (funcid= DecodeDiceOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 ) { char str[65],sstr[16]; unstringbits(sstr,sbits); - fprintf(stderr,"(%c) %.8f %s %s\n",funcid,(double)tx.vout[0].nValue/COIN,sstr,uint256_str(str,txid)); if ( sbits == refsbits && (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) { if ( funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T' ) { if ( total != 0 && maxinputs != 0 ) + { + fprintf(stderr,"use (%c) %.8f %s %s/v%d\n",funcid,(double)tx.vout[0].nValue/COIN,sstr,uint256_str(str,txid),vout); mtx.vin.push_back(CTxIn(txid,vout,CScript())); + } totalinputs += it->second.satoshis; n++; if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) @@ -662,11 +1030,11 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid, int32_t &entropytxs,bool random) { - char coinaddr[64],str[65]; uint64_t sbits; int64_t nValue,totalinputs = 0; uint256 hash,txid,proof,hashBlock,fundingtxid; CScript fundingPubKey; CTransaction tx,vinTx; int32_t vout,first=0,n=0,i=0; uint8_t funcid; + char coinaddr[64],str[65]; uint64_t sbits; int64_t nValue,sum,totalinputs = 0; uint256 hash,txid,proof,hashBlock,fundingtxid; CScript fundingPubKey; CTransaction tx,vinTx; int32_t vout,first=0,n=0,i=0,pendingbets=0; uint8_t funcid; std::vector > unspentOutputs; entropyval = 0; entropytxid = zeroid; - if ( GetTransaction(reffundingtxid,tx,hashBlock,false) != 0 && tx.vout.size() > 1 && ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) != 0 ) + if ( myGetTransaction(reffundingtxid,tx,hashBlock) != 0 && tx.vout.size() > 1 && ConstrainVout(tx.vout[0],1,cp->unspendableCCaddr,0) != 0 ) { fundingPubKey = tx.vout[1].scriptPubKey; } else return(0); @@ -674,10 +1042,15 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit SetCCunspents(unspentOutputs,coinaddr); entropyval = 0; int loops = 0; - int numtxs = unspentOutputs.size()/2; - int startfrom = rand()%numtxs; + int numtxs = unspentOutputs.size()/8; + int startfrom = rand() % (numtxs+1); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( vout != 0 ) + continue; + sum += it->second.satoshis; loops++; if (random) { if ( loops < startfrom ) @@ -685,49 +1058,54 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit if ( (rand() % 100) < 90 ) continue; } - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 ) //we want consensus safe results myIsutxo_spentinmempool(txid,vout) == 0 ) { - //char str[65],str2[65]; - if ( (funcid= DecodeDiceOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 ) + if ( (funcid= DecodeDiceOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 && sbits == refsbits ) { + if ( funcid == 'B' ) + { + pendingbets++; + fprintf(stderr,"%d: %s/v%d (%c %.8f) %.8f %.8f\n",n,uint256_str(str,txid),vout,funcid,(double)it->second.satoshis/COIN,(double)totalinputs/COIN,(double)sum/COIN); + } if ( (funcid == 'F' && reffundingtxid == txid) || reffundingtxid == fundingtxid ) { - if ( refsbits == sbits && (nValue= IsDicevout(cp,tx,vout,refsbits,reffundingtxid)) > 10000 && (funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T') ) + if ( refsbits == sbits && (nValue= IsDicevout(cp,tx,vout,refsbits,reffundingtxid)) >= 10000 && (funcid == 'F' || funcid == 'E' || funcid == 'W' || funcid == 'L' || funcid == 'T') ) { - //fprintf(stderr,"%s.(%c %.8f) ",uint256_str(str,txid),funcid,(double)nValue/COIN); - if ( funcid != 'F' && funcid != 'T' ) + if ( funcid == 'L' || funcid == 'W' || funcid == 'E' ) n++; totalinputs += nValue; if ( first == 0 && (funcid == 'E' || funcid == 'W' || funcid == 'L') ) { //fprintf(stderr,"check first\n"); - if ( fundingPubKey == tx.vout[1].scriptPubKey ) + if ( tx.vout.size() > 1 && fundingPubKey == tx.vout[1].scriptPubKey ) { - if ( funcid == 'E' && fundingtxid != tx.vin[0].prevout.hash ) + if ( myGetTransaction(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 || (int32_t)tx.vin[0].prevout.n < 0 ) { - if ( GetTransaction(tx.vin[0].prevout.hash,vinTx,hashBlock,false) == 0 ) - { - fprintf(stderr,"cant find entropy vin0 %s or vin0prev %d vouts[%d]\n",uint256_str(str,tx.vin[0].prevout.hash),tx.vin[0].prevout.n,(int32_t)vinTx.vout.size()); - continue; - } - if ( vinTx.vout[tx.vin[0].prevout.n].scriptPubKey != fundingPubKey ) - { - uint8_t *ptr0,*ptr1; int32_t i; char str[65]; - ptr0 = (uint8_t *)vinTx.vout[tx.vin[0].prevout.n].scriptPubKey.data(); - ptr1 = (uint8_t *)fundingPubKey.data(); - for (i=0; i 1 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 ) + if ( myGetTransaction(fundingtxid,tx,hashBlock) != 0 && tx.vout.size() > 1 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 ) { if ( DecodeDiceFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,sbits,minbet,maxbet,maxodds,timeoutblocks) == 'F' && sbits == refsbits ) { @@ -785,7 +1163,7 @@ bool DicePlanExists(CScript &fundingPubKey,uint256 &fundingtxid,struct CCcontrac txid = it->first.txhash; if ( fundingtxid != zeroid && txid != fundingtxid ) continue; - if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 ) + if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && ConstrainVout(tx.vout[0],1,CCaddr,0) != 0 ) { if ( DecodeDiceFundingOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,sbits,minbet,maxbet,maxodds,timeoutblocks) == 'F' ) { @@ -824,7 +1202,7 @@ struct CCcontract_info *Diceinit(CScript &fundingPubKey,uint256 reffundingtxid,s UniValue DiceInfo(uint256 diceid) { UniValue result(UniValue::VOBJ); CPubKey dicepk; uint256 hashBlock,entropytxid; CTransaction vintx; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t sbits,funding,entropyval; char str[67],numstr[65]; struct CCcontract_info *cp,C; - if ( GetTransaction(diceid,vintx,hashBlock,false) == 0 ) + if ( myGetTransaction(diceid,vintx,hashBlock) == 0 ) { fprintf(stderr,"cant find fundingtxid\n"); ERR_RESULT("cant find fundingtxid"); @@ -865,7 +1243,7 @@ UniValue DiceList() for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { txid = it->first.txhash; - if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) + if ( myGetTransaction(txid,vintx,hashBlock) != 0 ) { if ( vintx.vout.size() > 0 && DecodeDiceFundingOpRet(vintx.vout[vintx.vout.size()-1].scriptPubKey,sbits,minbet,maxbet,maxodds,timeoutblocks) != 0 ) { @@ -879,7 +1257,7 @@ UniValue DiceList() std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks) { CMutableTransaction mtx; uint256 zero; CScript fundingPubKey; CPubKey mypk,dicepk; int64_t a,b,c,d; uint64_t sbits; struct CCcontract_info *cp,C; - if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 1 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 ) + if ( funds < 0 || minbet < 0 || maxbet < 0 || maxodds < 2 || maxodds > 9999 || timeoutblocks < 0 || timeoutblocks > 1440 ) { CCerror = "invalid parameter error"; fprintf(stderr,"%s\n", CCerror.c_str() ); @@ -936,7 +1314,7 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6 } if ( scriptPubKey == fundingPubKey ) { - if ( AddNormalinputs(mtx,mypk,amount+2*txfee,60) > 0 ) + if ( AddNormalinputs(mtx,mypk,amount+2*txfee,1) > 0 ) { hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash); mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,dicepk)); @@ -953,24 +1331,26 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6 return(""); } -std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds, std::string &error) +std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds) { CMutableTransaction mtx; CScript fundingPubKey; CPubKey mypk,dicepk; uint64_t sbits,entropyval; int64_t funding,minbet,maxbet,maxodds,timeoutblocks; uint256 entropytxid,entropy,hentropy; struct CCcontract_info *cp,C; if ( bet < 0 ) { - error = "bet must be positive"; + CCerror = "bet must be positive"; return(""); } - if ( odds < 1 || odds > 9999 ) + if ( odds < 2 || odds > 9999 ) { - error = "odds must be between 1 and 9999"; + CCerror = "odds must be between 2 and 9999"; return(""); } - if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) + if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) { + CCerror = "error in Diceinit"; return(""); + } if ( bet < minbet || bet > maxbet || odds > maxodds ) { - error = strprintf("Dice plan %s illegal bet %.8f: minbet %.8f maxbet %.8f or odds %d vs max.%d\n",planstr,(double)bet/COIN,(double)minbet/COIN,(double)maxbet/COIN,(int32_t)odds,(int32_t)maxodds); + CCerror = strprintf("Dice plan %s illegal bet %.8f: minbet %.8f maxbet %.8f or odds %d vs max.%d\n",planstr,(double)bet/COIN,(double)minbet/COIN,(double)maxbet/COIN,(int32_t)odds,(int32_t)maxodds); return(""); } int32_t entropytxs=0,emptyvar=0; @@ -979,12 +1359,12 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet if ( ( funding >= 2*bet*odds+txfee && entropyval != 0 ) ) { if ( entropytxs < 100 ) { - error = "Your dealer is broke, find a new casino."; + CCerror = "Your dealer is broke, find a new casino."; return(""); } if ( myIsutxo_spentinmempool(entropytxid,0) != 0 ) { - error = "entropy txid is spent"; + CCerror = "entropy txid is spent"; return(""); } mtx.vin.push_back(CTxIn(entropytxid,0,CScript())); @@ -995,19 +1375,21 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet mtx.vout.push_back(MakeCC1vout(cp->evalcode,bet,dicepk)); mtx.vout.push_back(CTxOut(txfee+odds,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeDiceOpRet('B',sbits,fundingtxid,entropy,zeroid))); - } else error = "cant find enough normal inputs for %.8f, plan funding %.8f\n"; + } else CCerror = "cant find enough normal inputs for %.8f, plan funding %.8f\n"; } if ( entropyval == 0 && funding != 0 ) - error = "cant find dice entropy inputs"; + CCerror = "cant find dice entropy inputs"; else - error = "cant find dice input"; + CCerror = "cant find dice input"; return(""); } -std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout) +std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout,uint256 vin0txid,int32_t vin0vout) { - CMutableTransaction mtx; CScript scriptPubKey,fundingPubKey; CTransaction betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs=0,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; uint8_t funcid=0; int32_t iswin=0; uint64_t entropyval,sbits; + CMutableTransaction mtx; CScript scriptPubKey,fundingPubKey; CTransaction oldbetTx,betTx,entropyTx; uint256 hentropyproof,entropytxid,hashBlock,bettorentropy,entropy,hentropy,oldbettxid; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int64_t inputs=0,CCchange=0,odds,fundsneeded,minbet,maxbet,maxodds,timeoutblocks; int32_t retval,iswin=0; uint64_t entropyval,sbits; + entropyused = zeroid; *resultp = 0; + funcid = 0; //char str[65]; fprintf(stderr,"DiceBetFinish.%s %s\n",planstr,uint256_str(str,bettxid)); if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) { @@ -1016,7 +1398,7 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 return(""); } fundingpk = DiceFundingPk(fundingPubKey); - if ( winlosetimeout != 0 ) + if ( winlosetimeout != 0 ) // must be dealernode { scriptPubKey = CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG; if ( scriptPubKey != fundingPubKey ) @@ -1025,47 +1407,89 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 winlosetimeout = 0; } } - if ( AddNormalinputs(mtx,mypk,txfee,1) == 0 ) - { - CCerror = "no txfee inputs for win/lose"; - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); - } - if ( GetTransaction(bettxid,betTx,hashBlock,false) != 0 && GetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock,false) != 0 ) + if ( myGetTransaction(bettxid,betTx,hashBlock) != 0 && myGetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock) != 0 ) { + entropytxid = betTx.vin[0].prevout.hash; + /*if ( dice_betspent((char *)"DiceBetFinish",bettxid) != 0 ) + { + CCerror = "bettxid already spent"; + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + }*/ bettorentropy = DiceGetEntropy(betTx,'B'); if ( winlosetimeout == 0 || (iswin= DiceIsWinner(hentropyproof,bettxid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) { - if ( winlosetimeout != 0 ) - winlosetimeout = iswin; - if ( iswin == winlosetimeout ) + if ( vin0txid == zeroid || vin0vout < 0 ) { - if ( myIsutxo_spentinmempool(bettxid,0) != 0 || myIsutxo_spentinmempool(bettxid,1) != 0 ) + if ( AddNormalinputs(mtx,mypk,2*txfee,1) == 0 ) // must be a single vin!! { - CCerror = "bettxid already spent"; + CCerror = "no txfee inputs for win/lose"; fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } + } + else + { + //fprintf(stderr,"use vin0 %s/%d\n",vin0txid.GetHex().c_str(),vin0vout); + mtx.vin.push_back(CTxIn(vin0txid,vin0vout,CScript())); + } + if ( winlosetimeout != 0 ) // dealernode + { + entropyused = hentropyproof; + /*if ( iswin == 0 ) + { + retval = -1; + fprintf(stderr,"invalid dicebet %s\n",bettxid.GetHex().c_str()); + } else retval = 0;*/ + if ( (retval= DiceEntropyUsed(oldbetTx,oldbettxid,entropyused,bettxid,betTx)) != 0 ) + { + if ( retval < 0 ) + { + fprintf(stderr,"orphan that reveals entropy, generate refund tx with proofs\n"); + // make sure we dont refund wrong amounts + mtx.vin.push_back(CTxIn(bettxid,0,CScript())); + mtx.vin.push_back(CTxIn(bettxid,1,CScript())); + funcid = 'R'; + mtx.vout.push_back(CTxOut(betTx.vout[0].nValue,fundingPubKey)); + mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); + mtx.vout.push_back(CTxOut(betTx.vout[1].nValue,betTx.vout[2].scriptPubKey)); + *resultp = 1; + return(FinalizeCCTx(0,cp,mtx,fundingpk,txfee,EncodeDiceOpRet(funcid,sbits,fundingtxid,entropyused,oldbettxid))); // need to change opreturn to include oldbetTx to allow validation + } + else + { + CCerror = "DiceBetFinish: duplicate betTx"; + *resultp = -2; // demote error to warning + } + //fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } + //fprintf(stderr,"set winlosetimeout %d <- %d\n",winlosetimeout,iswin); + if ( (winlosetimeout= iswin) > 0 ) + funcid = 'W'; + else funcid = 'L'; + } + if ( iswin == winlosetimeout ) // dealernode and normal node paths should always get here + { //fprintf(stderr,"iswin.%d matches\n",iswin); mtx.vin.push_back(CTxIn(bettxid,0,CScript())); mtx.vin.push_back(CTxIn(bettxid,1,CScript())); - if ( iswin == 0 ) + if ( iswin == 0 && funcid != 'L' && funcid != 'W' ) // normal node path { - funcid = 'T'; if ( DiceVerifyTimeout(betTx,timeoutblocks) == 0 ) // hasnt timed out yet { return(""); } else { + funcid = 'T'; hentropy = hentropyproof = zeroid; iswin = 1; + fprintf(stderr,"set timeout win T\n"); } } - if ( iswin > 0 ) + if ( iswin > 0 && funcid != 0 ) // dealernode 'W' or normal node 'T' path { - if ( funcid != 'T' ) - funcid = 'W'; odds = (betTx.vout[2].nValue - txfee); if ( odds < 1 || odds > maxodds ) { @@ -1077,28 +1501,37 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundsneeded = txfee + (odds+1)*betTx.vout[1].nValue; if ( CCchange >= fundsneeded ) CCchange -= fundsneeded; - else if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,60,sbits,fundingtxid)) > 0 ) + else if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,1,sbits,fundingtxid)) >= fundsneeded ) { if ( inputs > fundsneeded ) CCchange += (inputs - fundsneeded); } else { - CCerror = strprintf("not enough inputs for %.8f\n",(double)fundsneeded/COIN); - fprintf(stderr,"%s\n", CCerror.c_str() ); - return(""); + if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,60,sbits,fundingtxid)) > 0 ) + { + if ( inputs > fundsneeded ) + CCchange += (inputs - fundsneeded); + } + else + { + CCerror = strprintf("not enough inputs for %.8f\n",(double)fundsneeded/COIN); + fprintf(stderr,"%s\n", CCerror.c_str() ); + return(""); + } } mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dicepk)); mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); mtx.vout.push_back(CTxOut((odds+1) * betTx.vout[1].nValue,betTx.vout[2].scriptPubKey)); } - else + else // dealernode 'L' path { funcid = 'L'; mtx.vout.push_back(MakeCC1vout(cp->evalcode,betTx.vout[0].nValue + betTx.vout[1].nValue,dicepk)); mtx.vout.push_back(CTxOut(txfee,fundingPubKey)); } - if ( winlosetimeout != 0 ) + //fprintf(stderr,"make tx.%c\n",funcid); + if ( funcid == 'L' || funcid == 'W' ) // dealernode only hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash); *resultp = 1; //char str[65],str2[65]; @@ -1117,14 +1550,15 @@ std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 return("couldnt find bettx or entropytx"); } -double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,std::string &error) +double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid) { - CScript fundingPubKey,scriptPubKey; CTransaction spenttx,betTx; uint256 hash,proof,txid,hashBlock,spenttxid; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int32_t i,result,vout,n=0; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t sbits; char coinaddr[64]; std::string res; - if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) + CScript fundingPubKey,scriptPubKey; CTransaction spenttx,betTx,entropyTx; uint256 hentropyproof,entropyused,hash,proof,txid,hashBlock,spenttxid,bettorentropy; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int32_t i,flag,win,loss,duplicate=0,result,iswin,vout,n=0; int64_t minbet,maxbet,maxodds,timeoutblocks,sum=0; uint64_t sbits,refsbits; char coinaddr[64]; std::string res; uint8_t funcid; + if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,refsbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) { - error = "Diceinit error in status"; + CCerror = "Diceinit error in status"; return(0.); } + win = loss = 0; fundingpk = DiceFundingPk(fundingPubKey); scriptPubKey = CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG; GetCCaddress(cp,coinaddr,dicepk); @@ -1136,29 +1570,66 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx { txid = it->first.txhash; vout = (int32_t)it->first.index; - if ( GetTransaction(txid,betTx,hashBlock,false) != 0 && betTx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 ) + if ( vout != 0 ) + continue; + sum += it->second.satoshis; + if ( myGetTransaction(txid,betTx,hashBlock) != 0 && betTx.vout.size() >= 4 && betTx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 ) { - if ( DecodeDiceOpRet(txid,betTx.vout[betTx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof) == 'B' ) + if ( DecodeDiceOpRet(txid,betTx.vout[betTx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof) == 'B' && sbits == refsbits ) { - res = DiceBetFinish(&result,txfee,planstr,fundingtxid,txid,scriptPubKey == fundingPubKey); - if ( result > 0 ) + if ( myGetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock) != 0 ) { - mySendrawtransaction(res); - n++; - } else - { - error = res; - } + flag = 0; + if ( scriptPubKey == fundingPubKey ) + { + bettorentropy = DiceGetEntropy(betTx,'B'); + if ( (iswin= DiceIsWinner(hentropyproof,txid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) + { + if ( iswin > 0 ) + win++; + else if ( iswin < 0 ) + loss++; + n++; + DiceQueue(iswin,sbits,fundingtxid,txid,betTx); + } //else flag = 1; + } + if ( flag != 0 || scriptPubKey != fundingPubKey ) + { + if ( flag != 0 ) + fprintf(stderr,"illegal bettxid %d: iswin.%d W.%d L.%d %s/v%d (%c %.8f) %.8f\n",n,iswin,win,loss,txid.GetHex().c_str(),vout,funcid,(double)it->second.satoshis/COIN,(double)sum/COIN); + res = DiceBetFinish(funcid,entropyused,&result,txfee,planstr,fundingtxid,txid,scriptPubKey == fundingPubKey,zeroid,-1); + if ( result > 0 ) + { + mySenddicetransaction(res,entropyused,txid,betTx,funcid,0); + n++; + } + } + } else fprintf(stderr,"bettxid.%s cant find entropyTx.%s\n",txid.GetHex().c_str(),betTx.vin[0].prevout.hash.GetHex().c_str()); } } } - if ( 0 && scriptPubKey == fundingPubKey ) + if ( scriptPubKey == fundingPubKey ) { - for (i=0; i<=n; i++) + CTransaction tx; uint64_t entropyval; uint256 entropytxid; int32_t entropytxs; + DicePlanFunds(entropyval,entropytxid,refsbits,cp,dicepk,fundingtxid,entropytxs,false); + if ( entropytxs < DICE_MINUTXOS ) { - res = DiceAddfunding(txfee,planstr,fundingtxid,COIN); - fprintf(stderr,"ENTROPY tx:\n"); - mySendrawtransaction(res); + for (i=0; i 64 && is_hexstr((char *)res.c_str(),0) > 64 ) + { + if ( DecodeHexTx(tx,res) != 0 ) + { + //LOCK(cs_main); + if ( myAddtomempool(tx) != 0 ) + { + fprintf(stderr,"ENTROPY %s: %d of %d\n",tx.GetHash().GetHex().c_str(),i,DICE_MINUTXOS - entropytxs); + RelayTransaction(tx); + } else break; + } else break; + } else break; + } } } return(n); @@ -1169,35 +1640,35 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx if ( (vout= myIsutxo_spent(spenttxid,bettxid,1)) >= 0 ) { //fprintf(stderr,"bettx is spent\n"); - if ( GetTransaction(bettxid,betTx,hashBlock,false) != 0 && GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() > 2 ) + if ( myGetTransaction(bettxid,betTx,hashBlock) != 0 && myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() > 2 ) { //fprintf(stderr,"found spenttxid %s\n",uint256_str(str,spenttxid)); if ( betTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 || betTx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 || spenttx.vout[2].scriptPubKey != betTx.vout[2].scriptPubKey ) return(0.); else return((double)spenttx.vout[2].nValue/COIN); } - error = "couldnt find bettx or spenttx %s\n",uint256_str(str,spenttxid); + CCerror = "couldnt find bettx or spenttx %s\n",uint256_str(str,spenttxid); return(-1.); } else if ( scriptPubKey == fundingPubKey ) - res = DiceBetFinish(&result,txfee,planstr,fundingtxid,bettxid,1); - else res = DiceBetFinish(&result,txfee,planstr,fundingtxid,bettxid,0); + res = DiceBetFinish(funcid,entropyused,&result,txfee,planstr,fundingtxid,bettxid,1,zeroid,-1); + else res = DiceBetFinish(funcid,entropyused,&result,txfee,planstr,fundingtxid,bettxid,0,zeroid,-1); if ( result > 0 ) { - mySendrawtransaction(res); + mySenddicetransaction(res,entropyused,bettxid,betTx,funcid,0); sleep(1); if ( (vout= myIsutxo_spent(spenttxid,bettxid,1)) >= 0 ) { - if ( GetTransaction(txid,betTx,hashBlock,false) != 0 && GetTransaction(spenttxid,spenttx,hashBlock,false) != 0 && spenttx.vout.size() >= 2 ) + if ( myGetTransaction(txid,betTx,hashBlock) != 0 && myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() >= 2 ) { - if ( betTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 || betTx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 || spenttx.vout[2].scriptPubKey != betTx.vout[2].scriptPubKey ) + if ( funcid == 'L' )//betTx.vout[1].scriptPubKey.IsPayToCryptoCondition() == 0 || betTx.vout[2].scriptPubKey.IsPayToCryptoCondition() != 0 || spenttx.vout[2].scriptPubKey != betTx.vout[2].scriptPubKey ) //if ( spenttx.vout[2].scriptPubKey == fundingPubKey || ((uint8_t *)spenttx.vout[2].scriptPubKey.data())[0] == 0x6a ) return(0.); else return((double)spenttx.vout[2].nValue/COIN); } else return(0.); } - error = "didnt find dicefinish tx"; - } else error = res; + CCerror = "didnt find dicefinish tx"; + } else CCerror = res; return(-1.); } return(0.); diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index 676cb152c..3bf8a3476 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -142,14 +142,17 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + threshold = total/maxinputs; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; + if ( it->second.satoshis < threshold ) + continue; //char str[65]; fprintf(stderr,"check %s/v%d %.8f`\n",uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); // no need to prevent dup if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index 41601b437..9f9accbb5 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -122,6 +122,7 @@ bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) int64_t AddFSMInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { + // add threshold check char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 26c800a98..a9fc6a4cd 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -143,7 +143,7 @@ */ -int32_t GatewaysAddQueue(std::string coin,uint256 txid,CScript scriptPubKey,int64_t nValue) +void GatewaysAddQueue(std::string coin,uint256 txid,CScript scriptPubKey,int64_t nValue) { char destaddr[64],str[65]; Getscriptaddress(destaddr,scriptPubKey); @@ -332,15 +332,18 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction & int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 refassetid,int64_t total,int32_t maxinputs) { - char coinaddr[64],destaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 assetid,txid,hashBlock; std::vector origpubkey; std::vector vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid; + char coinaddr[64],destaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 assetid,txid,hashBlock; std::vector origpubkey; std::vector vopret; CTransaction vintx; int32_t j,vout,n = 0; uint8_t evalcode,funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + threshold = total/maxinputs; fprintf(stderr,"check %s for gateway inputs\n",coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; + if ( it->second.satoshis < threshold ) + continue; for (j=0; j origpubkey; CTransaction vintx; int32_t n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); @@ -295,6 +296,7 @@ std::string LottoCreate(uint64_t txfee,char *planstr,int64_t funding,int32_t tic mtx.vout.push_back(MakeCC1vout(EVAL_LOTTO,funding,lottopk)); return(FinalizeCCTx(0,cp,mtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_LOTTO << (uint8_t)'F' << sbits << ticketsize << odds << firstheight << period << hentropy))); } + return(""); } std::string LottoTicket(uint64_t txfee,uint256 lottoid,int64_t numtickets) diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 0c7d9e6e2..8fe1fe6d3 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -440,6 +440,7 @@ int64_t correlate_price(int32_t height,int64_t *prices,int32_t n) for (i=0; i %llu ht.%d\n",(long long)price,height); + return(price); } int64_t OracleCorrelatedPrice(int32_t height,std::vector origprices) @@ -650,8 +651,12 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t } return eval->Invalid("unexpected OraclesValidate 'D' tx invalid"); break; + default: + fprintf(stderr,"illegal oracles funcid.(%c)\n",script[1]); + return eval->Invalid("unexpected OraclesValidate funcid"); + break; } - } + } else return eval->Invalid("unexpected oracles missing funcid"); return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); } return(true); diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 6cd751b8d..f3cd40ba2 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -115,6 +115,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { + // add threshold check char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index d9074bd49..21e371b4a 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -122,6 +122,7 @@ bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx) int64_t AddPegsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) { + // add threshold check char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 6ee0364e2..3d69ceec1 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -129,6 +129,7 @@ bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx int64_t AddTokensInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,char *destaddr,uint256 tolenid,int64_t total,int32_t maxinputs) { + // add threshold check int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; SetCCunspents(unspentOutputs,destaddr); diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index a70071af9..649a9a9e6 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -287,8 +287,12 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t return eval->Invalid("unlock tx vout.2 isnt 0"); preventCCvouts = 1; break; + default: + fprintf(stderr,"illegal rewards funcid.(%c)\n",funcid); + return eval->Invalid("unexpected rewards funcid"); + break; } - } + } else return eval->Invalid("unexpected rewards missing funcid"); return(PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts)); } return(true); @@ -325,15 +329,16 @@ static uint64_t myIs_unlockedtx_inmempool(uint256 &txid,int32_t &vout,uint64_t r // 'L' vs 'F' and 'A' int64_t AddRewardsInputs(CScript &scriptPubKey,uint64_t maxseconds,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs,uint64_t refsbits,uint256 reffundingtxid) { - char coinaddr[64],str[65]; uint64_t sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t numblocks,j,vout,n = 0; uint8_t funcid; + char coinaddr[64],str[65]; uint64_t threshold,sbits,nValue,totalinputs = 0; uint256 txid,hashBlock,fundingtxid; CTransaction tx; int32_t numblocks,j,vout,n = 0; uint8_t funcid; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); SetCCunspents(unspentOutputs,coinaddr); + threshold = total/maxinputs; for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; - if ( it->second.satoshis < 1000000 ) + if ( it->second.satoshis < threshold ) continue; //fprintf(stderr,"(%s) %s/v%d %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN); for (j=0; j origpubkey; CTransaction vintx; int32_t vout,n = 0; std::vector > unspentOutputs; GetCCaddress(cp,coinaddr,pk); diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index c913c7ea0..1dd3fe706 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -69,6 +69,7 @@ int CurrentEpoch(int nHeight, const Consensus::Params& params) { return idxInt; } } + return(0); // jl777 seems the right value to return } uint32_t CurrentEpochBranchId(int nHeight, const Consensus::Params& params) { diff --git a/src/komodo.h b/src/komodo.h index e303c2bac..efbc4ddad 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -112,7 +112,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char errs++; if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) errs++; - if ( 1 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } else @@ -257,7 +257,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) errs++; - if ( 1 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } else diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 73a49e10c..76216efee 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1164,7 +1164,7 @@ int8_t komodo_segid(int32_t nocache,int32_t height) return(segid); } -int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) { static uint8_t prevhashbuf[100]; static int32_t prevheight; int32_t i; diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 379224b48..400ded593 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1380,7 +1380,8 @@ void komodo_passport_iteration() } if ( komodo_chainactive_timestamp() > lastinterest ) { - komodo_interestsum(); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + komodo_interestsum(); komodo_longestchain(); lastinterest = komodo_chainactive_timestamp(); } diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 1ebfdd16c..6d0b10328 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -58,7 +58,7 @@ uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; uint64_t PENDING_KOMODO_TX; extern int32_t KOMODO_LOADINGBLOCKS; unsigned int MAX_BLOCK_SIGOPS = 20000; diff --git a/src/main.cpp b/src/main.cpp index 837e380de..115920264 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1331,7 +1331,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } auto verifier = libzcash::ProofVerifier::Strict(); - if ( komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { //fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); return error("AcceptToMemoryPool: komodo_validate_interest failed"); @@ -1681,8 +1681,10 @@ bool myAddtomempool(CTransaction &tx) { CValidationState state; CTransaction Ltx; bool fMissingInputs,fOverrideFees = false; if ( mempool.lookup(tx.GetHash(),Ltx) == 0 ) + { + //fprintf(stderr,"call AcceptToMemoryPool\n"); return(AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)); - else return(true); + } else return(true); } bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) @@ -3580,7 +3582,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); if ( KOMODO_LONGESTCHAIN != 0 && pindexNew->nHeight >= KOMODO_LONGESTCHAIN ) - KOMODO_INSYNC = 1; + KOMODO_INSYNC = (int32_t)pindexNew->nHeight; else KOMODO_INSYNC = 0; //fprintf(stderr,"connect.%d insync.%d\n",(int32_t)pindexNew->nHeight,KOMODO_INSYNC); if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_INSYNC != 0 ) diff --git a/src/miner.cpp b/src/miner.cpp index fcc8d6127..3b245b286 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -335,6 +335,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) //fprintf(stderr,"dont have inputs\n"); continue; } + if ( 0 ) { CValidationState state; auto verifier = libzcash::ProofVerifier::Disabled(); @@ -939,7 +940,7 @@ void static BitcoinMiner() { fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height); if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN ) - KOMODO_INSYNC = 1; + KOMODO_INSYNC = Mining_height; sleep(3); } // Hash state diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 815860c7d..868431f6f 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -378,6 +378,18 @@ bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) return(false); } +bool mytxid_inmempool(uint256 txid) +{ + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + if ( txid == hash ) + return(true); + } + return(false); +} + UniValue mempoolToJSON(bool fVerbose = false) { if (fVerbose) diff --git a/src/rpccrosschain.cpp b/src/rpccrosschain.cpp index 09f1b21d1..2059ab452 100644 --- a/src/rpccrosschain.cpp +++ b/src/rpccrosschain.cpp @@ -50,7 +50,9 @@ UniValue assetchainproof(const UniValue& params, bool fHelp) UniValue crosschainproof(const UniValue& params, bool fHelp) { - + UniValue ret(UniValue::VOBJ); + fprintf(stderr,"crosschainproof needs to be implemented\n"); + return(ret); } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index db6ffbc14..97bf5001d 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -179,6 +179,8 @@ int32_t komodo_longestchain() //fprintf(stderr,"komodo_longestchain iter.%d\n",n); CNodeStateStats statestats; bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); + if ( statestats.nSyncHeight < 0 ) + continue; ht = 0; if ( stats.nStartingHeight > ht ) ht = stats.nStartingHeight; @@ -190,7 +192,6 @@ int32_t komodo_longestchain() maxheight = ht, num = 1; else if ( ht > maxheight*0.99 ) num++; - n++; if ( ht > height ) height = ht; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d41d77056..393545a63 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -242,7 +242,7 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; UniValue stop(const UniValue& params, bool fHelp) { - char buf[64]; + char buf[66+128]; // Accept the deprecated and ignored 'detach' boolean argument if (fHelp || params.size() > 1) throw runtime_error( diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 6ca3c8ed4..5f5cb5b28 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2750,7 +2750,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) uint64_t komodo_interestsum() { #ifdef ENABLE_WALLET - if ( GetBoolArg("-disablewallet", false) == 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && GetBoolArg("-disablewallet", false) == 0 ) { uint64_t interest,sum = 0; int32_t txheight; uint32_t locktime; vector vecOutputs; @@ -3422,6 +3422,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) " \"txid\": xxxxx, (string) the transaction id\n" " \"amount\": xxxxx, (numeric) the amount of value in the note\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" + " \"jsindex\": xxxxx, (numeric) the JoinSplit index\n" "}\n" "\nExamples:\n" + HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"") @@ -3463,6 +3464,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value)))); std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end()); obj.push_back(Pair("memo", HexStr(data))); + obj.push_back(Pair("jsindex", entry.jsop.js)); result.push_back(obj); } return result; @@ -4532,7 +4534,7 @@ int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); extern std::string NOTARY_PUBKEY; uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 hash,int32_t n,uint32_t blocktime,uint32_t prevtime,char *destaddr); int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout); -int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) { @@ -6165,13 +6167,12 @@ UniValue dicebet(const UniValue& params, bool fHelp) return(result); } if (amount > 0 && odds > 0) { - hex = DiceBet(0,name,fundingtxid,amount,odds,error); + hex = DiceBet(0,name,fundingtxid,amount,odds); + RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); - } else if ( error[0] != 0 ) { - ERR_RESULT(error); } } else { ERR_RESULT("amount and odds must be positive"); @@ -6181,7 +6182,7 @@ UniValue dicebet(const UniValue& params, bool fHelp) UniValue dicefinish(const UniValue& params, bool fHelp) { - UniValue result(UniValue::VOBJ); char *name; uint256 fundingtxid,bettxid; std::string hex; int32_t r; + UniValue result(UniValue::VOBJ); uint8_t funcid; char *name; uint256 entropyused,fundingtxid,bettxid; std::string hex; int32_t r; if ( fHelp || params.size() != 3 ) throw runtime_error("dicefinish name fundingtxid bettxid\n"); if ( ensure_CCrequirements() < 0 ) @@ -6195,7 +6196,7 @@ UniValue dicefinish(const UniValue& params, bool fHelp) } fundingtxid = Parseuint256((char *)params[1].get_str().c_str()); bettxid = Parseuint256((char *)params[2].get_str().c_str()); - hex = DiceBetFinish(&r,0,name,fundingtxid,bettxid,1); + hex = DiceBetFinish(funcid,entropyused,&r,0,name,fundingtxid,bettxid,1,zeroid,-1); if ( CCerror != "" ) { ERR_RESULT(CCerror); @@ -6203,6 +6204,13 @@ UniValue dicefinish(const UniValue& params, bool fHelp) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", hex)); + if ( funcid != 0 ) + { + char funcidstr[2]; + funcidstr[0] = funcid; + funcidstr[1] = 0; + result.push_back(Pair("funcid", funcidstr)); + } } else ERR_RESULT( "couldnt create dicefinish transaction"); return(result); } @@ -6225,11 +6233,9 @@ UniValue dicestatus(const UniValue& params, bool fHelp) memset(&bettxid,0,sizeof(bettxid)); if ( params.size() == 3 ) bettxid = Parseuint256((char *)params[2].get_str().c_str()); - winnings = DiceStatus(0,name,fundingtxid,bettxid,error); - if ( error[0] != 0 ) { - ERR_RESULT(error); - return(result); - } + winnings = DiceStatus(0,name,fundingtxid,bettxid); + RETURN_IF_ERROR(CCerror); + result.push_back(Pair("result", "success")); if ( winnings >= 0. ) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 70df32bef..67b81ea77 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1208,4 +1208,6 @@ public: /** Error status printout */ #define ERR_RESULT(x) result.push_back(Pair("result", "error")) , result.push_back(Pair("error", x)); +#define RETURN_IF_ERROR(CCerror) if ( CCerror != "" ) { ERR_RESULT(CCerror); return(result); } + #endif // BITCOIN_WALLET_WALLET_H