Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
8c49b49f05
  1. 372
      basilisk/basilisk.c
  2. 10
      basilisk/basilisk.h
  3. 296
      basilisk/basilisk_bitcoin.c
  4. 26
      basilisk/basilisk_ether.c
  5. 26
      basilisk/basilisk_lisk.c
  6. 26
      basilisk/basilisk_nxt.c
  7. 26
      basilisk/basilisk_waves.c
  8. 4
      iguana/iguana777.h
  9. 4
      includes/iguana_apideclares.h

372
basilisk/basilisk.c

@ -15,7 +15,7 @@
#include "../iguana/iguana777.h" #include "../iguana/iguana777.h"
char *basilisk_finish(struct basilisk_item *ptr,int32_t besti) char *basilisk_finish(struct basilisk_item *ptr,int32_t besti,char *errstr)
{ {
int32_t i; char *retstr = 0; int32_t i; char *retstr = 0;
for (i=0; i<ptr->numresults; i++) for (i=0; i<ptr->numresults; i++)
@ -24,10 +24,12 @@ char *basilisk_finish(struct basilisk_item *ptr,int32_t besti)
{ {
if ( ptr->results[i] != 0 ) if ( ptr->results[i] != 0 )
free(ptr->results[i]); free(ptr->results[i]);
} } else retstr = ptr->results[i];
else retstr = ptr->results[i];
ptr->results[i] = 0; ptr->results[i] = 0;
} }
if ( retstr == 0 )
retstr = clonestr(errstr);
ptr->retstr = retstr;
ptr->finished = (uint32_t)time(NULL); ptr->finished = (uint32_t)time(NULL);
return(retstr); return(retstr);
} }
@ -52,7 +54,18 @@ cJSON *basilisk_json(struct supernet_info *myinfo,cJSON *hexjson,uint32_t basili
return(retjson); return(retjson);
} }
cJSON *basilisk_resultsjson(struct supernet_info *myinfo,char *symbol,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,char *retstr) char *basilisk_results(uint32_t basilisktag,cJSON *valsobj)
{
cJSON *resultobj = cJSON_CreateObject();
jadd(resultobj,"vals",valsobj);
jaddstr(resultobj,"agent","basilisk");
jaddstr(resultobj,"method","result");
jaddnum(resultobj,"plaintext",1);
jaddnum(resultobj,"basilisktag",basilisktag);
return(jprint(resultobj,1));
}
/*cJSON *basilisk_resultsjson(struct supernet_info *myinfo,char *symbol,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,char *retstr)
{ {
cJSON *hexjson=0,*retjson=0; cJSON *hexjson=0,*retjson=0;
if ( retstr != 0 ) if ( retstr != 0 )
@ -72,7 +85,7 @@ cJSON *basilisk_resultsjson(struct supernet_info *myinfo,char *symbol,char *remo
retjson = cJSON_Parse(retstr); retjson = cJSON_Parse(retstr);
} }
return(retjson); return(retjson);
} }*/
#include "basilisk_bitcoin.c" #include "basilisk_bitcoin.c"
#include "basilisk_nxt.c" #include "basilisk_nxt.c"
@ -115,23 +128,33 @@ int32_t basilisk_submit(struct supernet_info *myinfo,cJSON *reqjson,int32_t time
return(n); return(n);
} }
struct basilisk_item *basilisk_issue(struct supernet_info *myinfo,cJSON *hexjson,int32_t timeoutmillis,int32_t fanout,int32_t minresults,uint32_t basilisktag) struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,char *methodstr,char *symbol,cJSON *vals,int32_t timeoutmillis,int32_t fanout,int32_t minresults,uint32_t basilisktag)
{ {
double expiration; struct basilisk_item *ptr; double expiration; struct basilisk_item *ptr; cJSON *hexjson;
ptr = calloc(1,sizeof(*ptr));
if ( basilisktag == 0 ) if ( basilisktag == 0 )
basilisktag = rand(); basilisktag = rand();
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"agent","basilisk");
jaddnum(hexjson,"basilisktag",basilisktag);
jaddstr(hexjson,"method",methodstr);
jaddstr(hexjson,"activecoin",symbol);
if ( vals != 0 )
jadd(hexjson,"vals",jduplicate(vals));
printf("issue.(%s)\n",jprint(hexjson,0));
ptr = calloc(1,sizeof(*ptr));
ptr->basilisktag = basilisktag; ptr->basilisktag = basilisktag;
ptr->numrequired = minresults;
queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0); queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
if ( basilisk_submit(myinfo,hexjson,timeoutmillis,fanout,ptr) > 0 ) if ( basilisk_submit(myinfo,hexjson,timeoutmillis,fanout,ptr) > 0 )
{ {
if ( timeoutmillis >= 0 ) if ( timeoutmillis > 0 )
{ {
expiration = OS_milliseconds() + ((timeoutmillis == 0) ? BASILISK_TIMEOUT : timeoutmillis); expiration = OS_milliseconds() + ((timeoutmillis == 0) ? BASILISK_TIMEOUT : timeoutmillis);
while ( OS_milliseconds() < expiration && ptr->finished == 0 && ptr->numresults < minresults ) while ( OS_milliseconds() < expiration && ptr->finished == 0 && ptr->numresults < ptr->numrequired )
usleep(timeoutmillis/100 + 1); usleep(timeoutmillis/100 + 1);
} }
} }
free_json(hexjson);
return(ptr); return(ptr);
} }
@ -142,7 +165,9 @@ void basilisk_functions(struct iguana_info *coin)
case IGUANA_PROTOCOL_BITCOIN: case IGUANA_PROTOCOL_BITCOIN:
coin->basilisk_balances = basilisk_bitcoinbalances; coin->basilisk_balances = basilisk_bitcoinbalances;
coin->basilisk_rawtx = basilisk_bitcoinrawtx; coin->basilisk_rawtx = basilisk_bitcoinrawtx;
coin->basilisk_rawtxmetric = basilisk_bitcoin_rawtxmetric;
coin->basilisk_value = basilisk_bitcoinvalue; coin->basilisk_value = basilisk_bitcoinvalue;
coin->basilisk_valuemetric = basilisk_bitcoin_valuemetric;
break; break;
/*case IGUANA_PROTOCOL_IOTA: /*case IGUANA_PROTOCOL_IOTA:
coin->basilisk_balances = basilisk_iotabalances; coin->basilisk_balances = basilisk_iotabalances;
@ -167,70 +192,164 @@ void basilisk_functions(struct iguana_info *coin)
} }
} }
char *basilisk_issuecmd(basilisk_func func,struct supernet_info *myinfo,char *remoteaddr,uint32_t basilisktag,char *symbol,int32_t timeoutmillis,cJSON *vals) int32_t basilisk_besti(struct basilisk_item *ptr)
{ {
struct iguana_info *coin; char *retstr=0; int32_t i,besti = -1; double metric,bestmetric;
if ( basilisktag == 0 ) if ( ptr->metricdir > 0 )
OS_randombytes((uint8_t *)&basilisktag,sizeof(basilisktag)); bestmetric = -1.;
if ( (coin= iguana_coinfind(symbol)) != 0 ) else if ( ptr->metricdir < 0 )
bestmetric = 1.;
else bestmetric = 0.;
for (i=0; i<ptr->numresults; i++)
{ {
if ( func != 0 ) if ( (metric= ptr->metrics[i]) != 0. )
{ {
if ( (retstr= (*func)(myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) if ( (ptr->metricdir < 0 && (bestmetric > 0. || metric < bestmetric)) || (ptr->metricdir > 0 && (bestmetric < 0. || metric > bestmetric)) || (ptr->metricdir == 0 && bestmetric == 0.) )
{ {
//retjson = basilisk_resultsjson(myinfo,symbol,remoteaddr,basilisktag,timeoutmillis,retstr); bestmetric = metric;
//free(retstr); besti = i;
//retstr = jprint(retjson,1);
printf("issue ret.(%s)\n",retstr);
} }
} }
} }
if ( besti >= 0 )
{
for (i=0; i<ptr->numresults; i++)
if ( fabs(ptr->metrics[i] - bestmetric) < SMALLVAL )
ptr->numexact++;
}
return(besti);
}
char *basilisk_block(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,struct basilisk_item *Lptr,struct basilisk_item *ptr)
{
int32_t besti,i,j,numvalid; char *retstr = 0,*errstr; struct iguana_peer *addr;
if ( ptr == Lptr )
{
if ( (retstr= Lptr->retstr) == 0 )
retstr = clonestr("{\"result\":\"null return from local basilisk_issuecmd\"}");
}
else
{
if ( ptr->numrequired == 0 )
ptr->numrequired = 1;
while ( OS_milliseconds() < ptr->expiration )
{
if ( (numvalid= ptr->numresults) >= ptr->numrequired )
{
for (i=numvalid=0; i<ptr->numresults; i++)
{
if ( ptr->metrics[i] != 0. )
numvalid++;
}
}
if ( numvalid < ptr->numrequired )
{
usleep(10000);
continue;
}
if ( ptr->uniqueflag == 0 && ptr->numexact <= (ptr->numresults >> 1) )
besti = -1, errstr = "{\"error\":\"basilisk non-consensus results\"}";
else besti = basilisk_besti(ptr), errstr = "{\"error\":\"basilisk no valid results\"}";
if ( (retstr= basilisk_finish(ptr,besti,errstr)) != 0 && remoteaddr != 0 && remoteaddr[0] != 0 && strcmp(remoteaddr,"127.0.0.1") != 0 )
{
for (j=0; j<IGUANA_MAXCOINS; j++)
{
if ( (coin= Coins[j]) == 0 )
continue;
for (i=0; i<IGUANA_MAXPEERS; i++)
{
if ( (addr= &coin->peers.active[i]) != 0 && addr->usock >= 0 )
{
if ( addr->supernet != 0 && strcmp(addr->ipaddr,remoteaddr) == 0 )
{
printf("send back.%d basilisk_result addr->supernet.%u to (%s).%d\n",(int32_t)strlen(retstr),addr->supernet,addr->ipaddr,addr->A.port);
iguana_send_supernet(addr,retstr,0);
return(retstr);
}
}
if ( 0 && addr->ipbits != 0 )
printf("i.%d (%s) vs (%s) %s\n",i,addr->ipaddr,remoteaddr,coin->symbol);
}
}
}
}
retstr = basilisk_finish(ptr,-1,"{\"error\":\"basilisk timeout\"}");
}
return(retstr); return(retstr);
} }
#include "../includes/iguana_apidefs.h" struct basilisk_item *basilisk_issuecmd(struct basilisk_item *Lptr,basilisk_func func,basilisk_metricfunc metricfunc,struct supernet_info *myinfo,char *remoteaddr,uint32_t basilisktag,char *symbol,int32_t timeoutmillis,cJSON *vals)
#include "../includes/iguana_apideclares.h" {
struct iguana_info *coin; struct basilisk_item *ptr;
memset(Lptr,0,sizeof(*Lptr));
if ( (coin= iguana_coinfind(symbol)) != 0 )
{
if ( func != 0 )
{
if ( (ptr= (*func)(Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
{
if ( (ptr->metricfunc= metricfunc) != 0 )
ptr->vals = jduplicate(vals);
strcpy(ptr->symbol,symbol);
ptr->expiration = OS_milliseconds() + timeoutmillis;
return(ptr);
}
else Lptr->retstr = clonestr("{\"error\":\"error issuing basilisk command\"}");
} else Lptr->retstr = clonestr("{\"error\":\"null basilisk function\"}");
} else Lptr->retstr = clonestr("{\"error\":\"error missing coin\"}");
return(Lptr);
}
INT_ARRAY_STRING(basilisk,balances,lastheight,addresses,activecoin) char *basilisk_check(int32_t *timeoutmillisp,uint32_t *basilisktagp,char *symbol,cJSON *vals)
{ {
/*uint64_t amount,total = 0; cJSON *item,*result,*array,*retjson,*hexjson; int32_t i,n,minconf=0; char *retstr,*balancestr,*coinaddr; if ( symbol != 0 && symbol[0] != 0 && vals != 0 )
retjson = cJSON_CreateObject();
if ( activecoin != 0 && activecoin[0] != 0 && (coin= iguana_coinfind(activecoin)) != 0 )
{ {
xxx if ( *basilisktagp == 0 )
jadd(retjson,"balances",array); *basilisktagp = rand();
jaddnum(retjson,"total",dstr(total)); if ( (*timeoutmillisp= jint(vals,"timeout")) < 0 )
if ( lastheight != 0 ) *timeoutmillisp = BASILISK_TIMEOUT;
jaddnum(retjson,"lastheight",lastheight); return(0);
if ( remoteaddr != 0 && remoteaddr[0] != 0 && strcmp(remoteaddr,"127.0.0.1") != 0 ) } else return(clonestr("{\"error\":\"missing activecoin or vals\"}"));
}
char *basilisk_standardcmd(struct supernet_info *myinfo,char *activecoin,char *remoteaddr,uint32_t basilisktag,cJSON *vals,basilisk_func func,basilisk_metricfunc metric)
{
char *retstr; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; struct iguana_info *coin;
if ( (retstr= basilisk_check(&timeoutmillis,&basilisktag,activecoin,vals)) == 0 )
{ {
//printf("remote req.(%s)\n",jprint(retjson,0)); if ( (coin= iguana_coinfind(activecoin)) != 0 )
hexjson = cJSON_CreateObject(); {
jaddstr(hexjson,"rawtx",jprint(retjson,1)); if ( (ptr= basilisk_issuecmd(&Lptr,func,metric,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)) != 0 )
jaddstr(hexjson,"agent","iguana"); return(basilisk_block(myinfo,coin,remoteaddr,&Lptr,ptr));
jaddstr(hexjson,"method","rawtx_result"); else return(clonestr("{\"error\":\"null return from basilisk_issuecmd\"}"));
jaddstr(hexjson,"activecoin",activecoin); } else return(clonestr("{\"error\":\"couldnt get coin\"}"));
jaddnum(hexjson,"basilisktag",lastheight); } else return(retstr);
retjson = iguana_json(myinfo,hexjson);
} else jaddstr(retjson,"result","success");
return(jprint(retjson,1));
}
else if ( remoteaddr == 0 || remoteaddr[0] == 0 || strcmp(remoteaddr,"127.0.0.1") == 0 )
{
if ( (retstr= basilisk_request_andwait(myinfo,&myinfo->basiliskQ,0,json,lastheight,juint(json,"timeout"))) == 0 )
return(clonestr("{\"error\":\"timeout waiting for remote request\"}"));
else return(retstr);
} else return(clonestr("{\"error\":\"invalid remoterequest when not relaynode\"}"));
} else */return(clonestr("{\"error\":\"invalid request for inactive coin\"}"));
} }
INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin) #include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
INT_ARRAY_STRING(basilisk,balances,basilisktag,vals,activecoin)
{
if ( (coin= iguana_coinfind(activecoin)) != 0 )
return(basilisk_standardcmd(myinfo,activecoin,remoteaddr,basilisktag,vals,coin->basilisk_balances,coin->basilisk_balancesmetric));
else return(clonestr("{\"error\":\"cant find missing coin\"}"));
}
INT_ARRAY_STRING(basilisk,value,basilisktag,vals,activecoin)
{
if ( (coin= iguana_coinfind(activecoin)) != 0 )
return(basilisk_standardcmd(myinfo,activecoin,remoteaddr,basilisktag,vals,coin->basilisk_value,coin->basilisk_valuemetric));
else return(clonestr("{\"error\":\"cant find missing coin\"}"));
}
char *basilisk_checkrawtx(int32_t *timeoutmillisp,uint32_t *basilisktagp,char *symbol,cJSON *vals)
{ {
cJSON *addresses=0; char *changeaddr,*spendscriptstr; int32_t i,n,timeoutmillis; cJSON *addresses=0; char *changeaddr,*spendscriptstr; int32_t i,n;
*timeoutmillisp = -1;
changeaddr = jstr(vals,"changeaddr"); changeaddr = jstr(vals,"changeaddr");
spendscriptstr = jstr(vals,"spendscript"); spendscriptstr = jstr(vals,"spendscript");
addresses = jarray(&n,vals,"addresses"); addresses = jarray(&n,vals,"addresses");
timeoutmillis = jint(vals,"timeout");
if ( addresses == 0 || changeaddr == 0 || changeaddr[0] == 0 ) if ( addresses == 0 || changeaddr == 0 || changeaddr[0] == 0 )
return(clonestr("{\"error\":\"invalid addresses[] or changeaddr\"}")); return(clonestr("{\"error\":\"invalid addresses[] or changeaddr\"}"));
else else
@ -239,53 +358,49 @@ INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin)
if ( strcmp(jstri(addresses,i),changeaddr) == 0 ) if ( strcmp(jstri(addresses,i),changeaddr) == 0 )
return(clonestr("{\"error\":\"changeaddr cant be in addresses[]\"}")); return(clonestr("{\"error\":\"changeaddr cant be in addresses[]\"}"));
} }
if ( spendscriptstr != 0 && spendscriptstr[0] != 0 && activecoin != 0 && activecoin[0] != 0 ) if ( spendscriptstr != 0 && spendscriptstr[0] != 0 )
{ return(basilisk_check(timeoutmillisp,basilisktagp,symbol,vals));
return(basilisk_issuecmd(coin->basilisk_rawtx,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)); else return(clonestr("{\"error\":\"missing spendscript\"}"));
}
return(clonestr("{\"error\":\"missing activecoin or spendscript\"}"));
} }
INT_ARRAY_STRING(basilisk,value,basilisktag,vals,activecoin) INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin)
{ {
int32_t timeoutmillis; char *retstr; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
if ( activecoin != 0 && activecoin[0] != 0 && vals != 0 ) if ( (retstr= basilisk_checkrawtx(&timeoutmillis,(uint32_t *)&basilisktag,activecoin,vals)) == 0 )
{ {
timeoutmillis = jint(vals,"timeout"); if ( (ptr= basilisk_issuecmd(&Lptr,coin->basilisk_rawtx,coin->basilisk_rawtxmetric,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)) != 0 )
return(basilisk_issuecmd(coin->basilisk_value,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)); {
} if ( (ptr->numrequired= juint(vals,"numrequired")) == 0 )
return(clonestr("{\"error\":\"missing activecoin\"}")); ptr->numrequired = 1;
ptr->uniqueflag = 1;
return(basilisk_block(myinfo,coin,remoteaddr,&Lptr,ptr));
} else return(clonestr("{\"error\":\"error issuing basilisk rawtx\"}"));
} else return(retstr);
} }
INT_AND_ARRAY(basilisk,result,basilisktag,vals) INT_AND_ARRAY(basilisk,result,basilisktag,vals)
{ {
struct basilisk_item *ptr; char *hexmsg=0; struct basilisk_item *ptr;
if ( vals != 0 && (hexmsg= jstr(vals,"hexmsg")) != 0 ) if ( vals != 0 )
{ {
ptr = calloc(1,sizeof(*ptr)); ptr = calloc(1,sizeof(*ptr));
ptr->results[0] = jprint(vals,0); ptr->retstr = jprint(vals,0);
ptr->basilisktag = basilisktag; ptr->basilisktag = basilisktag;
ptr->numresults = 1; printf("Q results vals.(%s)\n",ptr->retstr);
//printf("Q results hexmsg.(%s) args.(%s)\n",hexmsg,jprint(args,0));
queue_enqueue("resultsQ",&myinfo->basilisks.resultsQ,&ptr->DL,0); queue_enqueue("resultsQ",&myinfo->basilisks.resultsQ,&ptr->DL,0);
return(clonestr("{\"result\":\"queued basilisk return\"}")); return(clonestr("{\"result\":\"queued basilisk return\"}"));
} else printf("null vals.(%s) or no hexmsg.%p\n",jprint(vals,0),hexmsg); } else printf("null vals.(%s) or no hexmsg.%p\n",jprint(vals,0),vals);
return(clonestr("{\"error\":\"no hexmsg to return\"}")); return(clonestr("{\"error\":\"no hexmsg to return\"}"));
} }
#include "../includes/iguana_apiundefs.h" #include "../includes/iguana_apiundefs.h"
char *basilisk_hexmsg(struct supernet_info *myinfo,struct category_info *cat,void *ptr,int32_t len,char *remoteaddr) // incoming
char *basilisk_hexmsg(struct supernet_info *myinfo,struct category_info *cat,void *ptr,int32_t len,char *remoteaddr)
{ {
char *method="",*agent="",*retstr = 0,*tmpstr,*hexmsg; int32_t i,j,n,timeoutmillis; cJSON *array,*json,*valsobj; struct iguana_info *coin=0; struct iguana_peer *addr; uint32_t basilisktag; char *method="",*agent="",*retstr = 0,*tmpstr,*hexmsg; int32_t n; cJSON *array,*json,*valsobj; struct iguana_info *coin=0; uint32_t basilisktag;
array = 0; array = 0;
if ( (json= cJSON_Parse(ptr)) != 0 ) if ( (json= cJSON_Parse(ptr)) != 0 )
{ {
printf("basilisk.(%s)\n",jprint(json,0)); printf("basilisk.(%s)\n",jprint(json,0));
//basilisk.({"basilisktag":2955372280,"agent":"basilisk","method":"rawtx","vals":{"changeaddr":"1FNhoaBYzf7safMBjoCsJYgxtah3K95sep","addresses":["1Hgzt5xsnbfc8UTWqWKSTLRm5bEYHYBoCE"],"timeout":5000,"amount":"20000","spendscript":"76a914b7128d2ee837cf03e30a2c0e3e0181f7b9669bb688ac"},"basilisktag":2955372280})
// basilisk.({"agent":"basilisk","method":"rawtx","activecoin":"BTC","basilisktag":1398466607})
agent = jstr(json,"agent"); agent = jstr(json,"agent");
method = jstr(json,"method"); method = jstr(json,"method");
if ( agent != 0 && method != 0 && strcmp(agent,"SuperNET") == 0 && strcmp(method,"DHT") == 0 && (hexmsg= jstr(json,"hexmsg")) != 0 ) if ( agent != 0 && method != 0 && strcmp(agent,"SuperNET") == 0 && strcmp(method,"DHT") == 0 && (hexmsg= jstr(json,"hexmsg")) != 0 )
@ -294,6 +409,7 @@ char *basilisk_hexmsg(struct supernet_info *myinfo,struct category_info *cat,voi
tmpstr = calloc(1,n + 1); tmpstr = calloc(1,n + 1);
decode_hex((void *)tmpstr,n,hexmsg); decode_hex((void *)tmpstr,n,hexmsg);
free_json(json); free_json(json);
printf("NESTED.(%s)\n",tmpstr);
if ( (json= cJSON_Parse(tmpstr)) == 0 ) if ( (json= cJSON_Parse(tmpstr)) == 0 )
{ {
printf("couldnt parse decoded hexmsg.(%s)\n",tmpstr); printf("couldnt parse decoded hexmsg.(%s)\n",tmpstr);
@ -307,9 +423,7 @@ char *basilisk_hexmsg(struct supernet_info *myinfo,struct category_info *cat,voi
basilisktag = juint(json,"basilisktag"); basilisktag = juint(json,"basilisktag");
if ( strcmp(agent,"basilisk") == 0 && (valsobj= jobj(json,"vals")) != 0 ) if ( strcmp(agent,"basilisk") == 0 && (valsobj= jobj(json,"vals")) != 0 )
{ {
if ( jobj(json,"timeout") != 0 ) if ( jobj(valsobj,"coin") != 0 )
timeoutmillis = jint(json,"timeout");
if ( valsobj != 0 && jobj(valsobj,"coin") != 0 )
coin = iguana_coinfind(jstr(valsobj,"coin")); coin = iguana_coinfind(jstr(valsobj,"coin"));
else if ( jstr(json,"activecoin") != 0 ) else if ( jstr(json,"activecoin") != 0 )
coin = iguana_coinfind(jstr(json,"activecoin")); coin = iguana_coinfind(jstr(json,"activecoin"));
@ -318,68 +432,39 @@ char *basilisk_hexmsg(struct supernet_info *myinfo,struct category_info *cat,voi
if ( coin->RELAYNODE != 0 || coin->VALIDATENODE != 0 ) if ( coin->RELAYNODE != 0 || coin->VALIDATENODE != 0 )
{ {
if ( strcmp(method,"rawtx") == 0 ) if ( strcmp(method,"rawtx") == 0 )
{ retstr = basilisk_rawtx(myinfo,coin,0,remoteaddr,basilisktag,valsobj,coin->symbol);
retstr = basilisk_issuecmd(coin->basilisk_rawtx,myinfo,remoteaddr,basilisktag,coin->symbol,timeoutmillis,valsobj);
}
else if ( strcmp(method,"balances") == 0 ) else if ( strcmp(method,"balances") == 0 )
{ retstr = basilisk_balances(myinfo,coin,0,remoteaddr,basilisktag,valsobj,coin->symbol);
retstr = basilisk_issuecmd(coin->basilisk_balances,myinfo,remoteaddr,basilisktag,coin->symbol,timeoutmillis,valsobj);
}
else if ( strcmp(method,"value") == 0 ) else if ( strcmp(method,"value") == 0 )
{ retstr = basilisk_value(myinfo,coin,0,remoteaddr,basilisktag,valsobj,coin->symbol);
retstr = basilisk_issuecmd(coin->basilisk_value,myinfo,remoteaddr,basilisktag,coin->symbol,timeoutmillis,valsobj); if ( retstr != 0 )
} free(retstr);
if ( retstr == 0 ) // should automatically send to remote requester
return(0);
//printf("basilisk will return.(%s)\n",retstr);
for (j=0; j<IGUANA_MAXCOINS; j++)
{
if ( (coin= Coins[j]) == 0 )
continue;
for (i=0; i<IGUANA_MAXPEERS; i++)
{
if ( (addr= &coin->peers.active[i]) != 0 && addr->usock >= 0 )
{
if ( addr->supernet != 0 && strcmp(addr->ipaddr,remoteaddr) == 0 )
{
printf("send back.%d basilisk_result addr->supernet.%u to (%s).%d\n",(int32_t)strlen(retstr),addr->supernet,addr->ipaddr,addr->A.port);
iguana_send_supernet(addr,retstr,0);
free_json(json);
return(retstr);
}
}
if ( 0 && addr->ipbits != 0 )
printf("i.%d (%s) vs (%s) %s\n",i,addr->ipaddr,remoteaddr,coin->symbol);
}
}
} }
else else
{ {
if ( strcmp(method,"result") == 0 ) if ( strcmp(method,"result") == 0 )
{ return(basilisk_result(myinfo,coin,0,remoteaddr,basilisktag,valsobj));
//printf("got rawtx.(%s)\n",jstr(valsobj,"hexmsg"));
return(basilisk_result(myinfo,coin,json,remoteaddr,basilisktag,valsobj));
}
} }
} }
} }
free_json(json);
} }
printf("unhandled bitcoin_hexmsg.(%d) from %s (%s/%s)\n",len,remoteaddr,agent,method); printf("unhandled bitcoin_hexmsg.(%d) from %s (%s/%s)\n",len,remoteaddr,agent,method);
free_json(json);
return(retstr); return(retstr);
} }
void basilisks_loop(void *arg) void basilisks_loop(void *arg)
{ {
struct basilisk_item *ptr,*tmp,*pending; int32_t i,flag,n; struct supernet_info *myinfo = arg; basilisk_metricfunc metricfunc; struct basilisk_item *ptr,*tmp,*pending; int32_t i,flag,n; struct supernet_info *myinfo = arg;
uint8_t *blockspace; struct OS_memspace RAWMEM; struct iguana_info *coin; //uint8_t *blockspace; struct OS_memspace RAWMEM;
memset(&RAWMEM,0,sizeof(RAWMEM)); //memset(&RAWMEM,0,sizeof(RAWMEM));
blockspace = calloc(1,IGUANA_MAXPACKETSIZE); //blockspace = calloc(1,IGUANA_MAXPACKETSIZE);
while ( 1 ) while ( 1 )
{ {
for (i=0; i<IGUANA_MAXCOINS; i++) //for (i=0; i<IGUANA_MAXCOINS; i++)
if ( (coin= Coins[i]) != 0 && coin->RELAYNODE == 0 && coin->VALIDATENODE == 0 && coin->active != 0 && coin->chain->userpass[0] != 0 && coin->MAXPEERS == 1 ) // if ( (coin= Coins[i]) != 0 && coin->RELAYNODE == 0 && coin->VALIDATENODE == 0 && coin->active != 0 && coin->chain->userpass[0] != 0 && coin->MAXPEERS == 1 )
basilisk_bitcoinscan(coin,blockspace,&RAWMEM); // basilisk_bitcoinscan(coin,blockspace,&RAWMEM);
if ( (ptr= queue_dequeue(&myinfo->basilisks.submitQ,0)) != 0 ) if ( (ptr= queue_dequeue(&myinfo->basilisks.submitQ,0)) != 0 )
{ {
if ( ptr->finished == 0 ) if ( ptr->finished == 0 )
@ -394,8 +479,11 @@ void basilisks_loop(void *arg)
{ {
if ( (n= pending->numresults) < sizeof(pending->results)/sizeof(*pending->results) ) if ( (n= pending->numresults) < sizeof(pending->results)/sizeof(*pending->results) )
{ {
pending->results[n] = ptr->results[0]; pending->results[n] = ptr->retstr;
pending->numresults++; pending->numresults++;
if ( (metricfunc= ptr->metricfunc) == 0 )
pending->metrics[n] = n + 1;
else pending->metrics[n] = (*metricfunc)(myinfo,pending,pending->results[n]);
} }
} }
free(ptr); free(ptr);
@ -404,14 +492,36 @@ void basilisks_loop(void *arg)
else else
{ {
flag = 0; flag = 0;
HASH_ITER(hh,myinfo->basilisks.issued,ptr,tmp) HASH_ITER(hh,myinfo->basilisks.issued,pending,tmp)
{ {
if ( ptr->finished != 0 ) if ( pending->finished != 0 && pending->parent == 0 )
{ {
HASH_DELETE(hh,myinfo->basilisks.issued,ptr); HASH_DELETE(hh,myinfo->basilisks.issued,pending);
free(ptr); if ( pending->vals != 0 )
free_json(pending->vals);
if ( pending->dependents != 0 )
free(pending->dependents);
free(pending);
flag++; flag++;
} }
else if ( OS_milliseconds() > pending->expiration )
{
pending->finished = (uint32_t)time(NULL);
pending->retstr = clonestr("{\"error\":\"basilisk timeout\"}");
for (i=0; i<pending->numresults; i++)
if ( (metricfunc= pending->metricfunc) != 0 )
pending->metrics[i] = (*metricfunc)(myinfo,pending,pending->results[i]);
}
else
{
for (i=0; i<pending->numresults; i++)
if ( pending->metrics[i] == 0. )
{
if ( (metricfunc= pending->metricfunc) != 0 )
pending->metrics[i] = (*metricfunc)(myinfo,pending,pending->results[i]);
flag++;
}
}
} }
if ( flag == 0 ) if ( flag == 0 )
usleep(100000); usleep(100000);

10
basilisk/basilisk.h

@ -26,9 +26,10 @@ struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vou
struct basilisk_item struct basilisk_item
{ {
struct queueitem DL; UT_hash_handle hh; struct queueitem DL; UT_hash_handle hh; struct basilisk_item *parent; void *dependents;
uint32_t submit,finished,basilisktag,numresults,numexact; uint32_t submit,finished,basilisktag,numresults,numexact,uniqueflag,numrequired;
char *results[BASILISK_MAXFANOUT]; char symbol[32]; double expiration; cJSON *vals; int32_t metricdir; void *metricfunc;
char *retstr,*results[BASILISK_MAXFANOUT]; double metrics[BASILISK_MAXFANOUT];
}; };
struct basilisk_info struct basilisk_info
@ -38,8 +39,7 @@ struct basilisk_info
struct basilisk_value values[8192]; int32_t numvalues; struct basilisk_value values[8192]; int32_t numvalues;
}; };
struct basilisk_item *basilisk_issue(struct supernet_info *myinfo,cJSON *hexjson,int32_t timeoutmillis,int32_t fanout,int32_t minresults,uint32_t basilisktag); struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,char *methodstr,char *symbol,cJSON *vals,int32_t timeoutmillis,int32_t fanout,int32_t minresults,uint32_t basilisktag);
void basilisks_init(struct supernet_info *myinfo); void basilisks_init(struct supernet_info *myinfo);
char *basilisk_issuerawtx(struct supernet_info *myinfo,char *remoteaddr,uint32_t basilisktag,char *symbol,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *spendscriptstr,char *changeaddr,int64_t txfee,int32_t minconf,cJSON *addresses,int32_t timeout);
#endif #endif

296
basilisk/basilisk_bitcoin.c

@ -13,6 +13,14 @@
* * * *
******************************************************************************/ ******************************************************************************/
struct bitcoin_rawtxdependents
{
int64_t spentsatoshis,outputsum,cost,change;
int32_t numptrs,numresults;
char **results,*coinaddrs;
struct basilisk_item *ptrs[];
};
#ifdef bitcoincancalculatebalances #ifdef bitcoincancalculatebalances
int64_t bitcoin_value(struct iguana_info *coin,bits256 txid,int16_t vout,char *coinaddr) int64_t bitcoin_value(struct iguana_info *coin,bits256 txid,int16_t vout,char *coinaddr)
{ {
@ -75,7 +83,6 @@ char *bitcoin_balance(struct iguana_info *coin,char *coinaddr,int32_t lastheight
jaddnum(retjson,"balance",dstr(balance)); jaddnum(retjson,"balance",dstr(balance));
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
#else
char *basilisk_bitcoinblockhashstr(char *coinstr,char *serverport,char *userpass,int32_t height) char *basilisk_bitcoinblockhashstr(char *coinstr,char *serverport,char *userpass,int32_t height)
{ {
@ -149,23 +156,6 @@ int32_t basilisk_blockheight(struct iguana_info *coin,bits256 hash2)
return(height); return(height);
} }
/*bits256 basilisk_blockhash(struct iguana_info *coin,bits256 prevhash2)
{
char *blockhashstr; bits256 hash2; int32_t height;
memset(hash2.bytes,0,sizeof(hash2));
if ( (height= basilisk_blockheight(coin,prevhash2)) >= 0 )
{
printf("blockhash.%d\n",height);
if ( (blockhashstr= bitcoin_blockhashstr(coin->symbol,coin->chain->serverport,coin->chain->userpass,height+1)) != 0 )
{
printf("got (%s)\n",blockhashstr);
hash2 = bits256_conv(blockhashstr);
free(blockhashstr);
}
}
return(hash2);
}*/
cJSON *bitcoin_blockjson(int32_t *heightp,char *coinstr,char *serverport,char *userpass,char *blockhashstr,int32_t height) cJSON *bitcoin_blockjson(int32_t *heightp,char *coinstr,char *serverport,char *userpass,char *blockhashstr,int32_t height)
{ {
cJSON *json = 0; int32_t flag = 0; char buf[1024],*blocktxt = 0; cJSON *json = 0; int32_t flag = 0; char buf[1024],*blocktxt = 0;
@ -298,7 +288,6 @@ int32_t basilisk_bitcoinscan(struct iguana_info *coin,uint8_t origblockspace[IGU
coin->blocks.pending--; coin->blocks.pending--;
return(num); return(num);
} }
#endif #endif
int32_t basilisk_bitcoinavail(struct iguana_info *coin) int32_t basilisk_bitcoinavail(struct iguana_info *coin)
@ -310,7 +299,7 @@ int32_t basilisk_bitcoinavail(struct iguana_info *coin)
else return(0); else return(0);
} }
char *basilisk_bitcoinbalances(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals) void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals)
{ {
/* cJSON *array=0,*result,*item,*retjson,*hexjson; int32_t i,n,besti=-1; char *coinaddr,*balancestr=0,*retstr=0; int64_t total=0,amount,most=0; struct basilisk_item *ptr; /* cJSON *array=0,*result,*item,*retjson,*hexjson; int32_t i,n,besti=-1; char *coinaddr,*balancestr=0,*retstr=0; int64_t total=0,amount,most=0; struct basilisk_item *ptr;
array = cJSON_CreateArray(); array = cJSON_CreateArray();
@ -390,69 +379,142 @@ char *basilisk_valuestr(struct iguana_info *coin,char *coinaddr,uint64_t value,i
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
char *basilisk_bitcoinvalue(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals) double basilisk_bitcoin_valuemetric(struct supernet_info *myinfo,struct basilisk_item *ptr,char *resultstr)
{
struct basilisk_value *v; cJSON *resultarg; int32_t ind;
if ( (ind= myinfo->basilisks.numvalues) >= sizeof(myinfo->basilisks.values)/sizeof(*myinfo->basilisks.values) )
ind = (rand() % (sizeof(myinfo->basilisks.values)/sizeof(*myinfo->basilisks.values)));
else myinfo->basilisks.numvalues++;
v = &myinfo->basilisks.values[ind];
if ( (resultarg= cJSON_Parse(resultstr)) != 0 )
{
safecopy(v->coinaddr,jstr(resultarg,"address"),sizeof(v->coinaddr));
v->value = j64bits(resultarg,"value");
v->txid = jbits256(resultarg,"txid");
v->vout = jint(resultarg,"vout");
v->height = jint(resultarg,"height");
}
return(ind + 1);
}
void *basilisk_bitcoinvalue(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
{ {
int32_t i,height,vout; char *coinaddr,*retstr=0; struct basilisk_value *v; cJSON *hexjson,*resultarg; uint64_t value = 0; struct basilisk_item *ptr; bits256 txid; int32_t i,height,vout; char *coinaddr; struct basilisk_value *v; uint64_t value = 0; bits256 txid;
txid = jbits256(vals,"txid"); txid = jbits256(valsobj,"txid");
vout = jint(vals,"vout"); vout = jint(valsobj,"vout");
coinaddr = jstr(vals,"address"); coinaddr = jstr(valsobj,"address");
if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 && coinaddr != 0 && coinaddr[0] != 0 ) if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 && coinaddr != 0 && coinaddr[0] != 0 )
{ {
if ( coin->VALIDATENODE != 0 || coin->RELAYNODE != 0 ) if ( coin->VALIDATENODE != 0 || coin->RELAYNODE != 0 )
{ {
printf("local check\n");
if ( iguana_unspentindfind(coin,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount) > 0 ) if ( iguana_unspentindfind(coin,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount) > 0 )
return(basilisk_valuestr(coin,coinaddr,value,height,txid,vout)); {
Lptr->retstr = basilisk_valuestr(coin,coinaddr,value,height,txid,vout);
return(Lptr);
}
} //else return(bitcoin_value(coin,txid,vout,coinaddr)); } //else return(bitcoin_value(coin,txid,vout,coinaddr));
printf("have local, but lite node\n");
} }
else
{
printf("Scan basilisks values\n"); printf("Scan basilisks values\n");
if ( (v= myinfo->basilisks.values) != 0 ) if ( (v= myinfo->basilisks.values) != 0 )
{ {
for (i=0; i<myinfo->basilisks.numvalues; i++,v++) for (i=0; i<myinfo->basilisks.numvalues; i++,v++)
{ {
if ( v->vout == vout && bits256_cmp(txid,v->txid) == 0 && strcmp(v->coinaddr,coinaddr) == 0 ) if ( v->vout == vout && bits256_cmp(txid,v->txid) == 0 && strcmp(v->coinaddr,coinaddr) == 0 )
return(basilisk_valuestr(coin,v->coinaddr,v->value,v->height,txid,vout)); {
Lptr->retstr = basilisk_valuestr(coin,coinaddr,value,height,txid,vout);
return(Lptr);
} }
} }
hexjson = cJSON_CreateObject(); }
jaddstr(hexjson,"agent","basilisk"); return(basilisk_issueremote(myinfo,"value",coin->symbol,valsobj,0,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag));
jaddstr(hexjson,"method","value"); }
if ( vals != 0 )
jadd(hexjson,"vals",jduplicate(vals)); double basilisk_bitcoin_rawtxmetric_dependents(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_item *ptr,struct bitcoin_rawtxdependents *dependents)
printf("issue.(%s)\n",jprint(hexjson,0)); {
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 ) int32_t i,j,numaddrs,notfinished = 0; cJSON *childjson,*addresses; struct basilisk_item *child; double metric = 0.; char *childstr,*coinaddr; int64_t inputsum,value,txfee;
for (i=0; i<dependents->numptrs; i++)
{ {
v = &myinfo->basilisks.values[myinfo->basilisks.numvalues++]; if ( (child= dependents->ptrs[i]) != 0 )
if ( (resultarg= cJSON_Parse(ptr->results[0])) != 0 )
{ {
safecopy(v->coinaddr,jstr(resultarg,"address"),sizeof(v->coinaddr)); if ( ptr->finished != 0 )
v->value = j64bits(resultarg,"value"); child->finished = (uint32_t)time(NULL);
v->txid = jbits256(resultarg,"txid"); else if ( child->finished == 0 )
v->vout = jint(resultarg,"vout"); notfinished++;
v->height = jint(resultarg,"height");
} }
basilisk_finish(ptr,-1);
retstr = basilisk_valuestr(coin,v->coinaddr,v->value,v->height,txid,vout);
} }
free_json(hexjson); if ( notfinished != 0 )
{
if ( ptr->finished != 0 )
{
if ( ptr->metricdir < 0 )
return(1.);
else return(-1.);
} else return(0.);
}
else if ( ptr->vals != 0 )
{
txfee = j64bits(ptr->vals,"txfee");
addresses = jarray(&numaddrs,ptr->vals,"addresses");
for (inputsum=i=0; i<dependents->numptrs; i++)
{
if ( (child= dependents->ptrs[i]) != 0 && (childstr= child->retstr) != 0 && (coinaddr= &dependents->coinaddrs[64*i]) != 0 )
{
if ( (childjson= cJSON_Parse(childstr)) != 0 )
{
if ( (value= j64bits(childjson,"value")) != 0 )
{
inputsum += value;
for (j=0; j<numaddrs; j++)
if ( strcmp(jstri(addresses,j),coinaddr) == 0 )
break;
if ( j == numaddrs )
{
printf("spend of invalid input address.(%s)\n",coinaddr);
metric = 3. + i;
} }
return(retstr); printf("Valid spend %.8f to %s\n",dstr(value),coinaddr);
}
free_json(childjson);
}
free(childstr);
child->retstr = 0;
}
}
if ( (inputsum - dependents->outputsum) != txfee )
{
printf("inputsum %.8f - outputsum %.8f = %.8f != txfee %.8f\n",dstr(inputsum),dstr(dependents->outputsum),dstr(inputsum)-dstr(dependents->outputsum),dstr(txfee));
return(1001.); // error
}
return(dstr(dependents->cost));
} else return(666.); // no vals??
} }
int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t locktime,int64_t satoshis,int64_t txfee,cJSON *addresses,char *spendscriptstr,char *changeaddr,char *resultstr) double basilisk_bitcoin_rawtxmetric(struct supernet_info *myinfo,struct basilisk_item *ptr,char *resultstr)
{ {
cJSON *txobj,*vouts,*vin,*sobj,*addrs,*vretjson,*vins,*argvals,*resultsobj; int64_t value,change=0,outputsum=0,inputsum=0,spentsatoshis=0,cost = -1; int32_t i,j,m,numaddrs,vout,spendlen,n; struct iguana_msgtx msgtx; uint8_t extraspace[8192],script[IGUANA_MAXSCRIPTSIZE],asmtype; struct vin_info V; char *scriptstr,str[65],*vret,*rawtx; bits256 txid; cJSON *txobj,*vouts,*vin,*sobj,*addrs,*vins,*argvals,*resultsobj,*addresses; int64_t outputsum=0,amount=0,cost = -1; int32_t i,m,numaddrs,spendlen,n; struct iguana_msgtx msgtx; uint8_t extraspace[8192],script[IGUANA_MAXSCRIPTSIZE],asmtype; struct vin_info V; char *scriptstr,*changeaddr,*coinaddr,*rawtx,*spendscriptstr; bits256 txid; struct iguana_info *coin; struct basilisk_item Lsubptr,*child; struct bitcoin_rawtxdependents *dependents=0; double metric; uint32_t locktime;
if ( coin != 0 ) if ( (coin= iguana_coinfind(ptr->symbol)) != 0 )
{
if ( (dependents= ptr->dependents) != 0 )
{ {
if ( (metric= basilisk_bitcoin_rawtxmetric_dependents(myinfo,coin,ptr,dependents)) != 0. )
{
for (i=0; i<dependents->numptrs; i++)
if ( (child= dependents->ptrs[i]) != 0 )
child->parent = 0;
}
return(metric);
}
if ( (resultsobj= cJSON_Parse(resultstr)) == 0 || (vins= jobj(resultsobj,"vins")) != 0 || (rawtx= jstr(resultsobj,"rawtx")) != 0 ) if ( (resultsobj= cJSON_Parse(resultstr)) == 0 || (vins= jobj(resultsobj,"vins")) != 0 || (rawtx= jstr(resultsobj,"rawtx")) != 0 )
{ {
if ( resultsobj != 0 ) if ( resultsobj != 0 )
free_json(resultsobj); free_json(resultsobj);
return(0); return(1.); // error
} }
spendscriptstr = jstr(ptr->vals,"spendscript");
changeaddr = jstr(ptr->vals,"changeaddr");
locktime = juint(ptr->vals,"locktime");
amount = j64bits(ptr->vals,"amount");
addresses = jarray(&numaddrs,ptr->vals,"addresses");
spendlen = (int32_t)strlen(spendscriptstr) >> 1; spendlen = (int32_t)strlen(spendscriptstr) >> 1;
decode_hex(script,spendlen,spendscriptstr); decode_hex(script,spendlen,spendscriptstr);
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,rawtx,extraspace,sizeof(extraspace))) != 0 ) if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,rawtx,extraspace,sizeof(extraspace))) != 0 )
@ -461,11 +523,15 @@ int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *
if ( juint(txobj,"locktime") != locktime ) if ( juint(txobj,"locktime") != locktime )
{ {
printf("locktime mismatch %u != %u\n",juint(txobj,"locktime"),locktime); printf("locktime mismatch %u != %u\n",juint(txobj,"locktime"),locktime);
return(-1); return(2.); // error
} }
else if ( jobj(txobj,"error") == 0 && cJSON_GetArraySize(vins) == msgtx.tx_in ) else if ( jobj(txobj,"error") == 0 && cJSON_GetArraySize(vins) == msgtx.tx_in )
{ {
numaddrs = cJSON_GetArraySize(addresses); dependents = calloc(1,sizeof(*dependents) + msgtx.tx_in*(sizeof(*dependents->results) + sizeof(*dependents->ptrs) + 64));
dependents->results = (void *)&dependents->ptrs[msgtx.tx_in];
dependents->coinaddrs = (void *)&dependents->results[msgtx.tx_in];
dependents->numptrs = msgtx.tx_in;
ptr->dependents = dependents;
for (i=0; i<msgtx.tx_in; i++) for (i=0; i<msgtx.tx_in; i++)
{ {
vin = jitem(vins,i); vin = jitem(vins,i);
@ -475,41 +541,23 @@ int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *
V.spendlen = (int32_t)strlen(scriptstr) >> 1; V.spendlen = (int32_t)strlen(scriptstr) >> 1;
decode_hex(V.spendscript,V.spendlen,scriptstr); decode_hex(V.spendscript,V.spendlen,scriptstr);
asmtype = _iguana_calcrmd160(coin,&V); asmtype = _iguana_calcrmd160(coin,&V);
coinaddr = &dependents->coinaddrs[64 * i];
//if ( asmtype == IGUANA_SCRIPT_76A988AC || asmtype == IGUANA_SCRIPT_AC || asmtype == IGUANA_SCRIPT_76AC || asmtype == IGUANA_SCRIPT_P2SH ) //if ( asmtype == IGUANA_SCRIPT_76A988AC || asmtype == IGUANA_SCRIPT_AC || asmtype == IGUANA_SCRIPT_76AC || asmtype == IGUANA_SCRIPT_P2SH )
bitcoin_address(V.coinaddr,coin->chain->pubtype,V.rmd160,20); bitcoin_address(coinaddr,coin->chain->pubtype,V.rmd160,20);
argvals = cJSON_CreateObject(); if ( (argvals= cJSON_CreateObject()) != 0 )
txid = jbits256(argvals,"txid");
vout = jint(argvals,"vout");
if ( (vret= basilisk_bitcoinvalue(myinfo,coin,remoteaddr,0,10000,argvals)) != 0 )
{
if ( (vretjson= cJSON_Parse(vret)) != 0 )
{
if ( (value= j64bits(vretjson,"value")) != 0 )
{ {
inputsum += value; jaddbits256(argvals,"txid",jbits256(vin,"txid"));
for (j=0; j<numaddrs; j++) jaddnum(argvals,"vout",jint(vin,"vout"));
if ( strcmp(jstri(addresses,j),V.coinaddr) == 0 ) if ( (dependents->ptrs[i]= basilisk_bitcoinvalue(&Lsubptr,myinfo,coin,0,rand(),(ptr->expiration - OS_milliseconds()) * .777,argvals)) != 0 )
break;
if ( j == numaddrs )
{ {
printf("spend of invalid input address.(%s) (%s).%d\n",V.coinaddr,scriptstr,asmtype); if ( dependents->ptrs[i] == &Lsubptr )
free_json(txobj);
return(-1);
}
printf("Valid spend %.8f to %s\n",dstr(value),V.coinaddr);
}
free_json(vretjson);
}
free(vret);
}
else
{ {
printf("spend of invalid %s unspent.(%s).%d\n",V.coinaddr,bits256_str(str,msgtx.vins[i].prev_hash),msgtx.vins[i].prev_vout); dependents->results[i] = Lsubptr.retstr;
free_json(txobj); dependents->ptrs[i] = 0;
return(-1); } else dependents->ptrs[i]->parent = ptr;
} }
if ( argvals != 0 )
free_json(argvals); free_json(argvals);
}
} else printf("cant find spend info.(%s)\n",jprint(vin,0)); } else printf("cant find spend info.(%s)\n",jprint(vin,0));
} }
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n == msgtx.tx_out ) if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n == msgtx.tx_out )
@ -519,7 +567,7 @@ int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *
outputsum += msgtx.vouts[i].value; outputsum += msgtx.vouts[i].value;
if ( spendlen == msgtx.vouts[i].pk_scriptlen && memcmp(script,msgtx.vouts[i].pk_script,spendlen) == 0 ) if ( spendlen == msgtx.vouts[i].pk_scriptlen && memcmp(script,msgtx.vouts[i].pk_script,spendlen) == 0 )
{ {
spentsatoshis = msgtx.vouts[i].value; dependents->spentsatoshis = msgtx.vouts[i].value;
continue; continue;
} }
else else
@ -528,7 +576,7 @@ int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *
{ {
if ( m == 1 && strcmp(jstri(addrs,0),changeaddr) == 0 ) if ( m == 1 && strcmp(jstri(addrs,0),changeaddr) == 0 )
{ {
change = msgtx.vouts[i].value; dependents->change = msgtx.vouts[i].value;
printf("verify it is normal spend for %s\n",changeaddr); printf("verify it is normal spend for %s\n",changeaddr);
continue; continue;
} }
@ -541,22 +589,23 @@ int64_t basilisk_bitcointxcost(struct supernet_info *myinfo,struct iguana_info *
free_json(txobj); free_json(txobj);
} }
} }
if ( spentsatoshis != satoshis ) if ( dependents->spentsatoshis != amount )
{ {
printf("spentsatoshis %.8f != expected %.8f, change %.8f\n",dstr(spentsatoshis),dstr(satoshis),dstr(change)); printf("spentsatoshis %.8f != expected %.8f, change %.8f\n",dstr(dependents->spentsatoshis),dstr(amount),dstr(dependents->change));
return(-1); return(1000.); // error
} }
if ( (inputsum - outputsum) != txfee ) if ( (dependents->outputsum= outputsum) <= 0 )
{ {
printf("inputsum %.8f - outputsum %.8f = %.8f != txfee %.8f\n",dstr(inputsum),dstr(outputsum),dstr(inputsum)-dstr(outputsum),dstr(txfee)); printf("illegal outputsum %.8f\n",dstr(outputsum));
return(-1); return(1001.); // error
} }
return(cost); dependents->cost = cost;
return(0.);
} }
char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj) void *basilisk_bitcoinrawtx(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
{ {
uint8_t buf[IGUANA_MAXSCRIPTSIZE]; int32_t i,minconf,spendlen,besti=-1; cJSON *hexjson,*resultobj,*vins,*addresses,*txobj = 0; uint32_t locktime; char *spendscriptstr,*changeaddr,*retstr=0,*rawtx = 0; int64_t amount,txfee,cost,bestcost=-1; struct basilisk_item *ptr; uint8_t buf[IGUANA_MAXSCRIPTSIZE]; int32_t minconf,spendlen; cJSON *vins,*addresses,*txobj = 0; uint32_t locktime; char *spendscriptstr,*changeaddr,*rawtx = 0; int64_t amount,txfee;
vins = 0; vins = 0;
changeaddr = jstr(valsobj,"changeaddr"); changeaddr = jstr(valsobj,"changeaddr");
spendscriptstr = jstr(valsobj,"spendscript"); spendscriptstr = jstr(valsobj,"spendscript");
@ -569,7 +618,10 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
if ( (txfee= j64bits(valsobj,"txfee")) == 0 ) if ( (txfee= j64bits(valsobj,"txfee")) == 0 )
txfee = 10000; txfee = 10000;
if ( changeaddr == 0 || changeaddr[0] == 0 || spendscriptstr == 0 || spendscriptstr[0] == 0 || amount == 0 || addresses == 0 ) if ( changeaddr == 0 || changeaddr[0] == 0 || spendscriptstr == 0 || spendscriptstr[0] == 0 || amount == 0 || addresses == 0 )
return(clonestr("{\"error\":\"invalid changeaddr or spendscript or addresses\"}")); {
Lptr->retstr = clonestr("{\"error\":\"invalid changeaddr or spendscript or addresses\"}");
return(Lptr);
}
if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 ) if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 )
{ {
if ( coin->VALIDATENODE != 0 || coin->RELAYNODE != 0 ) if ( coin->VALIDATENODE != 0 || coin->RELAYNODE != 0 )
@ -580,57 +632,31 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
decode_hex(buf,spendlen,spendscriptstr); decode_hex(buf,spendlen,spendscriptstr);
bitcoin_txoutput(coin,txobj,buf,spendlen,amount); bitcoin_txoutput(coin,txobj,buf,spendlen,amount);
rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf); rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf);
} else printf("error creating txobj\n"); }
else
{
Lptr->retstr = clonestr("{\"error\":\"couldnt create rawtx locally\"}");
return(Lptr);
}
} //else rawtx = bitcoin_calcrawtx(myinfo,coin,vinsp,satoshis,spendscriptstr,changeaddr,txfee,addresses,minconf,locktime); } //else rawtx = bitcoin_calcrawtx(myinfo,coin,vinsp,satoshis,spendscriptstr,changeaddr,txfee,addresses,minconf,locktime);
if ( rawtx != 0 ) if ( rawtx != 0 )
{ {
if ( vins != 0 ) if ( vins != 0 )
{ {
free_json(txobj); free_json(txobj);
resultobj = cJSON_CreateObject();
valsobj = cJSON_CreateObject(); valsobj = cJSON_CreateObject();
jaddstr(valsobj,"rawtx",rawtx), free(rawtx);
jadd(valsobj,"vins",vins); jadd(valsobj,"vins",vins);
jadd(resultobj,"vals",valsobj); jaddstr(valsobj,"rawtx",rawtx);
jaddstr(resultobj,"agent","basilisk"); free(rawtx);
jaddstr(resultobj,"method","result"); Lptr->retstr = jprint(valsobj,1);
jaddnum(resultobj,"plaintext",1); return(Lptr);
//retstr = jprint(basilisk_resultsjson(myinfo,coin->symbol,remoteaddr,basilisktag,timeoutmillis,jprint(resultobj,1)),1);
return(jprint(resultobj,1));
} else free(rawtx); } else free(rawtx);
} } // fall through to remote
} }
if ( txobj != 0 ) if ( txobj != 0 )
free_json(txobj), txobj = 0; free_json(txobj), txobj = 0;
if ( vins != 0 ) if ( vins != 0 )
free_json(vins), vins = 0; free_json(vins), vins = 0;
if ( addresses != 0 ) return(basilisk_issueremote(myinfo,"rawtx",coin->symbol,valsobj,0,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag));
{
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"agent","basilisk");
jaddstr(hexjson,"method","rawtx");
jaddstr(hexjson,"activecoin",coin->symbol);
jadd(hexjson,"vals",jduplicate(valsobj));
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 )
{
for (i=0; i<ptr->numresults; i++)
{
if ( ptr->results[i] == 0 )
continue;
if ( retstr != 0 && strcmp(ptr->results[i],retstr) == 0 )
ptr->numexact++;
if ( (cost= basilisk_bitcointxcost(myinfo,coin,remoteaddr,locktime,amount,txfee,addresses,spendscriptstr,changeaddr,ptr->results[i])) >= 0 && (bestcost == 0 || cost < bestcost) )
{
if ( retstr != 0 )
ptr->numexact = 0;
retstr = ptr->results[i];
bestcost = cost;
besti = i;
}
}
retstr = basilisk_finish(ptr,besti);
}
free_json(hexjson);
}
return(retstr);
} }

26
basilisk/basilisk_ether.c

@ -13,29 +13,7 @@
* * * *
******************************************************************************/ ******************************************************************************/
char *basilisk_etherrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis) struct basilisk_item *basilisk_etherrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis)
{ {
cJSON *hexjson,*valsobj; char *retstr = 0; struct basilisk_item *ptr; return(0);
*vinsp = 0;
if ( addresses != 0 )
{
valsobj = cJSON_CreateObject();
jaddnum(valsobj,"basilisktag",basilisktag);
jaddstr(valsobj,"coin",coin->symbol);
jadd64bits(valsobj,"amount",satoshis);
jadd64bits(valsobj,"txfee",txfee);
jaddnum(valsobj,"minconf",minconf);
jaddnum(valsobj,"locktime",locktime);
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"changeaddr",changeaddr);
jaddstr(hexjson,"spendscriptstr",spendscriptstr);
jadd(hexjson,"addresses",jduplicate(addresses));
jadd(hexjson,"vals",valsobj);
jaddstr(hexjson,"agent","basilisk");
jaddstr(hexjson,"method","rawtx");
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 )
retstr = basilisk_finish(ptr,0);
free_json(hexjson);
}
return(retstr);
} }

26
basilisk/basilisk_lisk.c

@ -13,29 +13,7 @@
* * * *
******************************************************************************/ ******************************************************************************/
char *basilisk_liskrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis) struct basilisk_item *basilisk_liskrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis)
{ {
cJSON *hexjson,*valsobj; char *retstr = 0; struct basilisk_item *ptr; return(0);
*vinsp = 0;
if ( addresses != 0 )
{
valsobj = cJSON_CreateObject();
jaddnum(valsobj,"basilisktag",basilisktag);
jaddstr(valsobj,"coin",coin->symbol);
jadd64bits(valsobj,"amount",satoshis);
jadd64bits(valsobj,"txfee",txfee);
jaddnum(valsobj,"minconf",minconf);
jaddnum(valsobj,"locktime",locktime);
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"changeaddr",changeaddr);
jaddstr(hexjson,"spendscriptstr",spendscriptstr);
jadd(hexjson,"addresses",jduplicate(addresses));
jadd(hexjson,"vals",valsobj);
jaddstr(hexjson,"agent","basilisk");
jaddstr(hexjson,"method","rawtx");
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 )
retstr = basilisk_finish(ptr,0);
free_json(hexjson);
}
return(retstr);
} }

26
basilisk/basilisk_nxt.c

@ -13,29 +13,7 @@
* * * *
******************************************************************************/ ******************************************************************************/
char *basilisk_nxtrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis) struct basilisk_item *basilisk_nxtrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis)
{ {
cJSON *hexjson,*valsobj; char *retstr = 0; struct basilisk_item *ptr; return(0);
*vinsp = 0;
if ( addresses != 0 )
{
valsobj = cJSON_CreateObject();
jaddnum(valsobj,"basilisktag",basilisktag);
jaddstr(valsobj,"coin",coin->symbol);
jadd64bits(valsobj,"amount",satoshis);
jadd64bits(valsobj,"txfee",txfee);
jaddnum(valsobj,"minconf",minconf);
jaddnum(valsobj,"locktime",locktime);
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"changeaddr",changeaddr);
jaddstr(hexjson,"spendscriptstr",spendscriptstr);
jadd(hexjson,"addresses",jduplicate(addresses));
jadd(hexjson,"vals",valsobj);
jaddstr(hexjson,"agent","basilisk");
jaddstr(hexjson,"method","rawtx");
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 )
retstr = basilisk_finish(ptr,0);
free_json(hexjson);
}
return(retstr);
} }

