Merge remote-tracking branch 'upstream/FSM' into FSM

This commit is contained in:
Anton Lysakov
2018-11-08 21:13:32 +06:00
7 changed files with 377 additions and 210 deletions

View File

@@ -23,9 +23,9 @@
bool DiceValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds,std::string &error);
std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout);
double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,std::string &error);
std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds);
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);
double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid);
std::string DiceCreateFunding(uint64_t txfee,char *planstr,int64_t funds,int64_t minbet,int64_t maxbet,int64_t maxodds,int64_t timeoutblocks);
std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t amount);
UniValue DiceInfo(uint256 diceid);

View File

@@ -48,6 +48,8 @@ one other technical note is that komodod has the insight-explorer extensions bui
#include <univalue.h>
#include <exception>
#include "../komodo_defs.h"
#include "../utlist.h"
#include "../uthash.h"
extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE;
extern uint32_t ASSETCHAINS_CC;
@@ -134,6 +136,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);

View File

@@ -91,6 +91,8 @@ WARNING: there is an attack vector that precludes betting any large amounts, it
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
need to speed up dealer dicestatus loop (or in parallel)
validate refund
change to hashtables
*/
@@ -99,156 +101,330 @@ What is needed is for the dealer node to track the entropy tx that was already b
#define MAX_ENTROPYUSED 8192
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;
int32_t _dicehash_find(uint256 bettxid)
{
int32_t i;
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == bettxid )
return(1);
return(0);
}
void _dicehash_add(uint256 bettxid)
{
int32_t i;
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == zeroid )
{
bettxids[i] = bettxid;
return;
}
bettxids[rand() % MAX_ENTROPYUSED] = bettxid;
}
int32_t _dicerevealed_find(uint256 &oldbettxid,CTransaction &oldbetTx,uint256 entropyused,uint256 bettxid)
{
int32_t i;
for (i=0; i<MAX_ENTROPYUSED; i++)
{
if ( entropytxids[i][0] == entropyused )
{
if ( bettxid == entropytxids[i][1] )
return(i+1);
fprintf(stderr,"found identical entropy used.%d B different bettxid!\n",i);
oldbettxid = entropytxids[i][1];
oldbetTx = betTxs[i];
return(-1);
}
}
return(0);
}
void _dicerevealed_add(uint256 entropyused,uint256 bettxid,CTransaction betTx)
{
int32_t i;
for (i=0; i<MAX_ENTROPYUSED; i++)
{
if ( entropytxids[i][0] == zeroid )
break;
}
if ( i == MAX_ENTROPYUSED )
i = (rand() % MAX_ENTROPYUSED);
entropytxids[i][0] = entropyused;
entropytxids[i][1] = bettxid;
betTxs[i] = betTx;
}
int32_t DiceEntropyUsed(CTransaction &oldbetTx,uint256 &oldbettxid,uint256 entropyused,uint256 bettxid,CTransaction betTx)
{
int32_t i;
int32_t retval;
oldbettxid = zeroid;
if ( entropyused == zeroid || bettxid == zeroid )
{
fprintf(stderr,"null entropyused or bettxid\n");
return(1);
}
for (i=0; i<MAX_ENTROPYUSED; i++)
{
if ( entropytxids[i][0] == entropyused )
{
if ( bettxid == entropytxids[i][1] )
{
fprintf(stderr,"found identical entropy used.%d\n",i);
return(i+1);
}
oldbettxid = entropytxids[i][1];
oldbetTx = betTxs[i];
fprintf(stderr,"duplicate entropyused %s oldbettxid.%s\n",entropyused.GetHex().c_str(),oldbettxid.GetHex().c_str());
return(-1);
}
}
//fprintf(stderr,"cant find entropy used\n");
return(0);
pthread_mutex_lock(&DICEREVEALED_MUTEX);
retval = _dicerevealed_find(oldbettxid,oldbetTx,entropyused,bettxid);
pthread_mutex_unlock(&DICEREVEALED_MUTEX);
return(retval);
}
bool mySenddicetransaction(std::string res,uint256 entropyused,uint256 bettxid,CTransaction betTx,uint8_t funcid)
bool mySenddicetransaction(std::string res,uint256 entropyused,uint256 bettxid,CTransaction betTx,uint8_t funcid,struct dicefinish_info *ptr)
{
CTransaction tx; int32_t i=0,retval=-1; uint256 oldbettxid; CTransaction oldbetTx;
if ( res.empty() == 0 && res.size() > 64 && is_hexstr((char *)res.c_str(),0) > 64 )
{
if ( DecodeHexTx(tx,res) != 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 )
{
LOCK(cs_main);
//LOCK(cs_main);
if ( myAddtomempool(tx) != 0 )
{
RelayTransaction(tx);
if ( retval == 0 )
{
for (i=0; i<MAX_ENTROPYUSED; i++)
{
if ( entropytxids[i][0] == zeroid )
break;
}
if ( i == MAX_ENTROPYUSED )
i = (rand() % MAX_ENTROPYUSED);
entropytxids[i][0] = entropyused;
entropytxids[i][1] = bettxid;
betTxs[i] = betTx;
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());
}
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 fprintf(stderr,"error adding funcid.%c E.%s bet.%s -> %s to mempool, probably Disable replacement feature\n",funcid,entropyused.GetHex().c_str(),bettxid.GetHex().c_str(),tx.GetHash().GetHex().c_str());
}
else
{
RelayTransaction(tx);
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());
/*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=0,result,maxiters=600; struct dicefinish_info *ptr; uint256 entropyused,hashBlock; uint8_t funcid; CTransaction betTx;
ptr = (struct dicefinish_info *)_ptr;
unstringbits(name,ptr->sbits);
hashBlock = zeroid;
if ( GetTransaction(ptr->bettxid,betTx,hashBlock,false) == 0 || hashBlock == zeroid )
int32_t n = 0; int64_t threshold = 2 * 10000;
total = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
usleep((rand() % 1000000) + 100000);
for (i=0; i<maxiters; i++)
if ( myIsutxo_spentinmempool(it->first.txhash,(int32_t)it->first.index) == 0 )
{
usleep(100000);
if ( mytxid_inmempool(ptr->bettxid) != 0 ) // wait for bettxid to be in mempool
if ( it->second.satoshis < threshold || it->second.satoshis > 10*threshold )
continue;
total++;
if ( n < max )
{
//fprintf(stderr,"i.%d dicefinish.%d %s funding.%s bet.%s\n",i,ptr->iswin,name,uint256_str(str,ptr->fundingtxid),uint256_str(str2,ptr->bettxid));
break;
if ( utxos != 0 )
{
utxos[n].txid = it->first.txhash;
utxos[n].vout = (int32_t)it->first.index;
}
n++;
}
}
} else fprintf(stderr,">>>>>>> bettxid already confirmed\n");
if ( i == maxiters )
fprintf(stderr,"dicefinish.%d %s bet.%s didnt arrive in mempool\n",ptr->iswin,name,uint256_str(str,ptr->bettxid));
else
{
res = DiceBetFinish(funcid,entropyused,&result,0,name,ptr->fundingtxid,ptr->bettxid,ptr->iswin);
if ( result > 0 )
mySenddicetransaction(res,entropyused,ptr->bettxid,ptr->betTx,funcid);
}
free(ptr);
total -= n;
return(n);
}
int32_t dice_betspent(char *debugstr,uint256 bettxid)
{
/*int32_t numblocks;
/*CSpentIndexValue value,value2;
CSpentIndexKey key(txid,0);
CSpentIndexKey key2(txid,1);
if ( GetSpentIndex(key,value) != 0 || GetSpentIndex(key2,value2) != 0 )
{
fprintf(stderr,"%s txid.%s already spent\n",debugstr,txid.GetHex().c_str());
return(1);
}
if ( mode > 0 )
{
CCduration(numblocks,txid);
if ( numblocks > 0 )
{
fprintf(stderr,"%s txid.%s already confirmed %d\n",debugstr,txid.GetHex().c_str(),numblocks);
return(1);
}
}
else*/
{
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);
}
}
return(0);
}
void *dicefinish(void *_ptr)
{
std::vector<uint8_t> mypk; struct CCcontract_info *cp,C; char name[32],coinaddr[64],CCaddr[64]; std::string res; int32_t newht,numblocks,lastheight=0,vin0_needed,n,m,num,iter,result; struct dicefinish_info *ptr,*tmp; struct dicefinish_utxo *utxos; uint256 hashBlock; CTransaction betTx;
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);
while ( (newht= KOMODO_INSYNC) == 0 )
sleep(1);
sleep(10);
while ( 1 )
{
lastheight = newht;
fprintf(stderr,"dicefinish process ht.%d\n",newht);
for (iter=-1; iter<=1; iter+=2)
{
vin0_needed = 0;
DL_FOREACH_SAFE(DICEFINISH_LIST,ptr,tmp)
{
if ( ptr->revealed != 0 && time(NULL) > ptr->revealed+3600 )
{
fprintf(stderr,"purge %s\n",ptr->bettxid.GetHex().c_str());
DL_DELETE(DICEFINISH_LIST,ptr);
free(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);
}
if ( ptr->bettxid_ready != 0 && ptr->iswin == iter )
{
if ( ptr->txid != zeroid )
{
CCduration(numblocks,ptr->txid);
if ( numblocks == 0 )
mySenddicetransaction(ptr->rawtx,ptr->entropyused,ptr->bettxid,ptr->betTx,ptr->funcid,ptr);
}
if ( ptr->txid == zeroid )
vin0_needed++;
}
}
if ( vin0_needed > 0 )
{
utxos = (struct dicefinish_utxo *)calloc(vin0_needed,sizeof(*utxos));
if ( (n= dicefinish_utxosget(num,utxos,vin0_needed,coinaddr)) > 0 )
{
m = 0;
DL_FOREACH_SAFE(DICEFINISH_LIST,ptr,tmp)
{
if ( ptr->revealed != 0 && time(NULL) > ptr->revealed+3600 )
{
fprintf(stderr,"purge2 %s\n",ptr->bettxid.GetHex().c_str());
DL_DELETE(DICEFINISH_LIST,ptr);
free(ptr);
continue;
}
if ( ptr->bettxid_ready != 0 && ptr->iswin == iter && ptr->rawtx.size() == 0 )
{
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
{
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;
//DL_DELETE(DICEFINISH_LIST,ptr);
//free(ptr);
}
if ( ++m >= n )
break;
}
}
}
free(utxos);
}
}
while ( (newht= KOMODO_INSYNC) == 0 || newht == lastheight )
{
sleep(1);
continue;
}
}
return(0);
}
void DiceQueue(int32_t iswin,uint64_t sbits,uint256 fundingtxid,uint256 bettxid,CTransaction betTx)
{
struct dicefinish_info *ptr; CSpentIndexValue value,value2; int32_t i,duplicate=0;
CSpentIndexKey key(bettxid, 0);
CSpentIndexKey key2(bettxid, 1);
if ( GetSpentIndex(key,value) != 0 || GetSpentIndex(key2,value2) != 0 )
static int32_t didinit;
struct dicefinish_info *ptr; int32_t i,duplicate=0; uint64_t txfee = 10000;
if ( didinit == 0 )
{
//fprintf(stderr,"DiceQueue status bettxid.%s already spent\n",bettxid.GetHex().c_str());
return;
}
if ( myIsutxo_spentinmempool(bettxid,0) != 0 || myIsutxo_spentinmempool(bettxid,1) != 0 )
{
fprintf(stderr,"DiceQueue status bettxid.%s already spent in mempool\n",bettxid.GetHex().c_str());
return;
}
// check for duplicates here!!!
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == bettxid )
if ( pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,dicefinish,0) == 0 )
{
duplicate = 1;
break;
pthread_mutex_init(&DICE_MUTEX,NULL);
pthread_mutex_init(&DICEREVEALED_MUTEX,NULL);
didinit = 1;
}
if ( duplicate == 0 )
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 )
{
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == zeroid )
{
bettxids[i] = bettxid;
break;
}
if ( i == MAX_ENTROPYUSED )
bettxids[rand() % i] = bettxid;
_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;
//fprintf(stderr,"Queue dicefinish %s\n",bettxid.GetHex().c_str());
if ( ptr != 0 && pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,dicefinish,(void *)ptr) != 0 )
{
//fprintf(stderr,"DiceQueue.%d\n",iswin);
} // small memory leak per DiceQueue
}
ptr->winamount = betTx.vout[1].nValue * ((betTx.vout[2].nValue - txfee)+1);
DL_APPEND(DICEFINISH_LIST,ptr);
//fprintf(stderr,"queued iswin.%d %s\n",iswin,bettxid.GetHex().c_str());
} else fprintf(stderr,"DiceQueue status bettxid.%s already in list\n",bettxid.GetHex().c_str());
pthread_mutex_unlock(&DICE_MUTEX);
}
CPubKey DiceFundingPk(CScript scriptPubKey)
@@ -728,7 +904,7 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( it->second.satoshis < threshold )
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<mtx.vin.size(); j++)
@@ -736,7 +912,7 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
break;
if ( j != mtx.vin.size() )
continue;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 && tx.vout.size() > 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 )
{
@@ -748,7 +924,7 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
{
if ( total != 0 && maxinputs != 0 )
{
fprintf(stderr,"use (%c) %.8f %s %s\n",funcid,(double)tx.vout[0].nValue/COIN,sstr,uint256_str(str,txid));
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;
@@ -765,11 +941,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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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);
@@ -777,10 +953,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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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 )
@@ -788,13 +969,15 @@ 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;
fprintf(stderr,"%d: %s.(%c %.8f) total %.8f\n",n,uint256_str(str,txid),funcid,(double)it->second.satoshis/COIN,(double)totalinputs/COIN);
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 )
{
if ( (funcid= DecodeDiceOpRet(txid,tx.vout[tx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof)) != 0 )
{
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') )
@@ -807,7 +990,7 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit
//fprintf(stderr,"check first\n");
if ( tx.vout.size() > 1 && fundingPubKey == tx.vout[1].scriptPubKey )
{
if ( GetTransaction(tx.vin[0].prevout.hash,vinTx,hashBlock,false) == 0 || (int32_t)tx.vin[0].prevout.n < 0 )
if ( myGetTransaction(tx.vin[0].prevout.hash,vinTx,hashBlock) == 0 || (int32_t)tx.vin[0].prevout.n < 0 )
{
fprintf(stderr,"cant find entropy vin0 %s or vin0prev %d vouts[%d], iscoinbase.%d\n",uint256_str(str,tx.vin[0].prevout.hash),(int32_t)tx.vin[0].prevout.n,(int32_t)vinTx.vout.size(),(int32_t)vinTx.vin.size());
continue;
@@ -858,7 +1041,7 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit
} i = i + 1;
}
if (!random) {
fprintf(stderr,"numentropy tx %d: %.8f\n",n,(double)totalinputs/COIN);
fprintf(stderr,"pendingbets.%d numentropy tx %d: %.8f\n",pendingbets,n,(double)totalinputs/COIN);
entropytxs = n;
return(totalinputs);
} else {
@@ -875,7 +1058,7 @@ bool DicePlanExists(CScript &fundingPubKey,uint256 &fundingtxid,struct CCcontrac
if ( fundingtxid != zeroid ) // avoid scan unless creating new funding plan
{
//fprintf(stderr,"check fundingtxid\n");
if ( GetTransaction(fundingtxid,tx,hashBlock,false) != 0 && tx.vout.size() > 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 )
{
@@ -891,7 +1074,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' )
{
@@ -930,7 +1113,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");
@@ -971,7 +1154,7 @@ UniValue DiceList()
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::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 )
{
@@ -1059,24 +1242,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 < 2 || odds > 9999 )
{
error = "odds must be between 2 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;
@@ -1085,12 +1270,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()));
@@ -1101,16 +1286,16 @@ 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(uint8_t &funcid,uint256 &entropyused,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 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;
@@ -1133,33 +1318,31 @@ std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t *resultp,
winlosetimeout = 0;
}
}
if ( AddNormalinputs(mtx,mypk,2*txfee,1) == 0 ) // must be a single vin!!
{
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;
CSpentIndexKey key(bettxid, 0);
CSpentIndexValue value;
CSpentIndexKey key2(bettxid, 1);
CSpentIndexValue value2;
if ( GetSpentIndex(key,value) != 0 || GetSpentIndex(key2,value2) != 0 )
/*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 ( myIsutxo_spentinmempool(bettxid,0) != 0 || myIsutxo_spentinmempool(bettxid,1) != 0 )
if ( vin0txid == zeroid || vin0vout < 0 )
{
CCerror = "bettxid already spent in mempool";
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
if ( AddNormalinputs(mtx,mypk,2*txfee,1) == 0 ) // must be a single vin!!
{
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
{
@@ -1218,16 +1401,24 @@ std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t *resultp,
fundsneeded = txfee + (odds+1)*betTx.vout[1].nValue;
if ( CCchange >= fundsneeded )
CCchange -= fundsneeded;
else if ( (inputs= AddDiceInputs(cp,mtx,dicepk,fundsneeded,56,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));
@@ -1259,14 +1450,15 @@ std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t *resultp,
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,entropyTx; uint256 hentropyproof,entropyused,hash,proof,txid,hashBlock,spenttxid,bettorentropy; CPubKey mypk,dicepk,fundingpk; struct CCcontract_info *cp,C; int32_t i,duplicate=0,result,iswin,vout,n=0; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t sbits; char coinaddr[64]; std::string res; uint8_t funcid;
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,win,loss,duplicate=0,result,iswin,vout,n=0; int64_t minbet,maxbet,maxodds,timeoutblocks,sum=0; uint64_t sbits; char coinaddr[64]; std::string res; uint8_t funcid;
if ( (cp= Diceinit(fundingPubKey,fundingtxid,&C,planstr,txfee,mypk,dicepk,sbits,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);
@@ -1278,67 +1470,34 @@ 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.size() >= 4 && betTx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && GetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock,false) != 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 && myGetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock) != 0 )
{
if ( DecodeDiceOpRet(txid,betTx.vout[betTx.vout.size()-1].scriptPubKey,sbits,fundingtxid,hash,proof) == 'B' )
{
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == txid )
{
duplicate = 1;
break;
}
if ( duplicate == 0 )
bettorentropy = DiceGetEntropy(betTx,'B');
if ( (iswin= DiceIsWinner(hentropyproof,txid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 )
{
for (i=0; i<MAX_ENTROPYUSED; i++)
if ( bettxids[i] == zeroid )
{
bettxids[i] = txid;
break;
}
if ( i == MAX_ENTROPYUSED )
bettxids[rand() % i] = txid;
CSpentIndexKey key(txid, 0);
CSpentIndexValue value;
CSpentIndexKey key2(txid, 1);
CSpentIndexValue value2;
if ( GetSpentIndex(key,value) != 0 || GetSpentIndex(key2,value2) != 0 )
{
fprintf(stderr,"status bettxid.%s already spent\n",txid.GetHex().c_str());
continue;
}
if ( myIsutxo_spentinmempool(txid,0) != 0 || myIsutxo_spentinmempool(txid,1) != 0 )
{
fprintf(stderr,"status bettxid.%s already spent in mempool\n",txid.GetHex().c_str());
continue;
}
/*following didnt work:
bettorentropy = DiceGetEntropy(betTx,'B');
if ( (iswin= DiceIsWinner(hentropyproof,txid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 )
{
DiceQueue(iswin,sbits,fundingtxid,txid);
if ( ++n >= 100 )
break;
}*/
res = DiceBetFinish(funcid,entropyused,&result,txfee,planstr,fundingtxid,txid,scriptPubKey == fundingPubKey);
if ( result > 0 )
{
mySenddicetransaction(res,entropyused,txid,betTx,funcid);
n++;
if ( n >= 100 )
break;
} //else error = res;
if ( iswin > 0 )
win++;
else if ( iswin < 0 )
loss++;
fprintf(stderr,"%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);
n++;
DiceQueue(iswin,sbits,fundingtxid,txid,betTx);
}
}
}
}
if ( scriptPubKey == fundingPubKey )
{
CTransaction tx; uint64_t entropyval; uint256 entropytxid; int32_t entropytxs,mintxs=5000;
CTransaction tx; uint64_t entropyval; uint256 entropytxid; int32_t entropytxs,mintxs=2000;
DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,fundingtxid,entropytxs,false);
if ( entropytxs < mintxs )
{
for (i=0; i<mintxs - entropytxs; i++)
for (i=0; i<mintxs - entropytxs && i<100; i++)
{
res = DiceAddfunding(txfee,planstr,fundingtxid,COIN/100);
if ( res.empty() == 0 && res.size() > 64 && is_hexstr((char *)res.c_str(),0) > 64 )
@@ -1355,6 +1514,12 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx
} else break;
}
}
pubkey2addr(coinaddr,Mypubkey().data());
dicefinish_utxosget(entropytxs,0,0,coinaddr);
if ( entropytxs < mintxs )
{
fprintf(stderr,"need to generate %d 0.0002\n",mintxs - entropytxs);
}
}
return(n);
}
@@ -1364,26 +1529,26 @@ 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(funcid,entropyused,&result,txfee,planstr,fundingtxid,bettxid,1);
else res = DiceBetFinish(funcid,entropyused,&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 )
{
mySenddicetransaction(res,entropyused,bettxid,betTx,funcid);
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 ( 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 )
@@ -1391,8 +1556,8 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx
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.);

View File

@@ -3582,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 )

View File

@@ -940,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

View File

@@ -6167,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");
@@ -6197,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(funcid,entropyused,&r,0,name,fundingtxid,bettxid,1);
hex = DiceBetFinish(funcid,entropyused,&r,0,name,fundingtxid,bettxid,1,zeroid,-1);
if ( CCerror != "" )
{
ERR_RESULT(CCerror);
@@ -6224,7 +6223,7 @@ UniValue dicestatus(const UniValue& params, bool fHelp)
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain;
//LOCK2(cs_main, pwalletMain->cs_wallet);
LOCK2(cs_main, pwalletMain->cs_wallet);
name = (char *)params[0].get_str().c_str();
if (!VALID_PLAN_NAME(name)) {
ERR_RESULT(strprintf("Plan name can be at most %d ASCII characters",PLAN_NAME_MAX));
@@ -6234,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. )
{

View File

@@ -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