Hush Full Node software. We were censored from Github, this is where all development happens now. https://hush.is
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

807 lines
27 KiB

6 years ago
/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
6 years ago
#include "cJSON.c"
6 years ago
6 years ago
char hexbyte(int32_t c)
{
c &= 0xf;
if ( c < 10 )
return('0'+c);
else if ( c < 16 )
return('a'+c-10);
else return(0);
}
int32_t _unhex(char c)
{
if ( c >= '0' && c <= '9' )
return(c - '0');
else if ( c >= 'a' && c <= 'f' )
return(c - 'a' + 10);
else if ( c >= 'A' && c <= 'F' )
return(c - 'A' + 10);
return(-1);
}
int32_t is_hexstr(char *str,int32_t n)
{
int32_t i;
if ( str == 0 || str[0] == 0 )
return(0);
for (i=0; str[i]!=0; i++)
{
if ( n > 0 && i >= n )
break;
if ( _unhex(str[i]) < 0 )
break;
}
if ( n == 0 )
return(i);
return(i == n);
}
int32_t unhex(char c)
{
int32_t hex;
if ( (hex= _unhex(c)) < 0 )
{
//printf("unhex: illegal hexchar.(%c)\n",c);
}
return(hex);
}
unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); }
int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex)
{
int32_t adjust,i = 0;
//printf("decode.(%s)\n",hex);
if ( is_hexstr(hex,n) <= 0 )
{
memset(bytes,0,n);
return(n);
}
if ( hex[n-1] == '\n' || hex[n-1] == '\r' )
hex[--n] = 0;
if ( hex[n-1] == '\n' || hex[n-1] == '\r' )
hex[--n] = 0;
if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) )
{
if ( n > 0 )
{
bytes[0] = unhex(hex[0]);
printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex));
}
bytes++;
hex++;
adjust = 1;
} else adjust = 0;
if ( n > 0 )
{
for (i=0; i<n; i++)
bytes[i] = _decode_hex(&hex[i*2]);
}
//bytes[i] = 0;
return(n + adjust);
}
int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len)
{
int32_t i;
if ( len <= 0 )
{
hexbytes[0] = 0;
return(1);
}
for (i=0; i<len; i++)
{
hexbytes[i*2] = hexbyte((message[i]>>4) & 0xf);
hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf);
//printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]);
}
hexbytes[len*2] = 0;
//printf("len.%ld\n",len*2+1);
return((int32_t)len*2+1);
}
long _stripwhite(char *buf,int accept)
{
int32_t i,j,c;
if ( buf == 0 || buf[0] == 0 )
return(0);
for (i=j=0; buf[i]!=0; i++)
{
buf[j] = c = buf[i];
if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') )
j++;
}
buf[j] = 0;
return(j);
}
char *clonestr(char *str)
{
char *clone;
if ( str == 0 || str[0] == 0 )
{
printf("warning cloning nullstr.%p\n",str);
//#ifdef __APPLE__
// while ( 1 ) sleep(1);
//#endif
str = (char *)"<nullstr>";
}
clone = (char *)malloc(strlen(str)+16);
strcpy(clone,str);
return(clone);
}
int32_t safecopy(char *dest,char *src,long len)
{
int32_t i = -1;
if ( src != 0 && dest != 0 && src != dest )
{
if ( dest != 0 )
memset(dest,0,len);
for (i=0; i<len&&src[i]!=0; i++)
dest[i] = src[i];
if ( i == len )
{
printf("safecopy: %s too long %ld\n",src,len);
//printf("divide by zero! %d\n",1/zeroval());
#ifdef __APPLE__
//getchar();
#endif
return(-1);
}
dest[i] = 0;
}
return(i);
}
6 years ago
char *bits256_str(char hexstr[65],bits256 x)
{
init_hexbytes_noT(hexstr,x.bytes,sizeof(x));
return(hexstr);
}
int64_t conv_floatstr(char *numstr)
{
double val,corr;
val = atof(numstr);
corr = (val < 0.) ? -0.50000000001 : 0.50000000001;
return((int64_t)(val * SATOSHIDEN + corr));
}
6 years ago
char *nonportable_path(char *str)
6 years ago
{
int32_t i;
for (i=0; str[i]!=0; i++)
if ( str[i] == '/' )
str[i] = '\\';
return(str);
}
6 years ago
char *portable_path(char *str)
6 years ago
{
#ifdef _WIN32
6 years ago
return(nonportable_path(str));
6 years ago
#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
}
6 years ago
void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
6 years ago
{
FILE *fp;
long filesize,buflen = *allocsizep;
uint8_t *buf = *bufp;
*lenp = 0;
if ( (fp= fopen(portable_path(fname),"rb")) != 0 )
6 years ago
{
fseek(fp,0,SEEK_END);
filesize = ftell(fp);
if ( filesize == 0 )
{
fclose(fp);
*lenp = 0;
6 years ago
printf("loadfile null size.(%s)\n",fname);
6 years ago
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);
}
6 years ago
void *filestr(long *allocsizep,char *_fname)
6 years ago
{
long filesize = 0; char *fname,*buf = 0; void *retptr;
*allocsizep = 0;
fname = malloc(strlen(_fname)+1);
strcpy(fname,_fname);
6 years ago
retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep);
6 years ago
free(fname);
return(retptr);
}
6 years ago
char *send_curl(char *url,char *fname)
6 years ago
{
6 years ago
long fsize; char curlstr[1024];
6 years ago
sprintf(curlstr,"curl --url \"%s\" > %s",url,fname);
6 years ago
system(curlstr);
6 years ago
return(filestr(&fsize,fname));
6 years ago
}
6 years ago
6 years ago
cJSON *get_urljson(char *url,char *fname)
6 years ago
{
6 years ago
char *jsonstr; cJSON *json = 0;
6 years ago
if ( (jsonstr= send_curl(url,fname)) != 0 )
6 years ago
{
6 years ago
//printf("(%s) -> (%s)\n",url,jsonstr);
6 years ago
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
6 years ago
//////////////////////////////////////////////
// start of dapp
//////////////////////////////////////////////
6 years ago
uint64_t get_btcusd()
6 years ago
{
6 years ago
cJSON *pjson,*bpi,*usd; uint64_t btcusd = 0;
6 years ago
if ( (pjson= get_urljson("http://api.coindesk.com/v1/bpi/currentprice.json","/tmp/oraclefeed.json")) != 0 )
6 years ago
{
if ( (bpi= jobj(pjson,"bpi")) != 0 && (usd= jobj(bpi,"USD")) != 0 )
6 years ago
{
btcusd = jdouble(usd,"rate_float") * SATOSHIDEN;
printf("BTC/USD %.4f\n",dstr(btcusd));
}
6 years ago
free_json(pjson);
6 years ago
}
6 years ago
return(btcusd);
}
char *REFCOIN_CLI;
cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2)
6 years ago
{
6 years ago
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[256];
sprintf(fname,"/tmp/oraclefeed.%s",method);
6 years ago
if ( acname[0] != 0 )
{
if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 )
printf("unexpected: refcoin.(%s) acname.(%s)\n",refcoin,acname);
6 years ago
sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,fname);
}
else if ( strcmp(refcoin,"KMD") == 0 )
sprintf(cmdstr,"./komodo-cli %s %s %s %s > %s\n",method,arg0,arg1,arg2,fname);
else if ( REFCOIN_CLI != 0 && REFCOIN_CLI[0] != 0 )
{
sprintf(cmdstr,"%s %s %s %s %s > %s\n",REFCOIN_CLI,method,arg0,arg1,arg2,fname);
6 years ago
printf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr);
}
6 years ago
system(cmdstr);
*retstrp = 0;
if ( (jsonstr= filestr(&fsize,fname)) != 0 )
{
6 years ago
//fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr);
6 years ago
if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 )
6 years ago
*retstrp = jsonstr;
else free(jsonstr);
}
return(retjson);
}
bits256 komodobroadcast(char *refcoin,char *acname,cJSON *hexjson)
6 years ago
{
6 years ago
char *hexstr,*retstr,str[65]; cJSON *retjson; bits256 txid;
memset(txid.bytes,0,sizeof(txid));
6 years ago
if ( (hexstr= jstr(hexjson,"hex")) != 0 )
{
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"sendrawtransaction",hexstr,"","")) != 0 )
6 years ago
{
6 years ago
//fprintf(stderr,"broadcast.(%s)\n",jprint(retjson,0));
6 years ago
free_json(retjson);
6 years ago
}
6 years ago
else if ( retstr != 0 )
{
6 years ago
if ( strlen(retstr) >= 64 )
{
retstr[64] = 0;
decode_hex(txid.bytes,32,retstr);
}
6 years ago
fprintf(stderr,"broadcast %s txid.(%s)\n",acname,bits256_str(str,txid));
6 years ago
free(retstr);
}
}
6 years ago
return(txid);
6 years ago
}
bits256 sendtoaddress(char *refcoin,char *acname,char *destaddr,int64_t satoshis)
{
char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid;
memset(txid.bytes,0,sizeof(txid));
sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"sendtoaddress",destaddr,numstr,"")) != 0 )
{
fprintf(stderr,"unexpected sendrawtransaction json.(%s)\n",jprint(retjson,0));
free_json(retjson);
}
else if ( retstr != 0 )
{
if ( strlen(retstr) >= 64 )
{
retstr[64] = 0;
decode_hex(txid.bytes,32,retstr);
}
fprintf(stderr,"sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid));
free(retstr);
}
return(txid);
}
int32_t get_coinheight(char *refcoin,char *acname)
{
6 years ago
cJSON *retjson; char *retstr; int32_t height=0;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockchaininfo","","","")) != 0 )
{
height = jint(retjson,"blocks");
free_json(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"%s get_coinheight.(%s) error.(%s)\n",refcoin,acname,retstr);
free(retstr);
}
6 years ago
return(height);
}
bits256 get_coinblockhash(char *refcoin,char *acname,int32_t height)
{
cJSON *retjson; char *retstr,heightstr[32]; bits256 hash;
memset(hash.bytes,0,sizeof(hash));
6 years ago
sprintf(heightstr,"%d",height);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockhash",heightstr,"","")) != 0 )
{
fprintf(stderr,"unexpected blockhash json.(%s)\n",jprint(retjson,0));
free_json(retjson);
}
else if ( retstr != 0 )
{
6 years ago
if ( strlen(retstr) >= 64 )
6 years ago
{
retstr[64] = 0;
decode_hex(hash.bytes,32,retstr);
6 years ago
}
free(retstr);
}
return(hash);
}
bits256 get_coinmerkleroot(char *refcoin,char *acname,bits256 blockhash)
{
cJSON *retjson; char *retstr,str[65]; bits256 merkleroot;
6 years ago
memset(merkleroot.bytes,0,sizeof(merkleroot));
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockheader",bits256_str(str,blockhash),"","")) != 0 )
{
merkleroot = jbits256(retjson,"merkleroot");
6 years ago
//fprintf(stderr,"got merkleroot.(%s)\n",bits256_str(str,merkleroot));
free_json(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"%s %s get_coinmerkleroot error.(%s)\n",refcoin,acname,retstr);
free(retstr);
}
6 years ago
return(merkleroot);
}
int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *merklerootp,int32_t prevheight)
{
int32_t height = 0; char str[65];
if ( prevheight == 0 )
height = get_coinheight(refcoin,acname) - 20;
else height = prevheight + 1;
if ( height > 0 )
{
*blockhashp = get_coinblockhash(refcoin,acname,height);
6 years ago
if ( bits256_nonz(*blockhashp) != 0 )
{
*merklerootp = get_coinmerkleroot(refcoin,acname,*blockhashp);
6 years ago
if ( bits256_nonz(*merklerootp) != 0 )
return(height);
}
}
6 years ago
memset(blockhashp,0,sizeof(*blockhashp));
memset(merklerootp,0,sizeof(*merklerootp));
return(0);
}
cJSON *get_gatewayspending(char *refcoin,char *acname,char *oraclestxidstr)
6 years ago
{
cJSON *retjson; char *retstr;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewayspending",oraclestxidstr,refcoin,"")) != 0 )
6 years ago
{
//printf("pending.(%s)\n",jprint(retjson,0));
6 years ago
return(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"%s get_gatewayspending.(%s) error.(%s)\n",refcoin,acname,retstr);
6 years ago
free(retstr);
}
return(0);
}
cJSON *get_rawmempool(char *refcoin,char *acname)
6 years ago
{
cJSON *retjson; char *retstr;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getrawmempool","","","")) != 0 )
6 years ago
{
6 years ago
//printf("mempool.(%s)\n",jprint(retjson,0));
6 years ago
return(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"get_rawmempool.(%s) error.(%s)\n",acname,retstr);
free(retstr);
}
return(0);
}
cJSON *get_addressutxos(char *refcoin,char *acname,char *coinaddr)
{
cJSON *retjson; char *retstr,jsonbuf[256];
if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 )
printf("warning: assumes %s has addressindex enabled\n",refcoin);
6 years ago
sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getaddressutxos",jsonbuf,"","")) != 0 )
{
6 years ago
//printf("addressutxos.(%s)\n",jprint(retjson,0));
return(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"get_addressutxos.(%s) error.(%s)\n",acname,retstr);
free(retstr);
}
return(0);
}
cJSON *get_rawtransaction(char *refcoin,char *acname,bits256 txid)
{
cJSON *retjson; char *retstr,str[65];
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getrawtransaction",bits256_str(str,txid),"1","")) != 0 )
{
return(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"get_rawtransaction.(%s) error.(%s)\n",acname,retstr);
free(retstr);
}
return(0);
}
void gatewaysmarkdone(char *refcoin,char *acname,bits256 txid)
6 years ago
{
6 years ago
char str[65],*retstr; cJSON *retjson;
6 years ago
printf("spend %s %s/v2 as marker\n",acname,bits256_str(str,txid));
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysmarkdone",bits256_str(str,txid),"","")) != 0 )
6 years ago
{
6 years ago
komodobroadcast(refcoin,acname,retjson);
6 years ago
free_json(retjson);
}
else if ( retstr != 0 )
{
printf("error parsing gatewaysmarkdone.(%s)\n",retstr);
free(retstr);
}
6 years ago
}
int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr)
{
6 years ago
cJSON *txobj,*vouts,*vout,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numvouts,retval = 0;
if ( (txobj= get_rawtransaction(refcoin,acname,txid)) != 0 )
{
if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 )
{
for (i=0; i<numvouts; i++)
{
vout = jitem(vouts,i);
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
{
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 )
{
for (j=0; j<n; j++)
{
addr = jstri(addresses,j);
if ( strcmp(addr,coinaddr) == 0 )
{
6 years ago
//fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i);
retval = 1;
}
}
}
}
}
}
free_json(txobj);
}
return(retval);
}
int32_t coinaddrexists(char *refcoin,char *acname,char *coinaddr)
{
cJSON *array; bits256 txid; int32_t i,n,num=0;
if ( (array= get_addressutxos(refcoin,acname,coinaddr)) != 0 )
{
num = cJSON_GetArraySize(array);
free_json(array);
} else return(-1);
if ( num == 0 )
{
if ( (array= get_rawmempool(refcoin,acname)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) != 0 )
{
for (i=0; i<n; i++)
{
txid = jbits256i(array,i);
if ( tx_has_voutaddress(refcoin,acname,txid,coinaddr) > 0 )
{
num = 1;
break;
}
}
}
free_json(array);
} else return(-1);
}
return(num);
}
void update_gatewayspending(char *refcoin,char *acname,char *oraclestxidstr)
6 years ago
{
// check queue to prevent duplicate
// check KMD chain and mempool for txidaddr
// if txidaddr exists properly, spend the marker (txid.2)
// create withdraw tx and sign it
/// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2)
/// if not enough sigs, post partially signed to acname with marker2
6 years ago
// monitor marker2, for the partially signed withdraws
6 years ago
cJSON *retjson,*pending,*item; char str[65],*coinstr,*txidaddr,*signeraddr,*withdrawaddr; int32_t i,n,retval,processed = 0; bits256 txid,withtxid,origtxid; int64_t satoshis;
6 years ago
if ( (retjson= get_gatewayspending("KMD",acname,oraclestxidstr)) != 0 )
6 years ago
{
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,refcoin) == 0 )
6 years ago
{
if ( (pending= jarray(&n,retjson,"pending")) != 0 )
{
for (i=0; i<n; i++)
{
if ( processed != 0 ) // avoid out of utxo conditions
break;
6 years ago
item = jitem(pending,i);
6 years ago
origtxid = jbits256(item,"txid");
6 years ago
//process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"}
if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 )
6 years ago
{
6 years ago
if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && (retval= coinaddrexists("KMD",acname,txidaddr)) == 0 )
6 years ago
{
// this is less errors but more expensive: ./komodo-cli z_sendmany "signeraddr" '[{"address":"<txidaddr>","amount":0.0001},{"address":"<withdrawaddr>","amount":<withamount>}]'
txid = sendtoaddress("KMD",acname,txidaddr,10000);
6 years ago
if ( bits256_nonz(txid) != 0 && coinaddrexists("KMD",acname,txidaddr) > 0 )
{
6 years ago
// the actual withdraw
withtxid = sendtoaddress(refcoin,"",withdrawaddr,satoshis);
if ( bits256_nonz(withtxid) != 0 )
{
6 years ago
fprintf(stderr,"withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
6 years ago
gatewaysmarkdone("KMD",acname,origtxid);
processed++;
}
else
{
6 years ago
fprintf(stderr,"ERROR withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
}
} else fprintf(stderr,"error sending %s txidaddr.%s -> %s exists.%d\n",acname,txidaddr,bits256_str(str,txid),coinaddrexists(refcoin,acname,txidaddr));
6 years ago
}
else if ( retval > 0 )
6 years ago
{
6 years ago
fprintf(stderr,"already did withdraw %s %s %.8f processed\n",refcoin,withdrawaddr,(double)satoshis/SATOSHIDEN);
6 years ago
gatewaysmarkdone("KMD",acname,origtxid);
6 years ago
}
}
6 years ago
}
}
}
free_json(retjson);
}
}
int32_t get_oracledata(char *refcoin,char *acname,int32_t prevheight,char *hexstr,int32_t maxsize,char *format)
{
6 years ago
int32_t i; uint32_t height; uint64_t price; bits256 blockhash,merkleroot;
hexstr[0] = 0;
if ( format[0] == 'L' || format[0] == 'l' )
{
if ( (price= get_btcusd()) != 0 )
{
for (i=0; i<8; i++)
sprintf(&hexstr[i*2],"%02x",(uint8_t)((price >> (i*8)) & 0xff));
hexstr[16] = 0;
return(16);
}
}
else if ( strcmp(format,"Ihh") == 0 )
{
if ( (height= get_coinheader(refcoin,acname,&blockhash,&merkleroot,prevheight)) > prevheight )
{
for (i=0; i<4; i++)
sprintf(&hexstr[i*2],"%02x",(uint8_t)((height >> (i*8)) & 0xff));
6 years ago
for (i=31; i>=0; i--)
6 years ago
sprintf(&hexstr[8 + (31-i)*2],"%02x",blockhash.bytes[i]);
6 years ago
for (i=31; i>=0; i--)
6 years ago
sprintf(&hexstr[8 + 64 + (31-i)*2],"%02x",merkleroot.bytes[i]);
hexstr[8 + 64*2] = 0;
return(height);
}
}
return(0);
}
6 years ago
/*
oraclescreate "BTCUSD" "coindeskpricedata" "L" -> 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3
oraclesregister 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 1000000 -> 11c54d4ab17293217276396e27d86f714576ff55a3300dac34417047825edf93
oraclessubscribe 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 1.5 -> ce4e4afa53765b11a74543dacbd3174a93f33f12bb94cdc080c2c023726b5838
oraclesdata 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 000000ff00000000 -> e8a8c897e97389dcac31d81b617ab73a829110bd5c6f99f9f533b9c0e22700d0
6 years ago
oraclessamples 4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3 90ff8813a93b5b2615ec43974ff4fc91e4373dfd672d995676c43ff2dcda1010 10 ->
6 years ago
{
"result": "success",
"samples": [
[
"4278190080"
]
]
}
6 years ago
oraclescreate test testsformat s -> 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff
oraclesregister -> 7825ad75ba854ab12868f7d2e06b4061903687fe93f41a2a99202a6b9ca3c029
oraclessubscribe 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 1.5 -> faf8a6676f6389abad9e7f397015d200395c9f8a24c4ded291d83e6265b2f4d1
oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 03404040 -> e8a8c897e97389dcac31d81b617ab73a829110bd5c6f99f9f533b9c0e22700d0
6 years ago
*/
6 years ago
// ./a.out AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e
6 years ago
6 years ago
int32_t main(int32_t argc,char **argv)
{
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,n,height,prevheight = 0; char *format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
if ( argc < 6 )
{
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
return(-1);
}
printf("Powered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
acname = argv[1];
oraclestr = argv[2];
pkstr = argv[3];
format = argv[4];
6 years ago
bindtxidstr = argv[5];
if ( argc > 6 )
6 years ago
REFCOIN_CLI = argv[6];
6 years ago
else REFCOIN_CLI = "./komodo-cli";
if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' )
{
printf("only formats of L and Ihh are supported now\n");
return(-1);
}
6 years ago
acheight = 0;
6 years ago
refcoin[0] = 0;
6 years ago
while ( 1 )
{
retstr = 0;
if ( (refcoin[0] == 0 || prevheight < (get_coinheight(refcoin,"") - 10)) && (clijson= get_komodocli("KMD",&retstr,acname,"oraclesinfo",oraclestr,"","")) != 0 )
6 years ago
{
6 years ago
if ( refcoin[0] == 0 && jstr(clijson,"name") != 0 )
{
6 years ago
strcpy(refcoin,jstr(clijson,"name"));
if ( strcmp("KMD",refcoin) != 0 && argc != 7 )
{
printf("need to specify path to refcoin's cli as last argv\n");
exit(0);
}
printf("set refcoin <- %s [%s]\n",refcoin,REFCOIN_CLI);
6 years ago
} //else printf("clijson.(%s)\n",jprint(clijson,0));
6 years ago
if ( (regjson= jarray(&n,clijson,"registered")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(regjson,i);
6 years ago
if ( (pubstr= jstr(item,"publisher")) != 0 && strcmp(pkstr,pubstr) == 0 )
6 years ago
{
if ( (height= get_oracledata(refcoin,"",prevheight,hexstr,sizeof(hexstr),"Ihh")) != 0 )
6 years ago
{
if ( (clijson2= get_komodocli("KMD",&retstr2,acname,"oraclesdata",oraclestr,hexstr,"")) != 0 )
{
6 years ago
//printf("data.(%s)\n",jprint(clijson2,0));
6 years ago
txid = komodobroadcast("KMD",acname,clijson2);
6 years ago
if ( bits256_nonz(txid) != 0 )
{
prevheight = height;
acheight = get_coinheight(refcoin,"");
printf("%s ht.%d <- %s\n",refcoin,height,hexstr);
update_gatewayspending(refcoin,acname,bindtxidstr);
6 years ago
}
free_json(clijson2);
}
else if ( retstr2 != 0 )
{
printf("error parsing oraclesdata.(%s)\n",retstr2);
free(retstr2);
}
6 years ago
}
6 years ago
break;
}
}
}
free_json(clijson);
}
if ( retstr != 0 )
{
printf("got json parse error.(%s)\n",retstr);
free(retstr);
}
6 years ago
sleep(10);
6 years ago
// best check is for txid to not be in mempool, ie confirmed
6 years ago
}
6 years ago
return(0);
}