26
basilisk/basilisk_waves.c

@ -13,29 +13,7 @@
* * * *
******************************************************************************/ ******************************************************************************/
char *basilisk_wavesrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis) struct basilisk_item *basilisk_wavesrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,cJSON **vinsp,uint32_t locktime,uint64_t satoshis,char *changeaddr,uint64_t txfee,cJSON *addresses,int32_t minconf,char *spendscriptstr,int32_t timeoutmillis)
{ {
cJSON *hexjson,*valsobj; char *retstr = 0; struct basilisk_item *ptr; return(0);
*vinsp = 0;
if ( addresses != 0 )
{
valsobj = cJSON_CreateObject();
jaddnum(valsobj,"basilisktag",basilisktag);
jaddstr(valsobj,"coin",coin->symbol);
jadd64bits(valsobj,"amount",satoshis);
jadd64bits(valsobj,"txfee",txfee);
jaddnum(valsobj,"minconf",minconf);
jaddnum(valsobj,"locktime",locktime);
hexjson = cJSON_CreateObject();
jaddstr(hexjson,"changeaddr",changeaddr);
jaddstr(hexjson,"spendscriptstr",spendscriptstr);
jadd(hexjson,"addresses",jduplicate(addresses));
jadd(hexjson,"vals",valsobj);
jaddstr(hexjson,"agent","basilisk");
jaddstr(hexjson,"method","rawtx");
if ( (ptr= basilisk_issue(myinfo,hexjson,timeoutmillis,0,1,basilisktag)) != 0 )
retstr = basilisk_finish(ptr,0);
free_json(hexjson);
}
return(retstr);
} }

