@@ -90,7 +90,7 @@ void WaitForShutdown(boost::thread_group* threadGroup)
|
||||
//komodo_longestchain();
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
komodo_cbopretupdate();
|
||||
for (i=0; i<ASSETCHAINS_BLOCKTIME/2; i++)
|
||||
for (i=0; i<=ASSETCHAINS_BLOCKTIME/5; i++)
|
||||
{
|
||||
fShutdown = ShutdownRequested();
|
||||
if ( fShutdown != 0 )
|
||||
|
||||
@@ -296,6 +296,14 @@ static void tg_hold(struct games_state *rs,tetris_game *obj)
|
||||
obj->stored.ori = ori;
|
||||
while (!tg_fits(obj, obj->falling)) {
|
||||
obj->falling.loc.row--;
|
||||
if (tg_fits(obj, obj->falling)) {
|
||||
break;
|
||||
}
|
||||
obj->falling.loc.col--;
|
||||
if (tg_fits(obj, obj->falling)) {
|
||||
break;
|
||||
}
|
||||
obj->falling.loc.col += 2;
|
||||
}
|
||||
}
|
||||
tg_put(obj, obj->falling);
|
||||
|
||||
@@ -201,6 +201,9 @@ try_again:
|
||||
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
|
||||
//curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
//curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2);
|
||||
|
||||
if ( strncmp(url,"https",5) == 0 )
|
||||
{
|
||||
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
|
||||
@@ -247,13 +250,13 @@ try_again:
|
||||
numretries++;
|
||||
if ( specialcase != 0 )
|
||||
{
|
||||
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
|
||||
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
else if ( numretries >= 1 )
|
||||
{
|
||||
//printf("Maximum number of retries exceeded!\n");
|
||||
fprintf(stderr,"Maximum number of retries exceeded!\n");
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1565,7 +1565,7 @@ int32_t komodo_heightpricebits(uint32_t prevbits[4],int32_t nHeight)
|
||||
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
memcpy(prevbits,&vopret[0],PRICES_SIZEBIT0);
|
||||
memcpy(prevbits,vopret.data(),vopret.size());
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
@@ -1579,44 +1579,64 @@ int32_t komodo_heightpricebits(uint32_t prevbits[4],int32_t nHeight)
|
||||
*/
|
||||
uint32_t komodo_pricenew(int32_t *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance)
|
||||
{
|
||||
uint32_t highprice,lowprice;
|
||||
uint64_t highprice,lowprice;
|
||||
if ( refprice < 2 )
|
||||
return(0);
|
||||
highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price
|
||||
lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest
|
||||
if ( highprice == refprice )
|
||||
highprice++;
|
||||
if ( lowprice == refprice )
|
||||
lowprice--;
|
||||
if ( price >= highprice )
|
||||
{
|
||||
*maxflagp = 1;
|
||||
//fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
|
||||
if ( price > highprice ) // return non-zero only if we violate the tolerance
|
||||
{
|
||||
*maxflagp = 2;
|
||||
return(highprice);
|
||||
}
|
||||
*maxflagp = 1;
|
||||
}
|
||||
else if ( price <= lowprice )
|
||||
{
|
||||
*maxflagp = -1;
|
||||
//fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance);
|
||||
if ( price < lowprice )
|
||||
{
|
||||
*maxflagp = -2;
|
||||
return(lowprice);
|
||||
}
|
||||
*maxflagp = -1;
|
||||
}
|
||||
else return(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance
|
||||
int32_t komodo_pricecmp(int32_t *maxflagp,uint32_t pricebitsA[4],uint32_t pricebitsB[4],int64_t tolerance)
|
||||
int32_t komodo_pricecmp(int32_t nHeight,int32_t n,int32_t *maxflagp,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance)
|
||||
{
|
||||
int32_t i;
|
||||
int32_t i; uint32_t newprice;
|
||||
*maxflagp = 0;
|
||||
for (i=1; i<4; i++)
|
||||
if ( komodo_pricenew(maxflagp,pricebitsA[i],pricebitsB[i],tolerance) != 0 )
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
if ( (newprice= komodo_pricenew(maxflagp,pricebitsA[i],pricebitsB[i],tolerance)) != 0 )
|
||||
{
|
||||
fprintf(stderr,"ht.%d i.%d/%d %u vs %u -> newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,*maxflagp);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// komodo_priceclamp() clamps any price that is beyond tolerance
|
||||
int32_t komodo_priceclamp(uint32_t pricebits[4],uint32_t refprices[4],int64_t tolerance)
|
||||
int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance)
|
||||
{
|
||||
int32_t i,maxflag = 0; uint32_t newprice;
|
||||
for (i=1; i<4; i++)
|
||||
int32_t i,maxflag; uint32_t newprice;
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
maxflag = 0;
|
||||
if ( (newprice= komodo_pricenew(&maxflag,pricebits[i],refprices[i],tolerance)) != 0 )
|
||||
{
|
||||
fprintf(stderr,"priceclamped[%d] %u -> %u\n",i,pricebits[i],newprice);
|
||||
fprintf(stderr,"priceclamped[%d of %d] %u vs %u -> %u\n",i,n,refprices[i],pricebits[i],newprice);
|
||||
pricebits[i] = newprice;
|
||||
}
|
||||
}
|
||||
@@ -1626,20 +1646,35 @@ int32_t komodo_priceclamp(uint32_t pricebits[4],uint32_t refprices[4],int64_t to
|
||||
// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight
|
||||
CScript komodo_mineropret(int32_t nHeight)
|
||||
{
|
||||
CScript opret; uint32_t pricebits[4],prevbits[4]; int32_t maxflag;
|
||||
CScript opret; uint32_t pricebits[8192],prevbits[8192]; int32_t maxflag,i,n,numzero=0;
|
||||
if ( Mineropret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
n = (int32_t)(Mineropret.size() / sizeof(uint32_t));
|
||||
numzero = 1;
|
||||
while ( numzero > 0 )
|
||||
{
|
||||
memcpy(pricebits,Mineropret.data(),Mineropret.size());
|
||||
for (i=numzero=0; i<n; i++)
|
||||
if ( pricebits[i] == 0 )
|
||||
numzero++;
|
||||
if ( numzero != 0 )
|
||||
fprintf(stderr,"numzero.%d\n",numzero);
|
||||
}
|
||||
if ( komodo_heightpricebits(prevbits,nHeight-1) == 0 )
|
||||
{
|
||||
memcpy(pricebits,&Mineropret[0],PRICES_SIZEBIT0);
|
||||
if ( komodo_pricecmp(&maxflag,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
memcpy(pricebits,Mineropret.data(),Mineropret.size());
|
||||
if ( komodo_pricecmp(0,n,&maxflag,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
// if the new prices are not within tolerance, update Mineropret with clipped prices
|
||||
komodo_priceclamp(pricebits,prevbits,PRICES_MAXCHANGE);
|
||||
komodo_priceclamp(n,pricebits,prevbits,PRICES_MAXCHANGE);
|
||||
fprintf(stderr,"update Mineropret to clamped prices\n");
|
||||
memcpy(&Mineropret[0],pricebits,PRICES_SIZEBIT0);
|
||||
memcpy(Mineropret.data(),pricebits,Mineropret.size());
|
||||
}
|
||||
}
|
||||
int32_t i;
|
||||
for (i=0; i<Mineropret.size(); i++)
|
||||
fprintf(stderr,"%02x",Mineropret[i]);
|
||||
fprintf(stderr," <- Mineropret\n");
|
||||
return(opret << OP_RETURN << Mineropret);
|
||||
}
|
||||
return(opret);
|
||||
@@ -1655,61 +1690,203 @@ CScript komodo_mineropret(int32_t nHeight)
|
||||
|
||||
int32_t komodo_opretvalidate(int32_t nHeight,CScript scriptPubKey)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint32_t localbits[4],pricebits[4],prevbits[4],newprice; int32_t i,lag,lag2,maxflag=0;
|
||||
std::vector<uint8_t> vopret; double btcusd,btcgbp,btceur; uint32_t localbits[8192],pricebits[8192],prevbits[8192],newprice; int32_t i,lag,lag2,n,maxflag=0; uint32_t now = (uint32_t)time(NULL);
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
GetOpReturnData(scriptPubKey,vopret);
|
||||
if ( vopret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
memcpy(pricebits,&vopret[0],PRICES_SIZEBIT0);
|
||||
lag = (int32_t)(time(NULL) - pricebits[0]);
|
||||
if ( lag < 0 )
|
||||
lag = -lag;
|
||||
lag2 = (int32_t)(pricebits[0] - komodo_heightstamp(nHeight-1));
|
||||
fprintf(stderr,"ht.%d: t%u lag.%d %.4f USD, %.4f GBP, %.4f EUR htstamp.%d [%d]\n",nHeight,pricebits[0],lag,(double)pricebits[1]/10000,(double)pricebits[2]/10000,(double)pricebits[3]/10000,komodo_heightstamp(nHeight-1),lag2);
|
||||
n = (int32_t)(vopret.size() / sizeof(uint32_t));
|
||||
memcpy(pricebits,vopret.data(),Mineropret.size());
|
||||
if ( nHeight > 1 )
|
||||
{
|
||||
lag = (int32_t)(now - pricebits[0]);
|
||||
lag2 = (int32_t)(komodo_heightstamp(nHeight-1) - pricebits[0]);
|
||||
if ( lag < -60 ) // avoid data from future
|
||||
{
|
||||
fprintf(stderr,"now.%u htstamp.%u - pricebits[0] %u -> lag.%d\n",now,komodo_heightstamp(nHeight-1),pricebits[0],lag2);
|
||||
return(-1);
|
||||
}
|
||||
// else need to check against current blocktime to prevent pricebits[0] games
|
||||
btcusd = (double)pricebits[1]/10000;
|
||||
btcgbp = (double)pricebits[2]/10000;
|
||||
btceur = (double)pricebits[3]/10000;
|
||||
fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2);
|
||||
if ( komodo_heightpricebits(prevbits,nHeight-1) == 0 )
|
||||
{
|
||||
if ( komodo_pricecmp(&maxflag,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
return(-1);
|
||||
} else return(-1);
|
||||
}
|
||||
if ( lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
memcpy(localbits,&Mineropret[0],PRICES_SIZEBIT0);
|
||||
if ( maxflag == 0 )
|
||||
{
|
||||
if ( komodo_pricecmp(&maxflag,localbits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=1; i<4; i++)
|
||||
if ( komodo_pricecmp(nHeight,n,&maxflag,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
maxflag = 0;
|
||||
if ( (newprice= komodo_pricenew(&maxflag,pricebits[i],prevbits[i],PRICES_MAXCHANGE)) != 0 ) // proposed price is clamped
|
||||
for (i=1; i<n; i++)
|
||||
fprintf(stderr,"%.4f ",(double)prevbits[i]/10000);
|
||||
fprintf(stderr," oldprices.%d\n",nHeight);
|
||||
for (i=1; i<n; i++)
|
||||
fprintf(stderr,"%.4f ",(double)pricebits[i]/10000);
|
||||
fprintf(stderr," newprices.%d\n",nHeight);
|
||||
sleep(3);
|
||||
memcpy(pricebits,vopret.data(),Mineropret.size());
|
||||
if ( komodo_heightpricebits(prevbits,nHeight-1) == 0 )
|
||||
{
|
||||
// make sure local price is beyond clamped
|
||||
if ( maxflag > 0 && localbits[i] < pricebits[i] )
|
||||
return(-1);
|
||||
else if ( maxflag < 0 && localbits[i] > pricebits[i] )
|
||||
if ( komodo_pricecmp(nHeight,n,&maxflag,pricebits,prevbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
fprintf(stderr,"vs prev maxflag.%d cmp error\n",maxflag);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else return(-1);
|
||||
if ( lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0 )
|
||||
{
|
||||
memcpy(localbits,Mineropret.data(),Mineropret.size());
|
||||
for (i=0; i<n; i++)
|
||||
if ( localbits[i] == 0 )
|
||||
localbits[i] = prevbits[i];
|
||||
if ( maxflag == 0 )
|
||||
{
|
||||
if ( komodo_pricecmp(nHeight,n,&maxflag,pricebits,localbits,PRICES_MAXCHANGE) < 0 )
|
||||
{
|
||||
fprintf(stderr,"maxflag.0 cmp error\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=1; i<n; i++)
|
||||
{
|
||||
maxflag = 0;
|
||||
if ( (newprice= komodo_pricenew(&maxflag,pricebits[i],prevbits[i],PRICES_MAXCHANGE)) != 0 ) // proposed price is clamped
|
||||
{
|
||||
// make sure local price is moving in right direction
|
||||
fprintf(stderr,"maxflag.%d i.%d localbits.%u vs pricebits.%u\n",maxflag,i,localbits[i],pricebits[i]);
|
||||
if ( maxflag > 0 && localbits[i] < prevbits[i] )
|
||||
return(-1);
|
||||
else if ( maxflag < 0 && localbits[i] > prevbits[i] )
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
} else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)PRICES_SIZEBIT0,(int32_t)scriptPubKey.size(),scriptPubKey[0]);
|
||||
} else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]);
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *nonportable_path(char *str)
|
||||
{
|
||||
int32_t i;
|
||||
for (i=0; str[i]!=0; i++)
|
||||
if ( str[i] == '/' )
|
||||
str[i] = '\\';
|
||||
return(str);
|
||||
}
|
||||
|
||||
char *portable_path(char *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(nonportable_path(str));
|
||||
#else
|
||||
#ifdef __PNACL
|
||||
/*int32_t i,n;
|
||||
if ( str[0] == '/' )
|
||||
return(str);
|
||||
else
|
||||
{
|
||||
n = (int32_t)strlen(str);
|
||||
for (i=n; i>0; i--)
|
||||
str[i] = str[i-1];
|
||||
str[0] = '/';
|
||||
str[n+1] = 0;
|
||||
}*/
|
||||
#endif
|
||||
return(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
|
||||
{
|
||||
FILE *fp;
|
||||
long filesize,buflen = *allocsizep;
|
||||
uint8_t *buf = *bufp;
|
||||
*lenp = 0;
|
||||
if ( (fp= fopen(portable_path(fname),"rb")) != 0 )
|
||||
{
|
||||
fseek(fp,0,SEEK_END);
|
||||
filesize = ftell(fp);
|
||||
if ( filesize == 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
*lenp = 0;
|
||||
//printf("loadfile null size.(%s)\n",fname);
|
||||
return(0);
|
||||
}
|
||||
if ( filesize > buflen )
|
||||
{
|
||||
*allocsizep = filesize;
|
||||
*bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64);
|
||||
}
|
||||
rewind(fp);
|
||||
if ( buf == 0 )
|
||||
printf("Null buf ???\n");
|
||||
else
|
||||
{
|
||||
if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
|
||||
printf("error reading filesize.%ld\n",(long)filesize);
|
||||
buf[filesize] = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
*lenp = filesize;
|
||||
//printf("loaded.(%s)\n",buf);
|
||||
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
void *filestr(long *allocsizep,char *_fname)
|
||||
{
|
||||
long filesize = 0; char *fname,*buf = 0; void *retptr;
|
||||
*allocsizep = 0;
|
||||
fname = (char *)malloc(strlen(_fname)+1);
|
||||
strcpy(fname,_fname);
|
||||
retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep);
|
||||
free(fname);
|
||||
return(retptr);
|
||||
}
|
||||
|
||||
cJSON *send_curl(char *url,char *fname)
|
||||
{
|
||||
long fsize; char curlstr[1024],*jsonstr; cJSON *json=0;
|
||||
sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname);
|
||||
if ( system(curlstr) == 0 )
|
||||
{
|
||||
if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 )
|
||||
{
|
||||
json = cJSON_Parse(jsonstr);
|
||||
free(jsonstr);
|
||||
}
|
||||
}
|
||||
return(json);
|
||||
}
|
||||
|
||||
// get_urljson just returns the JSON returned by the URL using issue_curl
|
||||
|
||||
#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0)
|
||||
|
||||
const char *Cryptos[] = { "KMD", "ETH", "LTC", "BCHABC", "XMR", "IOTA", "DASH", "XEM", "ZEC", "WAVES", "RVN", "LSK", "DCR", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" };
|
||||
|
||||
const char *Forex[] =
|
||||
{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR"
|
||||
};
|
||||
|
||||
/*
|
||||
const char *Techstocks[] =
|
||||
{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN"
|
||||
};
|
||||
const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", };
|
||||
|
||||
const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" };
|
||||
*/
|
||||
|
||||
cJSON *get_urljson(char *url)
|
||||
{
|
||||
char *jsonstr; cJSON *json = 0;
|
||||
@@ -1722,11 +1899,105 @@ cJSON *get_urljson(char *url)
|
||||
return(json);
|
||||
}
|
||||
|
||||
uint32_t get_stockprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json,*obj; uint32_t high,low,price = 0;
|
||||
sprintf(url,"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=%s&interval=15min&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
|
||||
if ( (json= get_urljson(url)) != 0 )
|
||||
{
|
||||
if ( (obj= jobj(json,(char *)"Time Series (15min)")) != 0 )
|
||||
{
|
||||
high = jdouble(jitem(obj,0),(char *)"2. high")*10000 + 0.000049;
|
||||
low = jdouble(jitem(obj,0),(char *)"3. low")*10000 + 0.000049;
|
||||
price = (high + low) / 2;
|
||||
}
|
||||
free_json(json);
|
||||
}
|
||||
return(price);
|
||||
}
|
||||
|
||||
uint32_t get_dailyfx(uint32_t *prices)
|
||||
{
|
||||
//{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"}
|
||||
char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0;
|
||||
sprintf(url,"https://api.openrates.io/latest?base=USD");
|
||||
if ( (json= send_curl(url,(char *)"dailyfx")) != 0 )
|
||||
{
|
||||
if ( (rates= jobj(json,(char *)"rates")) != 0 )
|
||||
{
|
||||
for (i=0; i<sizeof(Forex)/sizeof(*Forex); i++)
|
||||
{
|
||||
price = jdouble(rates,(char *)Forex[i]) * 10000 + 0.000049;
|
||||
fprintf(stderr,"(%s %.4f) ",Forex[i],(double)price/10000);
|
||||
prices[i] = price;
|
||||
}
|
||||
}
|
||||
if ( (datestr= jstr(json,(char *)"date")) != 0 )
|
||||
fprintf(stderr,"(%s)",datestr);
|
||||
fprintf(stderr,"\n");
|
||||
free_json(json);
|
||||
}
|
||||
return(datenum);
|
||||
}
|
||||
|
||||
uint32_t get_binanceprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json; uint32_t price = 0;
|
||||
sprintf(url,"https://api.binance.com/api/v1/ticker/price?symbol=%sBTC",symbol);
|
||||
if ( (json= send_curl(url,(char *)"bnbprice")) != 0 )
|
||||
{
|
||||
price = jdouble(json,(char *)"price")*SATOSHIDEN + 0.0000000049;
|
||||
free_json(json);
|
||||
}
|
||||
usleep(100000);
|
||||
return(price);
|
||||
}
|
||||
|
||||
int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n)
|
||||
{
|
||||
int32_t i,errs=0; uint32_t price;
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if ( (price= get_binanceprice(list[i])) == 0 )
|
||||
errs++;
|
||||
fprintf(stderr,"(%s %.8f) ",list[i],(double)price/SATOSHIDEN);
|
||||
prices[i] = price;
|
||||
}
|
||||
fprintf(stderr," errs.%d\n",errs);
|
||||
return(-errs);
|
||||
}
|
||||
|
||||
uint32_t get_currencyprice(const char *symbol)
|
||||
{
|
||||
char url[512]; cJSON *json,*obj; uint32_t price = 0;
|
||||
sprintf(url,"https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=%s&to_currency=USD&apikey=%s",symbol,NOTARY_PUBKEY.data()+50);
|
||||
if ( (json= send_curl(url,(char *)"curldata")) != 0 )//get_urljson(url)) != 0 )
|
||||
{
|
||||
if ( (obj= jobj(jitem(json,0),0)) != 0 )
|
||||
price = jdouble(obj,(char *)"5. Exchange Rate")*10000 + 0.000049;
|
||||
free_json(json);
|
||||
}
|
||||
return(price);
|
||||
}
|
||||
|
||||
int32_t get_stocks(const char *list[],int32_t n)
|
||||
{
|
||||
int32_t i,errs=0; uint32_t price;
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if ( (price= get_stockprice(list[i])) == 0 )
|
||||
errs++;
|
||||
else fprintf(stderr,"(%s %.4f) ",list[i],(double)price/10000);
|
||||
}
|
||||
fprintf(stderr," errs.%d\n",errs);
|
||||
return(-errs);
|
||||
}
|
||||
|
||||
// parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data.
|
||||
|
||||
int32_t get_btcusd(uint32_t pricebits[4])
|
||||
{
|
||||
cJSON *pjson,*bpi,*obj; char str[512]; uint64_t btcusd = 0,btcgbp = 0,btceur = 0;
|
||||
cJSON *pjson,*bpi,*obj; char str[512]; double dbtcgbp,dbtcusd,dbtceur; uint64_t btcusd = 0,btcgbp = 0,btceur = 0;
|
||||
if ( (pjson= get_urljson((char *)"http://api.coindesk.com/v1/bpi/currentprice.json")) != 0 )
|
||||
{
|
||||
if ( (bpi= jobj(pjson,(char *)"bpi")) != 0 )
|
||||
@@ -1749,26 +2020,74 @@ int32_t get_btcusd(uint32_t pricebits[4])
|
||||
}
|
||||
}
|
||||
free_json(pjson);
|
||||
fprintf(stderr,"BTC/USD %.4f, BTC/GBP %.4f, BTC/EUR %.4f\n",dstr(btcusd),dstr(btcgbp),dstr(btceur));
|
||||
dbtcusd = (double)pricebits[1]/10000;
|
||||
dbtcgbp = (double)pricebits[2]/10000;
|
||||
dbtceur = (double)pricebits[3]/10000;
|
||||
fprintf(stderr,"BTC/USD %.4f, BTC/GBP %.4f, BTC/EUR %.4f GBPUSD %.6f, EURUSD %.6f EURGBP %.6f\n",dbtcusd,dbtcgbp,dbtceur,dbtcusd/dbtcgbp,dbtcusd/dbtceur,dbtcgbp/dbtceur);
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation
|
||||
|
||||
void komodo_cbopretupdate()
|
||||
{
|
||||
uint32_t pricebits[4];
|
||||
static uint32_t lasttime,lastcrypto,lastbtc;
|
||||
static uint32_t pricebits[4],cryptoprices[sizeof(Cryptos)/sizeof(*Cryptos)],forexprices[sizeof(Forex)/sizeof(*Forex)];
|
||||
int32_t size; uint32_t now = (uint32_t)time(NULL);
|
||||
if ( (ASSETCHAINS_CBOPRET & 1) != 0 )
|
||||
{
|
||||
if ( get_btcusd(pricebits) == 0 )
|
||||
if ( komodo_nextheight() > 333 )
|
||||
ASSETCHAINS_CBOPRET = 7;
|
||||
size = PRICES_SIZEBIT0;
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
size += sizeof(forexprices);
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
size += sizeof(cryptoprices);
|
||||
if ( Mineropret.size() < size )
|
||||
Mineropret.resize(size);
|
||||
size = PRICES_SIZEBIT0;
|
||||
if ( now > lastbtc+120 && get_btcusd(pricebits) == 0 )
|
||||
{
|
||||
if ( Mineropret.size() < PRICES_SIZEBIT0 )
|
||||
Mineropret.resize(PRICES_SIZEBIT0);
|
||||
memcpy(&Mineropret[0],pricebits,PRICES_SIZEBIT0);
|
||||
//int32_t i; for (i=0; i<Mineropret.size(); i++)
|
||||
// fprintf(stderr,"%02x",Mineropret[i]);
|
||||
//fprintf(stderr," <- set Mineropret[%d]\n",(int32_t)Mineropret.size());
|
||||
memcpy(Mineropret.data(),pricebits,PRICES_SIZEBIT0);
|
||||
lastbtc = (uint32_t)time(NULL);
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 2) != 0 )
|
||||
{
|
||||
if ( now > lasttime+3600*5 || forexprices[0] == 0 )
|
||||
{
|
||||
get_dailyfx(forexprices);
|
||||
memcpy(&Mineropret.data()[size],forexprices,sizeof(forexprices));
|
||||
lasttime = (uint32_t)time(NULL);
|
||||
}
|
||||
size += sizeof(forexprices);
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
if ( now > lastcrypto+100 )
|
||||
{
|
||||
get_cryptoprices(cryptoprices,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)));
|
||||
memcpy(&Mineropret.data()[size],cryptoprices,sizeof(cryptoprices));
|
||||
lastcrypto = (uint32_t)time(NULL);
|
||||
}
|
||||
size += sizeof(cryptoprices);
|
||||
}
|
||||
//int32_t i; for (i=0; i<Mineropret.size(); i++)
|
||||
// fprintf(stderr,"%02x",Mineropret[i]);
|
||||
//fprintf(stderr," <- set Mineropret[%d]\n",(int32_t)Mineropret.size());
|
||||
/*
|
||||
if ( (ASSETCHAINS_CBOPRET & 4) != 0 )
|
||||
{
|
||||
get_currencies(Metals,(int32_t)(sizeof(Metals)/sizeof(*Metals)));
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 32) != 0 )
|
||||
{
|
||||
get_stocks(Markets,(int32_t)(sizeof(Markets)/sizeof(*Markets)));
|
||||
}
|
||||
if ( (ASSETCHAINS_CBOPRET & 64) != 0 )
|
||||
{
|
||||
get_stocks(Techstocks,(int32_t)(sizeof(Techstocks)/sizeof(*Techstocks)));
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1816,7 +1816,7 @@ void komodo_args(char *argv0)
|
||||
if ( hexstr.size() != 0 )
|
||||
{
|
||||
Mineropret.resize(hexstr.size()/2);
|
||||
decode_hex(&Mineropret[0],hexstr.size()/2,(char *)hexstr.c_str());
|
||||
decode_hex(Mineropret.data(),hexstr.size()/2,(char *)hexstr.c_str());
|
||||
for (i=0; i<Mineropret.size(); i++)
|
||||
fprintf(stderr,"%02x",Mineropret[i]);
|
||||
fprintf(stderr," Mineropret\n");
|
||||
@@ -2067,7 +2067,7 @@ void komodo_args(char *argv0)
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
{
|
||||
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CBOPRET),(void *)&ASSETCHAINS_CBOPRET);
|
||||
komodo_cbopretupdate(); // will set Mineropret
|
||||
//komodo_cbopretupdate(); // will set Mineropret
|
||||
fprintf(stderr,"This blockchain uses data produced from CoinDesk Bitcoin Price Index\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import pickle
|
||||
import platform
|
||||
import os
|
||||
import subprocess
|
||||
import random
|
||||
import signal
|
||||
from slickrpc import Proxy
|
||||
from binascii import hexlify
|
||||
@@ -1044,34 +1045,41 @@ def print_multiplayer_games_list(rpc_connection):
|
||||
|
||||
def rogue_newgame_singleplayer(rpc_connection, is_game_a_rogue=True):
|
||||
try:
|
||||
new_game_txid = rpc_connection.cclib("newgame", "17", "[1]")["txid"]
|
||||
print("New singleplayer training game succesfully created. txid: " + new_game_txid)
|
||||
while True:
|
||||
mempool = rpc_connection.getrawmempool()
|
||||
if new_game_txid in mempool:
|
||||
print(colorize("Waiting for game transaction to be mined", "blue"))
|
||||
time.sleep(5)
|
||||
else:
|
||||
print(colorize("Game transaction is mined", "green"))
|
||||
break
|
||||
players_list = rogue_players_list(rpc_connection)
|
||||
if len(players_list["playerdata"]) > 0:
|
||||
print_players_list(rpc_connection)
|
||||
if is_game_a_rogue:
|
||||
new_game_txid = rpc_connection.cclib("newgame", "17", "[1]")["txid"]
|
||||
print("New singleplayer training game succesfully created. txid: " + new_game_txid)
|
||||
while True:
|
||||
is_choice_needed = input("Do you want to choose a player for this game? [y/n] ")
|
||||
if is_choice_needed == "y":
|
||||
player_txid = input("Please input player txid: ")
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid, player_txid)["txid"]
|
||||
break
|
||||
elif is_choice_needed == "n":
|
||||
set_warriors_name(rpc_connection)
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"]
|
||||
break
|
||||
mempool = rpc_connection.getrawmempool()
|
||||
if new_game_txid in mempool:
|
||||
print(colorize("Waiting for game transaction to be mined", "blue"))
|
||||
time.sleep(5)
|
||||
else:
|
||||
print("Please choose y or n !")
|
||||
print(colorize("Game transaction is mined", "green"))
|
||||
break
|
||||
else:
|
||||
pending_games = rpc_connection.cclib("pending", "17")["pending"]
|
||||
new_game_txid = random.choice(pending_games)
|
||||
if is_game_a_rogue:
|
||||
players_list = rogue_players_list(rpc_connection)
|
||||
if len(players_list["playerdata"]) > 0:
|
||||
print_players_list(rpc_connection)
|
||||
while True:
|
||||
is_choice_needed = input("Do you want to choose a player for this game? [y/n] ")
|
||||
if is_choice_needed == "y":
|
||||
player_txid = input("Please input player txid: ")
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid, player_txid)["txid"]
|
||||
break
|
||||
elif is_choice_needed == "n":
|
||||
set_warriors_name(rpc_connection)
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"]
|
||||
break
|
||||
else:
|
||||
print("Please choose y or n !")
|
||||
else:
|
||||
print("No players available to select")
|
||||
input("Press [Enter] to continue...")
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"]
|
||||
else:
|
||||
print("No players available to select")
|
||||
input("Press [Enter] to continue...")
|
||||
newgame_regisration_txid = rogue_game_register(rpc_connection, new_game_txid)["txid"]
|
||||
while True:
|
||||
mempool = rpc_connection.getrawmempool()
|
||||
@@ -1143,7 +1151,7 @@ def rogue_newgame_singleplayer(rpc_connection, is_game_a_rogue=True):
|
||||
print("Let's wait a little bit more")
|
||||
time.sleep(5)
|
||||
pass
|
||||
if confirmations_amount < 2:
|
||||
if confirmations_amount < 1:
|
||||
print("Last keystroke not confirmed yet! Let's wait a little")
|
||||
time.sleep(10)
|
||||
else:
|
||||
@@ -1163,15 +1171,16 @@ def rogue_newgame_singleplayer(rpc_connection, is_game_a_rogue=True):
|
||||
is_bailout_needed = input("Do you want to make bailout now [y] or wait for one more block [n]? [y/n]: ")
|
||||
if is_bailout_needed == "y":
|
||||
bailout_info = rogue_bailout(rpc_connection, new_game_txid)
|
||||
while True:
|
||||
try:
|
||||
confirmations_amount = rpc_connection.getrawtransaction(bailout_info["txid"], 1)["confirmations"]
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Bailout not on blockchain yet. Let's wait a little bit more")
|
||||
time.sleep(20)
|
||||
pass
|
||||
if is_game_a_rogue:
|
||||
while True:
|
||||
try:
|
||||
confirmations_amount = rpc_connection.getrawtransaction(bailout_info["txid"], 1)["confirmations"]
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Bailout not on blockchain yet. Let's wait a little bit more")
|
||||
time.sleep(20)
|
||||
pass
|
||||
break
|
||||
elif is_bailout_needed == "n":
|
||||
game_end_height = int(rpc_connection.getinfo()["blocks"])
|
||||
|
||||
Reference in New Issue
Block a user