4
iguana/iguana777.h

@ -495,13 +495,15 @@ struct hhbits256 { UT_hash_handle hh; bits256 txid; int32_t height; uint16_t fir
struct iguana_monitorinfo { bits256 txid; int32_t numreported; uint8_t peerbits[IGUANA_MAXPEERS >> 3]; }; struct iguana_monitorinfo { bits256 txid; int32_t numreported; uint8_t peerbits[IGUANA_MAXPEERS >> 3]; };
typedef char *(*basilisk_func)(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals); typedef void *(*basilisk_func)(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals);
typedef double (*basilisk_metricfunc)(struct supernet_info *myinfo,struct basilisk_item *ptr,char *result);
struct iguana_info struct iguana_info
{ {
char name[64],symbol[8],protocol,statusstr[512],scriptsfname[2][512]; char name[64],symbol[8],protocol,statusstr[512],scriptsfname[2][512];
struct iguana_peers peers; struct iguana_peer internaladdr; struct iguana_peers peers; struct iguana_peer internaladdr;
basilisk_func basilisk_rawtx,basilisk_balances,basilisk_value; basilisk_func basilisk_rawtx,basilisk_balances,basilisk_value;
basilisk_metricfunc basilisk_rawtxmetric,basilisk_balancesmetric,basilisk_valuemetric;
uint32_t fastfind; FILE *fastfps[0x100]; uint8_t *fast[0x100]; int32_t *fasttables[0x100]; long fastsizes[0x100]; uint32_t fastfind; FILE *fastfps[0x100]; uint8_t *fast[0x100]; int32_t *fasttables[0x100]; long fastsizes[0x100];
uint64_t instance_nonce,myservices,totalsize,totalrecv,totalpackets,sleeptime; uint64_t instance_nonce,myservices,totalsize,totalrecv,totalpackets,sleeptime;

4
includes/iguana_apideclares.h

@ -14,8 +14,8 @@
******************************************************************************/ ******************************************************************************/
INT_ARRAY_STRING(basilisk,balances,basilisktag,vals,activecoin);//lastheight,addresses,activecoin); INT_ARRAY_STRING(basilisk,balances,basilisktag,vals,activecoin);
INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin);//changeaddr,addresses,vals,spendscriptstr); INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin);
INT_ARRAY_STRING(basilisk,value,basilisktag,vals,activecoin); INT_ARRAY_STRING(basilisk,value,basilisktag,vals,activecoin);
INT_AND_ARRAY(basilisk,result,basilisktag,vals); INT_AND_ARRAY(basilisk,result,basilisktag,vals);

Loading…
Cancel
Save