/****************************************************************************** * Copyright © 2014-2017 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. * * * ******************************************************************************/ #define CHROMEAPP_NAME iguana #define CHROMEAPP_STR "iguana" #define CHROMEAPP_CONF "iguana.config" #define CHROMEAPP_MAIN iguana_main #define CHROMEAPP_JSON iguana_JSON #define CHROMEAPP_HANDLER Handler_iguana #define ACTIVELY_DECLARE #define HAVE_STRUCT_TIMESPEC #include "../pnacl_main.h" #include "iguana777.h" struct iguana_jsonitem { struct queueitem DL; struct supernet_info *myinfo; uint32_t fallback,expired,allocsize; char *retjsonstr; char remoteaddr[64]; uint16_t port; char jsonstr[]; }; uint16_t SuperNET_API2num(char *agent,char *method) { int32_t i,n = 0; cJSON *item; if ( agent != 0 && method != 0 && API_json != 0 && (n= cJSON_GetArraySize(API_json)) > 0 ) { for (i=0; i>= 5; if ( API_json != 0 && (n= cJSON_GetArraySize(API_json)) > 0 && num < n ) { item = jitem(API_json,num); strcpy(agent,jstr(item,"agent")); strcpy(method,jstr(item,"method")); return(num); } return(-1); } int32_t SuperNET_str2hex(uint8_t *hex,char *str) { int32_t len; len = (int32_t)strlen(str)+1; decode_hex(hex,len,str); return(len); } void SuperNET_hex2str(char *str,uint8_t *hex,int32_t len) { init_hexbytes_noT(str,hex,len); } struct supernet_info *SuperNET_MYINFO(char *passphrase) { if ( MYINFO.ctx == 0 ) { OS_randombytes(MYINFO.privkey.bytes,sizeof(MYINFO.privkey)); MYINFO.myaddr.pubkey = curve25519(MYINFO.privkey,curve25519_basepoint9()); printf("SuperNET_MYINFO: generate session keypair\n"); MYINFO.NOTARY.RELAYID = -1; } if ( passphrase == 0 || passphrase[0] == 0 ) return(&MYINFO); else { // search saved accounts } return(&MYINFO); return(0); } struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey) { int32_t i; *nump = 0; if ( MYINFOS != 0 ) { for (i=0; MYINFOS[i]!=0; i++) { *nump = i; if ( bits256_cmp(pubkey,MYINFOS[i]->myaddr.persistent) == 0 ) return(MYINFOS[i]); } *nump = i; } return(0); } int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max) { int32_t i = 0; if ( MYINFOS != 0 ) { for (i=0; imyaddr.persistent) == 0 ) { MYINFOS = realloc(MYINFOS,(num + 2) * sizeof(*MYINFOS)); char str[65]; printf("MYNFOadd[%d] <- %s\n",num,bits256_str(str,myinfo->myaddr.persistent)); MYINFOS[num] = calloc(1,sizeof(*myinfo)); *MYINFOS[num] = *myinfo; MYINFOS[++num] = 0; } } char *iguana_JSON(void *_myinfo,void *_coin,char *jsonstr,uint16_t port) { char *retstr=0; cJSON *json; struct supernet_info *myinfo = _myinfo; struct iguana_info *coin = _coin; if ( (json= cJSON_Parse(jsonstr)) != 0 ) { if ( myinfo == 0 ) myinfo = SuperNET_MYINFO(0); retstr = SuperNET_JSON(myinfo,coin,json,"127.0.0.1",port); free_json(json); } if ( retstr == 0 ) retstr = clonestr("{\"error\":\"null return from iguana_JSON\"}"); return(retstr); } char *SuperNET_jsonstr(struct supernet_info *myinfo,char *jsonstr,char *remoteaddr,uint16_t port) { cJSON *json; char *agent,*method,*retstr = 0; //printf("SuperNET_jsonstr.(%s)\n",jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { method = jstr(json,"method"); if ( (agent= jstr(json,"agent")) != 0 && method != 0 && jobj(json,"params") == 0 ) retstr = SuperNET_parser(myinfo,agent,method,json,remoteaddr); else if ( method != 0 && is_bitcoinrpc(myinfo,method,remoteaddr) >= 0 ) retstr = iguana_bitcoinRPC(myinfo,method,json,remoteaddr,port); else retstr = clonestr("{\"error\":\"need both agent and method\"}"); free_json(json); } else retstr = clonestr("{\"error\":\"couldnt parse SuperNET_JSON\"}"); //printf("SuperNET_jsonstr ret.(%s)\n",retstr); return(retstr); } int32_t iguana_jsonQ(struct supernet_info *myinfo,struct iguana_info *coin) { struct iguana_jsonitem *ptr; char *str; queue_t *finishedQ,*jsonQ; if ( coin == 0 ) { finishedQ = &FINISHED_Q; jsonQ = &JSON_Q; } else { finishedQ = &coin->finishedQ; jsonQ = &coin->jsonQ; } if ( COMMANDLINE_ARGFILE != 0 ) { ptr = calloc(1,sizeof(*ptr) + strlen(COMMANDLINE_ARGFILE) + 1); ptr->myinfo = myinfo;//SuperNET_MYINFO(0); strcpy(ptr->jsonstr,COMMANDLINE_ARGFILE); free(COMMANDLINE_ARGFILE); COMMANDLINE_ARGFILE = 0; if ( (ptr->retjsonstr= SuperNET_jsonstr(ptr->myinfo,ptr->jsonstr,ptr->remoteaddr,ptr->port)) == 0 ) ptr->retjsonstr = clonestr("{\"error\":\"null return from iguana_jsonstr\"}"); printf("COMMANDLINE_ARGFILE.(%s) -> (%s) %.0f\n",ptr->jsonstr,ptr->retjsonstr!=0?ptr->retjsonstr:"null return",OS_milliseconds()); queue_enqueue("finishedQ",finishedQ,&ptr->DL); return(1); } if ( (ptr= queue_dequeue(finishedQ)) != 0 ) { if ( ptr->expired != 0 ) { if ( (str= ptr->retjsonstr) != 0 ) { ptr->retjsonstr = 0; free(str); } printf("garbage collection: expired.(%s)\n",ptr->jsonstr); myfree(ptr,ptr->allocsize); } else queue_enqueue("finishedQ",finishedQ,&ptr->DL); } if ( (ptr= queue_dequeue(jsonQ)) != 0 ) { if ( (ptr->retjsonstr= SuperNET_jsonstr(ptr->myinfo,ptr->jsonstr,ptr->remoteaddr,ptr->port)) == 0 ) ptr->retjsonstr = clonestr("{\"error\":\"null return from iguana_jsonstr\"}"); //printf("finished.(%s) -> (%s) %.0f\n",ptr->jsonstr,ptr->retjsonstr!=0?ptr->retjsonstr:"null return",OS_milliseconds()); queue_enqueue("finishedQ",finishedQ,&ptr->DL); return(1); } return(0); } char *iguana_blockingjsonstr(struct supernet_info *myinfo,struct iguana_info *coin,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port) { queue_t *Q; struct iguana_jsonitem *ptr; int32_t len,allocsize; double expiration; expiration = OS_milliseconds() + maxmillis; //printf("blocking case.(%s) %.0f maxmillis.%d\n",jsonstr,OS_milliseconds(),maxmillis); len = (int32_t)strlen(jsonstr); allocsize = sizeof(*ptr) + len + 1; ptr = mycalloc('J',1,allocsize); ptr->allocsize = allocsize; ptr->myinfo = myinfo; ptr->port = port; ptr->retjsonstr = 0; safecopy(ptr->remoteaddr,remoteaddr,sizeof(ptr->remoteaddr)); memcpy(ptr->jsonstr,jsonstr,len+1); if ( coin == 0 || coin->FULLNODE < 0 || (coin->FULLNODE == 0 && coin->VALIDATENODE == 0) ) Q = &JSON_Q; else Q = &coin->jsonQ; queue_enqueue("jsonQ",Q,&ptr->DL); while ( OS_milliseconds() < expiration ) { usleep(100); if ( ptr->retjsonstr != 0 ) { //printf("got blocking retjsonstr.(%s) delete allocsize.%d:%d\n",retjsonstr,allocsize,ptr->allocsize); queue_delete(coin != 0 ? &coin->finishedQ : &FINISHED_Q,&ptr->DL,ptr->allocsize,1); return(ptr->retjsonstr); } usleep(1000); } //printf("(%s) expired\n",jsonstr); ptr->expired = (uint32_t)time(NULL); return(clonestr("{\"error\":\"iguana jsonstr expired\"}")); } int32_t iguana_immediate(struct iguana_info *coin,int32_t immedmillis) { double endmillis; if ( immedmillis > 60000 ) immedmillis = 60000; endmillis = OS_milliseconds() + immedmillis; while ( 1 ) { if ( coin->busy_processing == 0 ) break; usleep(100); if ( OS_milliseconds() > endmillis ) break; } return(coin->busy_processing == 0); } char *SuperNET_processJSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port) { cJSON *retjson; uint64_t tag; uint32_t timeout,immedmillis; char *jsonstr,*retjsonstr,*retstr = 0; //*hexmsg,*method, //char str[65]; printf("processJSON %p %s\n",&myinfo->privkey,bits256_str(str,myinfo->privkey)); if ( json != 0 ) { if ( jobj(json,"tag") == 0 || (tag= j64bits(json,"tag")) == 0 ) { OS_randombytes((uint8_t *)&tag,sizeof(tag)); jadd64bits(json,"tag",tag); } if ( (timeout= juint(json,"timeout")) == 0 ) timeout = IGUANA_JSONTIMEOUT; /*if ( (method= jstr(json,"method")) != 0 && strcmp(method,"DHT") == 0 && remoteaddr != 0 && (hexmsg= jstr(json,"hexmsg")) != 0 ) { //printf("hexmsgprocess myinfo.%p\n",myinfo); SuperNET_hexmsgprocess(myinfo,0,json,hexmsg,remoteaddr); return(clonestr("{\"result\":\"processed remote DHT\"}")); }*/ jsonstr = jprint(json,0); //printf("RPC? (%s)\n",jsonstr); if ( (immedmillis= juint(json,"immediate")) != 0 || ((remoteaddr == 0 || remoteaddr[0] == 0) && port == myinfo->rpcport) ) { if ( coin != 0 ) { if ( immedmillis == 0 || iguana_immediate(coin,immedmillis) != 0 ) retjsonstr = SuperNET_jsonstr(myinfo,jsonstr,remoteaddr,port); else retjsonstr = clonestr("{\"error\":\"coin is busy processing\"}"); } else retjsonstr = SuperNET_jsonstr(myinfo,jsonstr,remoteaddr,port); } else retjsonstr = iguana_blockingjsonstr(myinfo,coin,jsonstr,tag,timeout,remoteaddr,port); if ( retjsonstr != 0 ) { if ( (retjsonstr[0] == '{' || retjsonstr[0] == '[') && (retjson= cJSON_Parse(retjsonstr)) != 0 ) { if ( is_cJSON_Array(retjson) == 0 ) { if ( jobj(retjson,"tag") == 0 || j64bits(retjson,"tag") != tag ) { if ( jobj(retjson,"tag") != 0 ) jdelete(retjson,"tag"); jadd64bits(retjson,"tag",tag); } retstr = jprint(retjson,1); free(retjsonstr);//,strlen(retjsonstr)+1); //printf("retstr.(%s) retjsonstr.%p retjson.%p\n",retstr,retjsonstr,retjson); } else retstr = retjsonstr; } else retstr = retjsonstr; } free(jsonstr); } else retstr = clonestr("{\"error\":\"cant parse JSON\"}"); if ( retstr == 0 ) retstr = clonestr("{\"error\":\"null return\"}"); //printf("processJSON.(%s)\n",retstr); return(retstr); } char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port) { int32_t autologin = 0; uint32_t timestamp; char *retstr=0,*agent=0,*method=0,*userpass; uint64_t tag; //printf("SuperNET_JSON.(%s)\n",jprint(json,0)); if ( remoteaddr != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 ) remoteaddr = 0; if ( (agent = jstr(json,"agent")) == 0 ) agent = "bitcoinrpc"; if ( (method= jstr(json,"method")) == 0 ) { printf("no method in request.(%s)\n",jprint(json,0)); return(clonestr("{\"error\":\"no method\"}")); } if ( strcmp(method,"login") == 0 || strcmp(method,"logout") == 0 ) return(clonestr("{\"error\":\"login and logout are internal only functions\"}")); if ( remoteaddr == 0 ) { if ( jobj(json,"timestamp") != 0 ) jdelete(json,"timestamp"); timestamp = (uint32_t)time(NULL); jaddnum(json,"timestamp",timestamp); } if ( jobj(json,"tag") == 0 || (tag= j64bits(json,"tag")) == 0 ) { OS_randombytes((uint8_t *)&tag,sizeof(tag)); jadd64bits(json,"tag",tag); } if ( coin != 0 && coin->FULLNODE >= 0 && coin->chain->userpass[0] != 0 ) { if ( (userpass= jstr(json,"userpass")) == 0 || strcmp(userpass,coin->chain->userpass) != 0 ) { printf("iguana authentication error {%s} (%s) != (%s)\n",jprint(json,0),userpass,coin->chain->userpass); return(clonestr("{\"error\":\"authentication error\"}")); } } if ( (retstr= SuperNET_processJSON(myinfo,coin,json,remoteaddr,port)) == 0 ) printf("null retstr from SuperNET_JSON\n"); if ( autologin != 0 ) SuperNET_logout(myinfo,0,json,remoteaddr); return(retstr); } void iguana_exit(struct supernet_info *myinfo,struct iguana_bundle *bp) { static int exiting; int32_t i,j,iter; struct iguana_info *coin,*tmp; if ( exiting != 0 ) while ( 1 ) sleep(1); exiting = 1; if ( myinfo == 0 ) myinfo = SuperNET_MYINFO(0); printf("start EXIT\n"); for (iter=0; iter<3; iter++) { if ( iter == 0 ) basilisk_request_goodbye(myinfo); else { HASH_ITER(hh,myinfo->allcoins,coin,tmp) { if ( coin->peers != 0 ) { for (j=0; jpeers->active[j].dead = (uint32_t)time(NULL); break; case 2: if ( coin->peers->active[j].usock >= 0 ) closesocket(coin->peers->active[j].usock); break; } } } } } sleep(3); } printf("sockets closed\n"); if ( bp != 0 ) iguana_bundleremove(bp->coin,bp->hdrsi,1); for (i=0; i<10; i++) { printf("need to exit, please restart after shutdown in %d seconds, or just ctrl-C\n",10-i); sleep(1); } exit(0); } #ifndef _WIN32 #include void sigint_func() { printf("\nSIGINT\n"); iguana_exit(0,0); } void sigillegal_func() { printf("\nSIGILL\n"); iguana_exit(0,0); } void sighangup_func() { printf("\nSIGHUP\n"); iguana_exit(0,0); } void sigkill_func() { printf("\nSIGKILL\n"); iguana_exit(0,0); } void sigabort_func() { printf("\nSIGABRT\n"); iguana_exit(0,0); } void sigquit_func() { printf("\nSIGQUIT\n"); iguana_exit(0,0); } void sigchild_func() { printf("\nSIGCHLD\n"); signal(SIGCHLD,sigchild_func); } void sigalarm_func() { printf("\nSIGALRM\n"); signal(SIGALRM,sigalarm_func); } void sigcontinue_func() { printf("\nSIGCONT\n"); signal(SIGCONT,sigcontinue_func); } #endif void iguana_signalsinit() { #ifndef _WIN32 signal(SIGABRT,sigabort_func); signal(SIGINT,sigint_func); signal(SIGILL,sigillegal_func); signal(SIGHUP,sighangup_func); //signal(SIGKILL,sigkill_func); signal(SIGQUIT,sigquit_func); signal(SIGCHLD,sigchild_func); signal(SIGALRM,sigalarm_func); signal(SIGCONT,sigcontinue_func); #endif } // mksquashfs DB/BTC BTC.squash -b 1048576 -> 19GB? // mksquashfs DB/BTC BTC.lzo -comp lzo -b 1048576 -> takes a really long time -> 20GB // mksquashfs DB/BTC BTC.xz -b 1048576 -comp xz -Xdict-size 512K -> takes a long time -> 16GB // mksquashfs DB/BTC BTC.xz1m -b 1048576 -comp xz -Xdict-size 1024K -> takes a long time -> /* mksquashfs DB/BTC BTC.xz -comp xz mksquashfs DB/BTC BTC.xzs -b 16384 -comp xz -Xdict-size 8K mksquashfs DB/BTC BTC.xz1m -b 1048576 -comp xz -Xdict-size 1024K mksquashfs DB/BTC BTC.xz8k -comp xz -Xdict-size 8K mksquashfs DB/BTC BTC.lzo -comp lzo mksquashfs DB/BTC BTC.lzo1m -comp lzo -b 1048576 mksquashfs DB/BTC BTC.squash mksquashfs DB/BTC BTC.squash1M -b 1048576 rm BTC.xz; mksquashfs DB/BTC BTC.xz -comp xz -b 1048576 -comp xz -Xdict-size 1024K sudo mount BTC.xz DB/ro/BTC -t squashfs -o loop https://github.com/vasi/squashfuse */ void DEX_explorerloop(void *ptr) { struct supernet_info *myinfo = ptr; while ( 1 ) { if ( myinfo->DEXEXPLORER != 0 ) { kmd_bitcoinscan(); } usleep(100000); } } void mainloop(struct supernet_info *myinfo) { struct iguana_info *coin; int32_t counter=0,depth; double lastmilli = 0; sleep(3); printf("mainloop\n"); while ( 1 ) { //printf("main iteration\n"); if ( 1 ) { if ( OS_milliseconds() > lastmilli+100 ) { //fprintf(stderr,"."); counter++; coin = 0; depth = 0; //printf("check jsonQ\n"); while ( iguana_jsonQ(myinfo,0) != 0 ) ; lastmilli = OS_milliseconds(); } usleep(30000); } //pangea_queues(SuperNET_MYINFO(0)); //if ( flag == 0 ) // usleep(100000 + isRT*100000 + (numpeers == 0)*1000000); //iguana_jsonQ(); // cant do this here safely, need to send to coin specific queue } } void iguana_accounts(char *keytype) { long filesize; cJSON *json,*array,*item,*posting,*auths,*json2; int32_t i,n,m; char *str,*str2,*postingkey,*name,*key,fname[128],cmd[512]; FILE *postingkeys; if ( (str= OS_filestr(&filesize,"accounts.txt")) != 0 ) { if ( (json= cJSON_Parse(str)) != 0 ) { if ( (array= jarray(&n,json,"result")) != 0 && (postingkeys= fopen("keys.c","wb")) != 0 ) { fprintf(postingkeys,"char *%skeys[][2] = {\n",keytype); for (i=0; i %s",key,fname); if ( system(cmd) != 0 ) printf("Error issuing.(%s)\n",cmd); if ( (str2= OS_filestr(&filesize,fname)) != 0 ) { if ( (json2= cJSON_Parse(str2)) != 0 ) { if ( (postingkey= jstr(json2,"result")) != 0 ) fprintf(postingkeys,"{ \"%s\", \"%s\" },",name,postingkey); else printf("no result in (%s)\n",jprint(json2,0)); free_json(json2); } else printf("couldnt parse (%s)\n",str2); free(str2); } else printf("couldnt load (%s)\n",fname); } } } } fprintf(postingkeys,"\n};\n"); fclose(postingkeys); } free_json(json); } free(str); } } void iguana_appletests(struct supernet_info *myinfo) { char *str; //iguana_chaingenesis(1,1403138561,0x1e0fffff,8359109,bits256_conv("fd1751cc6963d88feca94c0d01da8883852647a37a0a67ce254d62dd8c9d5b2b")); // BTCD if ( (0) ) { char genesisblock[1024]; //iguana_chaingenesis("VPN",0,bits256_conv("00000ac7d764e7119da60d3c832b1d4458da9bc9ef9d5dd0d91a15f690a46d99"),genesisblock,"scrypt",1,1409839200,0x1e0fffff,64881664,bits256_conv("698a93a1cacd495a7a4fb3864ad8d06ed4421dedbc57f9aaad733ea53b1b5828")); // VPN iguana_chaingenesis(myinfo,"LTC",0,0,0,bits256_conv("12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2"),genesisblock,"sha256",1,1317972665,0x1e0ffff0,2084524493,bits256_conv("97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); // LTC //char *Str = "01000000f615f7ce3b4fc6b8f61e8f89aedb1d0852507650533a9e3b10b9bbcc30639f279fcaa86746e1ef52d3edb3c4ad8259920d509bd073605c9bf1d59983752a6b06b817bb4ea78e011d012d59d4"; // https://litecoin.info/Scrypt 0000000110c8357966576df46f3b802ca897deb7ad18b12f1c24ecff6386ebd9 //uint8_t buf[1000]; bits256 shash,hash2; char str[65],str2[65]; //decode_hex(buf,(int32_t)strlen(Str)>>1,Str); //calc_scrypthash(shash.uints,buf); //blockhash_sha256(&hash2,buf,80); //printf("shash -> %s sha256x2 %s\n",bits256_str(str,shash),bits256_str(str2,hash2)); getchar(); } if ( 1 ) { /*int32_t i; ;bits256 hash2; uint8_t pubkey[33]; double startmillis = OS_milliseconds(); for (i=0; i<1000; i++) hash2 = curve25519_shared(hash2,rand256(0)); printf("curve25519 elapsed %.3f for %d iterations\n",OS_milliseconds() - startmillis,i); startmillis = OS_milliseconds(); bitcoin_pubkey33(myinfo->ctx,pubkey,hash2); for (i=0; i<1000; i++) bitcoin_sharedsecret(myinfo->ctx,hash2,pubkey,33); printf("secp256k1 elapsed %.3f for %d iterations\n",OS_milliseconds() - startmillis,i); getchar();**/ if ( (0) && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"protover\":70002,\"RELAY\":1,\"VALIDATE\":1,\"portp2p\":14631,\"rpc\":14632,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":512,\"endpend\":512,\"services\":129,\"maxpeers\":8,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); if ( 1 && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTC"),cJSON_Parse("{\"portp2p\":8333,\"RELAY\":0,\"VALIDATE\":0,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":1,\"endpend\":1,\"services\":128,\"maxpeers\":8,\"newcoin\":\"BTC\",\"active\":0,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); if ( (0) && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0,myinfo->rpcport)) != 0 ) { free(str); if ( (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0,myinfo->rpcport)) != 0 ) free(str); } } } sleep(1); } } int32_t iguana_commandline(struct supernet_info *myinfo,char *arg) { cJSON *argjson,*array; char *coinargs,*argstr=0,*str; int32_t i,n; long filesize = 0; if ( arg == 0 ) arg = "iguana.conf"; else if ( (COMMANDLINE_ARGFILE= OS_filestr(&filesize,arg)) != 0 ) { if ( (argjson= cJSON_Parse(COMMANDLINE_ARGFILE)) == 0 ) { printf("couldnt parse %s: (%s) after initialized\n",arg,COMMANDLINE_ARGFILE); free(COMMANDLINE_ARGFILE); COMMANDLINE_ARGFILE = 0; } else { IGUANA_NUMHELPERS = juint(argjson,"numhelpers"); myinfo->remoteorigin = juint(argjson,"remoteorigin"); free_json(argjson); printf("Will run (%s) after initialized with %d threads\n",COMMANDLINE_ARGFILE,IGUANA_NUMHELPERS); } } else if ( arg != 0 ) { if ( arg[0] == '{' || arg[0] == '[' ) argstr = arg; //else argstr = OS_filestr(&filesize,arg); if ( argstr != 0 && (argjson= cJSON_Parse(argstr)) != 0 ) { IGUANA_NUMHELPERS = juint(argjson,"numhelpers"); if ( (myinfo->rpcport= juint(argjson,"port")) == 0 ) myinfo->rpcport = IGUANA_RPCPORT; if ( (myinfo->publicRPC= juint(argjson,"publicRPC")) != 0 && myinfo->publicRPC != myinfo->rpcport ) myinfo->publicRPC = 0; if ( jstr(argjson,"rpccoin") != 0 ) safecopy(myinfo->rpcsymbol,jstr(argjson,"rpccoin"),sizeof(myinfo->rpcsymbol)); safecopy(Userhome,jstr(argjson,"userhome"),sizeof(Userhome)); if ( jstr(argjson,"tmpdir") != 0 ) { safecopy(GLOBAL_TMPDIR,jstr(argjson,"tmpdir"),sizeof(GLOBAL_TMPDIR)); printf("GLOBAL tmpdir.(%s)\n",GLOBAL_TMPDIR); } printf("call argv JSON.(%s)\n",(char *)arg); SuperNET_JSON(myinfo,0,argjson,0,myinfo->rpcport); if ( (coinargs= SuperNET_keysinit(myinfo,arg)) != 0 ) iguana_launch(0,"iguana_coins",iguana_coins,coinargs,IGUANA_PERMTHREAD); if ( (array= jarray(&n,argjson,"commands")) != 0 ) { for (i=0; irpcport)) != 0 ) free(str); } free_json(argjson); if ( (0) ) { uint32_t buf[81],c; OS_randombytes((void *)buf,sizeof(buf)); printf("("); for (i=0; i<81; i++) { c = buf[i] % 27; if ( c == 26 ) c = '9'; else c += 'a'; printf("%c",c); } printf(") <- IOTA random passphrase\n"); } } //else printf("error parsing.(%s)\n",(char *)argstr); //if ( argstr != arg ) // free(argstr); } return(COMMANDLINE_ARGFILE != 0); } void iguana_ensuredirs() { char dirname[512]; sprintf(dirname,"%s",GLOBAL_HELPDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s",GLOBAL_GENESISDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s",GLOBAL_CONFSDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/TRANSACTIONS",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/purgeable",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s",GLOBAL_TMPDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s",GLOBAL_VALIDATEDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/ECB",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/BTC",GLOBAL_VALIDATEDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/BTCD",GLOBAL_VALIDATEDIR), OS_ensure_directory(dirname); sprintf(dirname,"SVM"), OS_ensure_directory(dirname); sprintf(dirname,"SVM/rawfeatures"), OS_ensure_directory(dirname); sprintf(dirname,"SVM/models"), OS_ensure_directory(dirname); } void iguana_Qinit() { iguana_initQ(&helperQ,"helperQ"); iguana_initQ(&JSON_Q,"jsonQ"); iguana_initQ(&FINISHED_Q,"finishedQ"); iguana_initQ(&bundlesQ,"bundlesQ"); iguana_initQ(&emitQ,"emitQ"); //iguana_initQ(&TerminateQ,"TerminateQ"); } void iguana_helpinit(struct supernet_info *myinfo) { char *tmpstr = 0; if ( (tmpstr= SuperNET_JSON(myinfo,0,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"help\"}"),0,myinfo->rpcport)) != 0 ) { if ( (API_json= cJSON_Parse(tmpstr)) != 0 && (API_json= jobj(API_json,"result")) != 0 ) API_json = jobj(API_json,"API"); else printf("couldnt parse tmpstr\n"); free(tmpstr); } printf("generated API_json tmpstr.%p\n",tmpstr); } void iguana_urlinit(struct supernet_info *myinfo,int32_t ismainnet,int32_t usessl) { int32_t iter,j; FILE *fp; char line[4096],NXTaddr[64]; uint8_t pubkey[32]; strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:7876/nxt"); for (iter=0; iter<2; iter++) { if ( (fp= fopen(iter == 0 ? "nxtpasswords" : "fimpasswords","rb")) != 0 ) { while ( fgets(line,sizeof(line),fp) > 0 ) { j = (int32_t)strlen(line) - 1; line[j] = 0; calc_NXTaddr(NXTaddr,pubkey,(uint8_t *)line,j); printf("FORGING %s (%s)\n",NXTaddr,issue_startForging(myinfo,line)); } fclose(fp); } strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:7886/nxt"); } if ( usessl == 0 ) strcpy(myinfo->NXTAPIURL,"http://127.0.0.1:"); else strcpy(myinfo->NXTAPIURL,"https://127.0.0.1:"); if ( ismainnet != 0 ) strcat(myinfo->NXTAPIURL,"7876/nxt"); else strcat(myinfo->NXTAPIURL,"6876/nxt"); } void jumblr_loop(void *ptr) { struct iguana_info *coin; uint32_t t,n=0; struct supernet_info *myinfo = ptr; int32_t mult = 10; printf("JUMBLR loop\n"); while ( myinfo->IAMNOTARY == 0 ) { if ( (coin= iguana_coinfind("KMD")) != 0 ) { n++; if ( (n % 3) == 0 ) smartaddress_update(myinfo,(n/3) & 1); if ( myinfo->jumblr_passphrase[0] != 0 && coin->FULLNODE < 0 ) { // if BTC has arrived in destination address, invoke DEX -> BTC t = (uint32_t)time(NULL); if ( (t % (120 * mult)) < 60 ) { // if BTC has arrived in deposit address, invoke DEX -> KMD jumblr_iteration(myinfo,coin,(t % (360 * mult)) / (120 * mult),t % (120 * mult)); } //printf("t.%u %p.%d %s\n",t,coin,coin!=0?coin->FULLNODE:0,myinfo->jumblr_passphrase); } } sleep(55); } } void iguana_launchdaemons(struct supernet_info *myinfo) { int32_t i; char *helperargs,helperstr[512]; if ( IGUANA_NUMHELPERS == 0 )//|| COMMANDLINE_ARGFILE != 0 ) IGUANA_NUMHELPERS = 1; for (i=0; i bufsize ) { message = calloc(1,cipherlen); *ptrp = (void *)message; } else message = buf; origptr = cipher; if ( bits256_nonz(srcpubkey) == 0 ) { memcpy(srcpubkey.bytes,cipher,sizeof(srcpubkey)); char str[65]; printf("use attached pubkey.(%s)\n",bits256_str(str,srcpubkey)); cipher += sizeof(srcpubkey); cipherlen -= sizeof(srcpubkey); } nonce = cipher; cipher += crypto_box_NONCEBYTES, cipherlen -= crypto_box_NONCEBYTES; *msglenp = cipherlen - crypto_box_ZEROBYTES; if ( (retptr= _SuperNET_decipher(nonce,cipher,message,cipherlen,srcpubkey,privkey)) == 0 ) { *msglenp = -1; free(*ptrp); } return(retptr); } uint8_t *SuperNET_ciphercalc(void **ptrp,int32_t *cipherlenp,bits256 *privkeyp,bits256 *destpubkeyp,uint8_t *data,int32_t datalen,uint8_t *space2,int32_t space2size) { bits256 mypubkey; uint8_t *buf,*nonce,*cipher,*origptr,space[8192]; int32_t onetimeflag=0,allocsize; *ptrp = 0; allocsize = (datalen + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES); if ( bits256_nonz(*destpubkeyp) == 0 || memcmp(destpubkeyp->bytes,GENESIS_PUBKEY.bytes,sizeof(*destpubkeyp)) == 0 ) { *destpubkeyp = GENESIS_PUBKEY; onetimeflag = 2; // prevent any possible leakage of privkey by encrypting to known destpub } if ( bits256_nonz(*privkeyp) == 0 ) onetimeflag = 1; if ( onetimeflag != 0 ) { crypto_box_keypair(mypubkey.bytes,privkeyp->bytes); allocsize += sizeof(bits256); } if ( allocsize > sizeof(space) ) buf = calloc(1,allocsize); else buf = space; if ( allocsize+sizeof(struct iguana_msghdr) > space2size ) { cipher = calloc(1,allocsize + sizeof(struct iguana_msghdr)); *ptrp = (void *)cipher; } else cipher = space2; cipher = &cipher[sizeof(struct iguana_msghdr)]; origptr = nonce = cipher; if ( onetimeflag != 0 ) { memcpy(cipher,mypubkey.bytes,sizeof(mypubkey)); nonce = &cipher[sizeof(mypubkey)]; } OS_randombytes(nonce,crypto_box_NONCEBYTES); cipher = &nonce[crypto_box_NONCEBYTES]; _SuperNET_cipher(nonce,cipher,(void *)data,datalen,*destpubkeyp,*privkeyp,buf); if ( buf != space ) free(buf); *cipherlenp = allocsize; return(origptr); } cJSON *SuperNET_rosettajson(struct supernet_info *myinfo,bits256 privkey,int32_t showprivs) { uint8_t rmd160[20],pub[33]; uint64_t nxt64bits; bits256 pubkey; char str2[41],wifbuf[64],addr[64],str[128],coinwif[16]; cJSON *retjson; struct iguana_info *coin,*tmp; pubkey = acct777_pubkey(privkey); nxt64bits = acct777_nxt64bits(pubkey); retjson = cJSON_CreateObject(); jaddbits256(retjson,"pubkey",pubkey); RS_encode(str,nxt64bits); jaddstr(retjson,"RS",str); jadd64bits(retjson,"NXT",nxt64bits); bitcoin_pubkey33(0,pub,privkey); init_hexbytes_noT(str,pub,33); jaddstr(retjson,"btcpubkey",str); calc_OP_HASH160(str2,rmd160,str); jaddstr(retjson,"rmd160",str2); HASH_ITER(hh,myinfo->allcoins,coin,tmp) { if ( coin != 0 && coin->symbol[0] != 0 ) { if ( bitcoin_address(addr,coin->chain->pubtype,pub,33) != 0 ) { jaddstr(retjson,coin->symbol,addr); sprintf(coinwif,"%swif",coin->symbol); if ( showprivs != 0 ) { bitcoin_priv2wif(wifbuf,privkey,coin->chain->wiftype); jaddstr(retjson,coinwif,wifbuf); } } } } /*if ( bitcoin_address(addr,0,pub,33) != 0 ) { jaddstr(retjson,"BTC",addr); if ( showprivs != 0 ) { bitcoin_priv2wif(wifbuf,privkey,128); jaddstr(retjson,"BTCwif",wifbuf); } } if ( bitcoin_address(addr,60,pub,33) != 0 ) { jaddstr(retjson,"BTCD",addr); if ( showprivs != 0 ) { bitcoin_priv2wif(wifbuf,privkey,188); jaddstr(retjson,"BTCDwif",wifbuf); } }*/ if ( showprivs != 0 ) jaddbits256(retjson,"privkey",privkey); return(retjson); } cJSON *SuperNET_peerarray(struct iguana_info *coin,int32_t max,int32_t supernetflag) { int32_t i,r,j,n = 0; struct iguana_peer *addr; cJSON *array = cJSON_CreateArray(); if ( coin->peers == 0 ) return(array); r = rand(); for (j=0; jpeers->active[i]; if ( addr->usock >= 0 && supernetflag == (addr->supernet != 0) ) { jaddistr(array,addr->ipaddr); if ( ++n >= max ) break; } } if ( n == 0 ) { free_json(array); return(0); } return(array); } int32_t SuperNET_coinpeers(struct iguana_info *coin,cJSON *SNjson,cJSON *rawjson,int32_t max) { cJSON *array,*item; if ( (array= SuperNET_peerarray(coin,max,1)) != 0 ) { max -= cJSON_GetArraySize(array); item = cJSON_CreateObject(); jaddstr(item,"coin",coin->symbol); jadd(item,"peers",array); jaddi(SNjson,item); } if ( max > 0 && (array= SuperNET_peerarray(coin,max,0)) != 0 ) { max -= cJSON_GetArraySize(array); item = cJSON_CreateObject(); jaddstr(item,"coin",coin->symbol); jadd(item,"peers",array); jaddi(rawjson,item); } return(max); } void SuperNET_remotepeer(struct supernet_info *myinfo,struct iguana_info *coin,char *symbol,char *ipaddr,int32_t supernetflag) { uint64_t ipbits; struct iguana_peer *addr; ipbits = calc_ipbits(ipaddr); printf("got %s remotepeer.(%s) supernet.%d\n",symbol,ipaddr,supernetflag); if ( supernetflag != 0 && (uint32_t)myinfo->myaddr.selfipbits != (uint32_t)ipbits ) { if ( (addr= iguana_peerslot(coin,ipbits,0)) != 0 ) { printf("launch startconnection to supernet peer.(%s)\n",ipaddr); iguana_launch(coin,"connection",iguana_startconnection,addr,IGUANA_CONNTHREAD); return; } } iguana_possible_peer(coin,ipaddr); } void SuperNET_parsepeers(struct supernet_info *myinfo,cJSON *array,int32_t n,int32_t supernetflag) { int32_t i,j,m; cJSON *coinarray,*item; char *symbol,*ipaddr; struct iguana_info *ptr; if ( array != 0 && n > 0 ) { for (i=0; i 0 ) jaddnum(retjson,"RTheight",coin->RTheight); } return(jprint(retjson,1)); } STRING_ARG(iguana,validate,activecoin) { int32_t i,total,validated; struct iguana_bundle *bp; cJSON *retjson; if ( (coin= iguana_coinfind(activecoin)) != 0 ) { for (i=total=validated=0; ibundlescount; i++) if ( (bp= coin->bundles[i]) != 0 ) { validated += iguana_bundlevalidate(myinfo,coin,bp,1); total += bp->n; } retjson = cJSON_CreateObject(); jaddstr(retjson,"result","validation run"); jaddstr(retjson,"coin",coin->symbol); jaddnum(retjson,"validated",validated); jaddnum(retjson,"total",total); jaddnum(retjson,"bundles",coin->bundlescount); jaddnum(retjson,"accuracy",(double)validated/total); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"no active coin\"}")); } STRING_ARG(iguana,removecoin,activecoin) { struct iguana_bundle *bp; int32_t i,height; char fname[1024]; if ( (coin= iguana_coinfind(activecoin)) != 0 ) { coin->active = 0; coin->started = 0; if ( (0) ) { for (i=0; isymbol,i), OS_removefile(fname,0); sprintf(fname,"%s/%s/%04d.vins",coin->VALIDATEDIR,coin->symbol,i), OS_removefile(fname,0); } sprintf(fname,"%s/%s/vouts/*",GLOBAL_DBDIR,coin->symbol), OS_removefile(fname,0); sprintf(fname,"%s/%s/*",coin->VALIDATEDIR,coin->symbol), OS_removefile(fname,0); for (i=0; ibundlescount; i++) { sprintf(fname,"%s/%s/balancecrc.%d",GLOBAL_DBDIR,coin->symbol,i), OS_removefile(fname,0); if ( (bp= coin->bundles[i]) != 0 ) { iguana_bundlepurgefiles(coin,bp); iguana_bundleremove(coin,bp->hdrsi,1); } } for (height=0; heightlongestchain; height+=IGUANA_SUBDIRDIVISOR) { sprintf(fname,"%s/%s/%d",GLOBAL_DBDIR,coin->symbol,height/IGUANA_SUBDIRDIVISOR); OS_remove_directory(fname); } sprintf(fname,"%s/%s/*",GLOBAL_DBDIR,coin->symbol), OS_remove_directory(fname); } return(clonestr("{\"result\":\"success\"}")); } return(clonestr("{\"error\":\"no active coin\"}")); } INT_ARG(bitcoinrpc,getblockhash,height) { cJSON *retjson; if ( coin->notarychain >= 0 && coin->FULLNODE == 0 ) return(_dex_getblockhash(myinfo,coin->symbol,height)); retjson = cJSON_CreateObject(); jaddbits256(retjson,"result",iguana_blockhash(coin,height)); return(jprint(retjson,1)); } HASH_AND_TWOINTS(bitcoinrpc,getblock,blockhash,verbose,remoteonly) { char *blockstr,*datastr; struct iguana_msgblock msg; struct iguana_block *block; cJSON *retjson; bits256 txid; int32_t len; if ( coin->notarychain >= 0 && coin->FULLNODE == 0 ) return(_dex_getblock(myinfo,coin->symbol,blockhash)); retjson = cJSON_CreateObject(); memset(&msg,0,sizeof(msg)); if ( remoteonly == 0 && (block= iguana_blockfind("getblockRPC",coin,blockhash)) != 0 ) { if ( verbose != 0 ) return(jprint(iguana_blockjson(myinfo,coin,block,1),1)); else { if ( (len= iguana_peerblockrequest(myinfo,coin,coin->blockspace,coin->blockspacesize,0,blockhash,0)) > 0 ) { datastr = malloc(len*2 + 1); init_hexbytes_noT(datastr,coin->blockspace,len); jaddstr(retjson,"result",datastr); free(datastr); return(jprint(retjson,1)); } jaddstr(retjson,"error","error getting rawblock"); } } else if ( coin->APIblockstr != 0 ) jaddstr(retjson,"error","already have pending request"); else { memset(txid.bytes,0,sizeof(txid)); if ( (blockstr= iguana_APIrequest(coin,blockhash,txid,5)) != 0 ) { jaddstr(retjson,"result",blockstr); free(blockstr); } else jaddstr(retjson,"error","cant find blockhash"); } return(jprint(retjson,1)); } ZERO_ARGS(bitcoinrpc,getbestblockhash) { cJSON *retjson; if ( coin->notarychain >= 0 && coin->FULLNODE == 0 ) return(_dex_getbestblockhash(myinfo,coin->symbol)); retjson = cJSON_CreateObject(); char str[65]; jaddstr(retjson,"result",bits256_str(str,coin->blocks.hwmchain.RO.hash2)); return(jprint(retjson,1)); } ZERO_ARGS(bitcoinrpc,getblockcount) { cJSON *retjson = cJSON_CreateObject(); //printf("result %d\n",coin->blocks.hwmchain.height); jaddnum(retjson,"result",coin->blocks.hwmchain.height); return(jprint(retjson,1)); } STRING_AND_INT(iguana,bundleaddresses,activecoin,height) { struct iguana_info *ptr; if ( (ptr= iguana_coinfind(activecoin)) != 0 ) return(iguana_bundleaddrs(ptr,height / coin->chain->bundlesize)); else return(clonestr("{\"error\":\"activecoin is not active\"}")); } STRING_AND_INT(iguana,PoSweights,activecoin,height) { struct iguana_info *ptr; int32_t num,nonz,errs,bundleheight; struct iguana_pkhash *refP; uint64_t *weights,supply; cJSON *retjson; if ( (ptr= iguana_coinfind(activecoin)) != 0 ) { //for (bundleheight=coin->chain->bundlesize; bundleheightchain->bundlesize) { bundleheight = (height / ptr->chain->bundlesize) * ptr->chain->bundlesize; if ( (weights= iguana_PoS_weights(myinfo,ptr,&refP,&supply,&num,&nonz,&errs,bundleheight)) != 0 ) { retjson = cJSON_CreateObject(); jaddstr(retjson,"result",errs == 0 ? "success" : "error"); jaddnum(retjson,"bundleheight",bundleheight); jaddnum(retjson,"numaddresses",num); jaddnum(retjson,"nonzero",nonz); jaddnum(retjson,"errors",errs); jaddnum(retjson,"supply",dstr(supply)); free(weights); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"iguana_PoS_weights returned null\"}")); } } return(clonestr("{\"error\":\"activecoin is not active\"}")); } STRING_ARG(iguana,stakers,activecoin) { struct iguana_info *ptr; int32_t i,datalen,pkind,hdrsi; bits256 hash2; struct iguana_bundle *bp; cJSON *retjson,*array; struct iguana_pkhash *refP; struct iguana_ramchaindata *rdata; char coinaddr[64]; uint8_t refrmd160[20]; bits256 *sortbuf; if ( (ptr= iguana_coinfind(activecoin)) != 0 && ptr->RTheight > ptr->chain->bundlesize ) { hdrsi = (ptr->RTheight / ptr->chain->bundlesize) - 1; if ( (bp= ptr->bundles[hdrsi]) != 0 && bp->weights != 0 && (rdata= bp->ramchain.H.data) != 0 && bp->weights != 0 ) { sortbuf = calloc(bp->numweights,2 * sizeof(*sortbuf)); for (i=datalen=0; inumweights; i++) datalen += iguana_rwnum(1,&((uint8_t *)sortbuf)[datalen],sizeof(bp->weights[i]),(void *)&bp->weights[i]); hash2 = bits256_doublesha256(0,(uint8_t *)sortbuf,datalen); refP = RAMCHAIN_PTR(rdata,Poffset); retjson = cJSON_CreateObject(); array = cJSON_CreateArray(); memset(refrmd160,0,sizeof(refrmd160)); for (i=0; ichain->bundlesize; i++) { if ( (pkind= iguana_staker_sort(ptr,&hash2,refrmd160,refP,bp->weights,bp->numweights,sortbuf)) > 0 ) { bitcoin_address(coinaddr,ptr->chain->pubtype,refP[pkind].rmd160,sizeof(refP[pkind].rmd160)); jaddistr(array,coinaddr); } else jaddistr(array,"error"); } jaddstr(retjson,"result","success"); jadd(retjson,"stakers",array); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"iguana_stakers needs PoSweights and weights\"}")); } return(clonestr("{\"error\":\"activecoin is not active\"}")); } STRING_AND_INT(iguana,bundlehashes,activecoin,height) { struct iguana_info *ptr; struct iguana_bundle *bp; int32_t i,hdrsi; cJSON *retjson,*array; struct iguana_ramchaindata *rdata; if ( (ptr= iguana_coinfind(activecoin)) != 0 ) { hdrsi = height / coin->chain->bundlesize; if ( hdrsi < coin->bundlescount && hdrsi >= 0 && (bp= coin->bundles[hdrsi]) != 0 ) { if ( (rdata= bp->ramchain.H.data) != 0 ) { array = cJSON_CreateArray(); for (i=0; ilhashes[i].txid); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddbits256(retjson,"sha256",rdata->sha256); jadd(retjson,"bundlehashes",array); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"ramchain not there\"}")); } else return(clonestr("{\"error\":\"height is too big\"}")); } else return(clonestr("{\"error\":\"activecoin is not active\"}")); } // low priority RPC HASH_AND_TWOINTS(bitcoinrpc,listsinceblock,blockhash,target,flag) { /*"transactions" : [ { "account" : "doc test", "address" : "mmXgiR6KAhZCyQ8ndr2BCfEq1wNG2UnyG6", "category" : "receive", "amount" : 0.10000000, "vout" : 0, "confirmations" : 76478, "blockhash" : "000000000017c84015f254498c62a7c884a51ccd75d4dd6dbdcb6434aa3bd44d", "blockindex" : 1, "blocktime" : 1399294967, "txid" : "85a98fdf1529f7d5156483ad020a51b7f3340e47448cf932f470b72ff01a6821", "walletconflicts" : [ ], "time" : 1399294967, "timereceived" : 1418924714 },*/ cJSON *retjson = cJSON_CreateObject(); jaddstr(retjson,"error","low priority RPC not implemented"); return(jprint(retjson,1)); } ZERO_ARGS(bitcoinrpc,gettxoutsetinfo) { cJSON *retjson = cJSON_CreateObject(); jaddstr(retjson,"error","low priority RPC not implemented"); return(jprint(retjson,1)); } ZERO_ARGS(bitcoinrpc,listaddressgroupings) { if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); return(clonestr("{\"error\":\"low priority RPC not implemented\"}")); } SS_D_I_S(bitcoinrpc,move,fromaccount,toaccount,amount,minconf,comment) { cJSON *retjson; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( myinfo->expiration == 0 ) return(clonestr("{\"error\":\"need to unlock wallet\"}")); retjson = cJSON_CreateObject(); return(jprint(retjson,1)); } ZERO_ARGS(pax,start) { void PAX_init(); PAX_init(); return(clonestr("{\"result\":\"PAX_init called\"}")); } STRING_AND_TWOINTS(mouse,change,name,x,y) { printf("mouse (%s) x.%d y.%d\n",name,x,y); return(clonestr("{\"result\":\"changed\"}")); } STRING_ARG(mouse,leave,name) { printf("mouse (%s) leave\n",name); return(clonestr("{\"result\":\"left\"}")); } STRING_AND_TWOINTS(mouse,click,name,x,y) { printf("mouse (%s) x.%d y.%d click\n",name,x,y); return(clonestr("{\"result\":\"click\"}")); } STRING_AND_INT(keyboard,key,name,c) { printf(" KEY.(%s) c.%d (%c)\n",name,c,c); return(clonestr("{\"result\":\"key\"}")); } STRING_AND_TWOINTS(mouse,image,name,x,y) { printf("mouse CREATE (%s) x.%d y.%d\n",name,x,y); return(clonestr("{\"result\":\"opened\"}")); } STRING_ARG(mouse,close,name) { printf("mouse CLOSE (%s)\n",name); return(clonestr("{\"result\":\"closed\"}")); } HASH_ARRAY_STRING(basilisk,geckotx,hash,vals,hexstr) { struct iguana_info *btcd; char *retstr=0,*symbol; uint8_t *data,*allocptr,space[4096]; int32_t datalen; bits256 txid; if ( (btcd= iguana_coinfind("BTCD")) != 0 && (symbol= jstr(vals,"symbol")) != 0 ) { if ( (data= get_dataptr(BASILISK_HDROFFSET,&allocptr,&datalen,space,sizeof(space),hexstr)) != 0 ) { txid = bits256_doublesha256(0,data,datalen); retstr = gecko_sendrawtransaction(myinfo,symbol,data,datalen,txid,vals,hexstr); } else retstr = clonestr("{\"error\":\"no tx submitted\"}"); if ( allocptr != 0 ) free(allocptr); if ( retstr == 0 ) retstr = clonestr("{\"error\":\"couldnt create geckotx\"}"); return(retstr); } return(clonestr("{\"error\":\"need symbol and chain and BTCD to create new gecko tx\"}")); } HASH_ARRAY_STRING(basilisk,geckoblock,hash,vals,hexstr) { return(clonestr("{\"error\":\"geckoblock is an internal reporting function\"}")); } HASH_ARRAY_STRING(basilisk,geckoheaders,hash,vals,hexstr) { return(clonestr("{\"error\":\"geckoheaders is an internal reporting function\"}")); } HASH_ARRAY_STRING(basilisk,geckoget,hash,vals,hexstr) { struct iguana_info *btcd,*virt; char *symbol; if ( (btcd= iguana_coinfind("BTCD")) != 0 && (symbol= jstr(vals,"symbol")) != 0 ) { if ( (virt= iguana_coinfind(symbol)) != 0 ) { basilisk_wait(myinfo,virt); return(basilisk_respond_geckoget(myinfo,"GET",&coin->internaladdr,remoteaddr,0,vals,0,0,hash,0)); } else return(clonestr("{\"error\":\"geckoget needs virtualchain\"}")); } return(clonestr("{\"error\":\"geckoget needs BTCD\"}")); } TWO_STRINGS(SuperNET,decryptjson,password,permanentfile) { char pass[8192],fname2[1023],destfname[1024]; cJSON *retjson; bits256 wallethash,wallet2priv; safecopy(pass,password,sizeof(pass)); safecopy(fname2,permanentfile,sizeof(fname2)); wallethash = wallet2priv = GENESIS_PRIVKEY; if ( strlen(pass) == sizeof(wallethash)*2 && is_hexstr(pass,(int32_t)sizeof(bits256)*2) > 0 ) wallethash = bits256_conv(pass); if ( strlen(fname2) == sizeof(wallet2priv)*2 && is_hexstr(fname2,(int32_t)sizeof(bits256)*2) > 0 ) wallet2priv = bits256_conv(fname2); if ( (retjson= SuperNET_decryptedjson(destfname,pass,sizeof(pass),wallethash,fname2,sizeof(fname2),wallet2priv)) != 0 ) { //printf("decrypt pass.(%s) fname2.(%s) -> destfname.(%s)\n",pass,fname2,destfname); //obj = jduplicate(jobj(retjson,"payload")); //jdelete(retjson,"payload"); //jadd(retjson,"result",obj); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"couldnt decrypt json file\"}")); } THREE_STRINGS(SuperNET,encryptjson,password,permanentfile,payload) { char destfname[4096],pass[8192],fname2[1023]; cJSON *argjson,*retjson = cJSON_CreateObject(); safecopy(pass,password,sizeof(pass)); safecopy(fname2,permanentfile,sizeof(fname2)); argjson = jduplicate(json); //printf("argjson.(%s)\n",jprint(argjson,0)); jdelete(argjson,"agent"); jdelete(argjson,"method"); jdelete(argjson,"password"); jdelete(argjson,"permanentfile"); jdelete(argjson,"timestamp"); jdelete(argjson,"tag"); if ( _SuperNET_encryptjson(myinfo,destfname,pass,sizeof(pass),fname2,sizeof(fname2),argjson) == 0 ) { jaddstr(retjson,"result","success"); jaddstr(retjson,"filename",destfname); } else jaddstr(retjson,"error","couldnt encrypt json file"); free_json(argjson); return(jprint(retjson,1)); } STRING_ARG(SuperNET,addr2rmd160,address) { uint8_t addrtype,rmd160[20]; char rmdstr[41]; cJSON *retjson; bitcoin_addr2rmd160(&addrtype,rmd160,address); init_hexbytes_noT(rmdstr,rmd160,sizeof(rmd160)); retjson = cJSON_CreateObject(); jaddstr(retjson,"result",rmdstr); jaddnum(retjson,"addrtype",addrtype); jaddstr(retjson,"address",address); return(jprint(retjson,1)); } STRING_ARG(SuperNET,rmd160conv,rmd160) { uint8_t rmdbuf[20]; char coinaddr[64],p2shaddr[64]; cJSON *retjson = cJSON_CreateObject(); if ( rmd160 != 0 && strlen(rmd160) == 40 ) { decode_hex(rmdbuf,20,rmd160); bitcoin_address(coinaddr,coin->chain->pubtype,rmdbuf,20); bitcoin_address(p2shaddr,coin->chain->p2shtype,rmdbuf,20); jaddstr(retjson,"result","success"); jaddstr(retjson,"address",coinaddr); jaddstr(retjson,"p2sh",p2shaddr); } return(jprint(retjson,1)); } HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype) { cJSON *retjson; bits256 pub; uint8_t pubkey[33]; char coinaddr[64],pubkeystr[67]; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); retjson = cJSON_CreateObject(); crypto_box_priv2pub(pub.bytes,privkey.bytes); jaddbits256(retjson,"curve25519",pub); pub = bitcoin_pubkey33(myinfo->ctx,pubkey,privkey); init_hexbytes_noT(pubkeystr,pubkey,33); jaddstr(retjson,"secp256k1",pubkeystr); bitcoin_address(coinaddr,addrtype,pubkey,33); jaddstr(retjson,"result",coinaddr); return(jprint(retjson,1)); } ZERO_ARGS(SuperNET,keypair) { cJSON *retjson; bits256 pubkey,privkey; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); retjson = cJSON_CreateObject(); crypto_box_keypair(pubkey.bytes,privkey.bytes); jaddstr(retjson,"result","generated keypair"); jaddbits256(retjson,"privkey",privkey); jaddbits256(retjson,"pubkey",pubkey); return(jprint(retjson,1)); } TWOHASHES_AND_STRING(SuperNET,decipher,privkey,srcpubkey,cipherstr) { int32_t cipherlen=0,msglen; char *retstr; cJSON *retjson; void *ptr = 0; uint8_t *cipher,*message,space[8192]; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( cipherstr != 0 ) cipherlen = (int32_t)strlen(cipherstr) >> 1; if ( cipherlen < crypto_box_NONCEBYTES ) return(clonestr("{\"error\":\"cipher is too short\"}")); cipher = calloc(1,cipherlen); decode_hex(cipher,cipherlen,cipherstr); if ( (message= SuperNET_deciphercalc(&ptr,&msglen,privkey,srcpubkey,cipher,cipherlen,space,sizeof(space))) != 0 ) { message[msglen] = 0; retjson = cJSON_CreateObject(); jaddstr(retjson,"result","deciphered message"); jaddstr(retjson,"message",(char *)message); retstr = jprint(retjson,1); if ( ptr != 0 ) free(ptr); } else retstr = clonestr("{\"error\":\"couldnt decipher message\"}"); return(retstr); } TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message) { cJSON *retjson; char *retstr,*hexstr,space[8129]; uint8_t space2[8129]; uint8_t *cipher; int32_t cipherlen,onetimeflag; bits256 origprivkey; void *ptr = 0; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( (cipher= SuperNET_ciphercalc(&ptr,&cipherlen,&privkey,&destpubkey,(uint8_t *)message,(int32_t)strlen(message)+1,space2,sizeof(space2))) != 0 ) { if ( cipherlen > sizeof(space)/2 ) hexstr = calloc(1,(cipherlen<<1)+1); else hexstr = (void *)space; init_hexbytes_noT(hexstr,cipher,cipherlen); retjson = cJSON_CreateObject(); jaddstr(retjson,"result",hexstr); onetimeflag = memcmp(origprivkey.bytes,privkey.bytes,sizeof(privkey)); if ( onetimeflag != 0 ) { //jaddbits256(retjson,"onetime_privkey",privkey); jaddbits256(retjson,"onetime_pubkey",destpubkey); if ( onetimeflag == 2 ) jaddstr(retjson,"warning","onetime keypair was used to broadcast"); } retstr = jprint(retjson,1); if ( hexstr != (void *)space ) free(hexstr); if ( ptr != 0 ) free(ptr); return(retstr); } printf("error encrypting message.(%s)\n",message); return(clonestr("{\"error\":\"cant encrypt message\"}")); } bits256 SuperNET_pindecipher(IGUANA_ARGS,char *pin,char *privcipher) { cJSON *testjson; char *mstr,*cstr; bits256 privkey,pinpriv,pinpub; conv_NXTpassword(pinpriv.bytes,pinpub.bytes,(uint8_t *)pin,(int32_t)strlen(pin)); privkey = GENESIS_PRIVKEY; if ( (cstr= SuperNET_decipher(IGUANA_CALLARGS,pinpriv,pinpub,privcipher)) != 0 ) { if ( (testjson= cJSON_Parse(cstr)) != 0 ) { if ( (mstr= jstr(testjson,"message")) != 0 && strlen(mstr) == sizeof(bits256)*2 ) { decode_hex(privkey.bytes,sizeof(privkey),mstr); } else printf("error cant find message privcipher\n"); free_json(testjson); } else printf("Error decipher.(%s)\n",cstr); free(cstr); } else printf("null return from deciphering privcipher\n"); return(privkey); } THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey) { uint8_t flag = 0; uint64_t nxt64bits; bits256 check,privkey,pubkey,pinpriv,pinpub; char str[128],privcipher[512],*privcipherstr,*cstr; cJSON *retjson; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); nxt64bits = conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); if ( showprivkey != 0 && strcmp(showprivkey,"yes") == 0 ) flag = 1; privcipher[0] = 0; conv_NXTpassword(pinpriv.bytes,pinpub.bytes,(uint8_t *)pin,(int32_t)strlen(pin)); if ( (cstr= SuperNET_cipher(IGUANA_CALLARGS,pinpriv,pinpub,bits256_str(str,privkey))) != 0 ) { if ( (retjson= cJSON_Parse(cstr)) != 0 ) { if ( (privcipherstr= jstr(retjson,"result")) != 0 ) strcpy(privcipher,privcipherstr); free_json(retjson); } else printf("error parsing cipher retstr.(%s)\n",cstr); free(cstr); } else printf("error SuperNET_cipher null return\n"); retjson = SuperNET_rosettajson(myinfo,privkey,flag); jaddstr(retjson,"privcipher",privcipher); check = SuperNET_pindecipher(IGUANA_CALLARGS,pin,privcipher); if ( memcmp(check.bytes,privkey.bytes,sizeof(check)) != 0 ) { jaddbits256(retjson,"deciphered",check); jaddstr(retjson,"error","cant recreate privkey from (pin + privcipher)"); } else if ( flag != 0 ) jaddbits256(retjson,"deciphered",check); if ( jobj(retjson,"error") == 0 ) jaddstr(retjson,"result","use pin and privcipher to access wallet"); return(jprint(retjson,1)); } STRING_ARG(SuperNET,broadcastcipher,message) { bits256 zero; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); memset(zero.bytes,0,sizeof(zero)); return(SuperNET_cipher(IGUANA_CALLARGS,zero,zero,message)); } STRING_ARG(SuperNET,broadcastdecipher,message) { bits256 zero; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); memset(zero.bytes,0,sizeof(zero)); return(SuperNET_decipher(IGUANA_CALLARGS,zero,zero,message)); } HASH_AND_STRING(SuperNET,multicastcipher,pubkey,message) { bits256 zero; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); memset(zero.bytes,0,sizeof(zero)); return(SuperNET_cipher(IGUANA_CALLARGS,zero,pubkey,message)); } HASH_AND_STRING(SuperNET,multicastdecipher,privkey,cipherstr) { bits256 zero; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); memset(zero.bytes,0,sizeof(zero)); return(SuperNET_decipher(IGUANA_CALLARGS,privkey,zero,cipherstr)); } ZERO_ARGS(SuperNET,stop) { if ( remoteaddr == 0 || strncmp(remoteaddr,"127.0.0.1",strlen("127.0.0.1")) == 0 ) { iguana_exit(myinfo,0); return(clonestr("{\"result\":\"exit started\"}")); } else return(clonestr("{\"error\":\"cant do a remote stop of this node\"}")); } TWO_ARRAYS(SuperNET,mypeers,supernet,rawpeers) { SuperNET_parsepeers(myinfo,supernet,cJSON_GetArraySize(supernet),1); SuperNET_parsepeers(myinfo,rawpeers,cJSON_GetArraySize(rawpeers),0); return(clonestr("{\"result\":\"peers parsed\"}")); } STRING_ARG(SuperNET,getpeers,activecoin) { int32_t max = 64; struct iguana_info *tmp; cJSON *SNjson,*rawjson,*retjson = cJSON_CreateObject(); SNjson = cJSON_CreateArray(); rawjson = cJSON_CreateArray(); if ( coin != 0 ) max = SuperNET_coinpeers(coin,SNjson,rawjson,max); else { //portable_mutex_lock(&myinfo->allcoins_mutex); HASH_ITER(hh,myinfo->allcoins,coin,tmp) { max = SuperNET_coinpeers(coin,SNjson,rawjson,max); } //portable_mutex_unlock(&myinfo->allcoins_mutex); } if ( max != 64 ) { jaddstr(retjson,"agent","SuperNET"); jaddstr(retjson,"method","mypeers"); jadd(retjson,"supernet",SNjson); jadd(retjson,"rawpeers",rawjson); } else { jaddstr(retjson,"error","no peers"); free_json(SNjson); free_json(rawjson); } return(jprint(retjson,1)); } /*TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(SuperNET,DHT,hexmsg,destip,categoryhash,subhash,maxdelay,broadcast) { if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"cant remote DHT\"}")); else if ( hexmsg == 0 || is_hexstr(hexmsg,(int32_t)strlen(hexmsg)) <= 0 ) return(clonestr("{\"error\":\"hexmsg missing or not in hex\"}")); return(SuperNET_DHTencode(myinfo,destip,categoryhash,subhash,hexmsg,maxdelay,broadcast,juint(json,"plaintext")!=0)); }*/ HASH_AND_STRING(SuperNET,saveconf,wallethash,confjsonstr) { if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); return(clonestr("{\"result\":\"saveconf here\"}")); } HASH_ARRAY_STRING(SuperNET,layer,mypriv,otherpubs,str) { if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); return(clonestr("{\"result\":\"layer encrypt here\"}")); } /*TWO_STRINGS(SuperNET,categoryhashes,category,subcategory) { bits256 categoryhash,subhash; cJSON *retjson = cJSON_CreateObject(); if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); jaddstr(retjson,"result","category hashes calculated"); jaddbits256(retjson,"categoryhash",categoryhash); jaddbits256(retjson,"subhash",subhash); return(jprint(retjson,1)); } TWO_STRINGS(SuperNET,subscribe,category,subcategory) { bits256 categoryhash,subhash; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); if ( category_subscribe(myinfo,categoryhash,subhash) != 0 ) return(clonestr("{\"result\":\"subscribed\"}")); else return(clonestr("{\"error\":\"couldnt subscribe\"}")); } TWO_STRINGS(SuperNET,gethexmsg,category,subcategory) { bits256 categoryhash,subhash; struct category_msg *m; char *hexstr; cJSON *retjson; struct private_chain *cat; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); if ( (m= category_gethexmsg(myinfo,&cat,categoryhash,subhash)) != 0 ) { hexstr = calloc(1,m->len*2+1); init_hexbytes_noT(hexstr,m->msg,m->len); retjson = cJSON_CreateObject(); jaddstr(retjson,"result",hexstr); free(hexstr); return(jprint(retjson,1)); } else return(clonestr("{\"result\":\"no message\"}")); } THREE_STRINGS(SuperNET,posthexmsg,category,subcategory,hexmsg) { bits256 categoryhash,subhash; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); category_posthexmsg(myinfo,categoryhash,subhash,hexmsg,tai_now(),remoteaddr); return(clonestr("{\"result\":\"posted message\"}")); } THREE_STRINGS(SuperNET,announce,category,subcategory,message) { bits256 categoryhash,subhash; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr)); } THREE_STRINGS(SuperNET,survey,category,subcategory,message) { bits256 categoryhash,subhash; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr)); }*/ STRING_ARG(SuperNET,wif2priv,wif) { bits256 privkey; char str[65]; uint8_t privkeytype; cJSON *retjson = cJSON_CreateObject(); if ( bitcoin_wif2priv(&privkeytype,&privkey,wif) == sizeof(privkey) ) { jaddstr(retjson,"result","success"); jaddstr(retjson,"privkey",bits256_str(str,privkey)); jaddnum(retjson,"type",privkeytype); } else jaddstr(retjson,"error","couldnt convert wif"); return(jprint(retjson,1)); } STRING_AND_INT(SuperNET,priv2wif,priv,wiftype) { bits256 privkey; char wifstr[65]; cJSON *retjson = cJSON_CreateObject(); if ( is_hexstr(priv,0) == sizeof(bits256)*2 ) { //wiftype = coin != 0 ? coin->chain->wiftype : 0x80; decode_hex(privkey.bytes,sizeof(privkey),priv); if ( bitcoin_priv2wif(wifstr,privkey,wiftype&0xff) > 0 ) { jaddstr(retjson,"result","success"); jaddstr(retjson,"privkey",priv); jaddnum(retjson,"type",wiftype); jaddstr(retjson,"wif",wifstr); } else jaddstr(retjson,"error","couldnt convert privkey"); } else jaddstr(retjson,"error","non 32 byte hex privkey"); return(jprint(retjson,1)); } STRING_ARG(SuperNET,myipaddr,ipaddr) { cJSON *retjson = cJSON_CreateObject(); myinfo->NOTARY.RELAYID = -1; if ( myinfo->ipaddr[0] == 0 ) { if ( is_ipaddr(ipaddr) != 0 ) { strcpy(myinfo->ipaddr,ipaddr); myinfo->myaddr.myipbits = (uint32_t)calc_ipbits(ipaddr); printf("SET MYIPADDR.(%s)\n",ipaddr); basilisk_setmyid(myinfo); } } jaddstr(retjson,"result",myinfo->ipaddr); if ( myinfo->IAMNOTARY != 0 && myinfo->NOTARY.RELAYID >= 0 ) { jaddnum(retjson,"relayid",myinfo->NOTARY.RELAYID); jaddnum(retjson,"numrelays",myinfo->NOTARY.NUMRELAYS); } return(jprint(retjson,1)); } STRING_ARG(SuperNET,setmyipaddr,ipaddr) { cJSON *retjson = cJSON_CreateObject(); if ( is_ipaddr(ipaddr) != 0 ) { strcpy(myinfo->ipaddr,ipaddr); basilisk_setmyid(myinfo); jaddstr(retjson,"result",myinfo->ipaddr); } else jaddstr(retjson,"error","illegal ipaddr"); return(jprint(retjson,1)); } STRING_ARG(SuperNET,utime2utc,utime) { uint32_t utc = 0; cJSON *retjson = cJSON_CreateObject(); utc = OS_conv_utime(utime); char str[65]; printf("utime.%s -> %u -> %s\n",utime,utc,utc_str(str,utc)); jaddnum(retjson,"result",utc); return(jprint(retjson,1)); } INT_ARG(SuperNET,utc2utime,utc) { char str[65]; cJSON *retjson = cJSON_CreateObject(); jaddstr(retjson,"result",utc_str(str,utc)); return(jprint(retjson,1)); } ZERO_ARGS(SuperNET,logout) { if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); iguana_walletlock(myinfo,coin); return(clonestr("{\"result\":\"logged out\"}")); } ZERO_ARGS(SuperNET,activehandle) { cJSON *retjson; char BTCaddr[64],KMDaddr[64]; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); retjson = SuperNET_rosettajson(myinfo,myinfo->persistent_priv,0); jaddstr(retjson,"result","success"); jaddstr(retjson,"handle",myinfo->handle); if ( myinfo->ipaddr[0] != 0 ) jaddstr(retjson,"myip",myinfo->ipaddr); if ( myinfo->IAMRELAY != 0 ) jaddnum(retjson,"notary",myinfo->NOTARY.RELAYID); jaddbits256(retjson,"persistent",myinfo->myaddr.persistent); if ( myinfo->expiration != 0 ) { jaddstr(retjson,"status","unlocked"); jaddnum(retjson,"duration",myinfo->expiration - time(NULL)); } else jaddstr(retjson,"status","locked"); if ( myinfo->jumblr_passphrase[0] != 0 ) { jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX); jaddstr(retjson,"BTCdeposit","notyet"); jaddstr(retjson,"KMDdeposit",KMDaddr); jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,""); jaddstr(retjson,"BTCjumblr","notyet"); jaddstr(retjson,"KMDjumblr",KMDaddr); } SuperNET_MYINFOadd(myinfo); return(jprint(retjson,1)); } struct supernet_info *SuperNET_accountfind(cJSON *json) { int32_t num; char *decryptstr; struct supernet_info M,*myinfo; struct iguana_info *coin = 0; char *password,*permanentfile,*passphrase,*remoteaddr,*perspriv; myinfo = 0; if ( (password= jstr(json,"password")) == 0 ) password = ""; if ( (permanentfile= jstr(json,"permanentfile")) == 0 ) permanentfile = ""; if ( (passphrase= jstr(json,"passphrase")) == 0 ) passphrase = ""; remoteaddr = jstr(json,"remoteaddr"); if ( (passphrase == 0 || passphrase[0] == 0) && (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,permanentfile)) != 0 ) { if ( (json= cJSON_Parse(decryptstr)) != 0 ) { memset(&M,0,sizeof(M)); if ( (perspriv= jstr(json,"persistent_priv")) != 0 && strlen(perspriv) == sizeof(bits256)*2 ) { M.persistent_priv = bits256_conv(perspriv); SuperNET_setkeys(&M,0,0,0); if ( (myinfo = SuperNET_MYINFOfind(&num,M.myaddr.persistent)) != 0 ) { //printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits); return(myinfo); } } else if ( (passphrase= jstr(json,"result")) != 0 || (passphrase= jstr(json,"passphrase")) != 0 ) { SuperNET_setkeys(&M,passphrase,(int32_t)strlen(passphrase),1); if ( (myinfo= SuperNET_MYINFOfind(&num,M.myaddr.persistent)) != 0 ) { //printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits); return(myinfo); } } else printf("no passphrase in (%s)\n",jprint(json,0)); free_json(json); } else printf("cant parse.(%s)\n",decryptstr); free(decryptstr); } return(SuperNET_MYINFO(0)); } FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase) { char *str,*decryptstr = 0; cJSON *argjson,*item,*walletitem; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( handle != 0 && handle[0] != 0 ) safecopy(myinfo->handle,handle,sizeof(myinfo->handle)); else memset(myinfo->handle,0,sizeof(myinfo->handle)); if ( password == 0 || password[0] == 0 ) password = passphrase; /*if ( password != 0 && password[0] != 0 ) safecopy(myinfo->secret,password,sizeof(myinfo->secret)); else if ( passphrase != 0 && passphrase[0] != 0 ) safecopy(myinfo->secret,passphrase,sizeof(myinfo->secret));*/ if ( permanentfile != 0 ) safecopy(myinfo->permanentfile,permanentfile,sizeof(myinfo->permanentfile)); if ( (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,myinfo->permanentfile)) != 0 ) { //printf("decryptstr.(%s)\n",decryptstr); if ( (argjson= cJSON_Parse(decryptstr)) != 0 ) { if ( jobj(argjson,"error") == 0 ) { //printf("decrypted.(%s) exp.%u pass.(%s)\n",decryptstr,myinfo->expiration,password); if ( myinfo->decryptstr != 0 ) free(myinfo->decryptstr); myinfo->decryptstr = decryptstr; if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) { SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1); free_json(argjson); myinfo->expiration = (uint32_t)(time(NULL) + 3600); return(SuperNET_activehandle(IGUANA_CALLARGS)); } else { free_json(argjson); return(clonestr("{\"error\":\"cant find passphrase in decrypted json\"}")); } } else free_json(argjson); } else { free(decryptstr); return(clonestr("{\"error\":\"cant parse decrypted json\"}")); } } else if ( myinfo->decryptstr != 0 ) { free(myinfo->decryptstr); myinfo->decryptstr = 0; } if ( passphrase != 0 && passphrase[0] != 0 ) { SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1); if ( myinfo->decryptstr != 0 && (argjson= cJSON_Parse(myinfo->decryptstr)) != 0 ) { if ( jobj(argjson,"passphrase") != 0 ) jdelete(argjson,"passphrase"); if ( jobj(argjson,"error") != 0 ) jdelete(argjson,"error"); } else { char rmd160str[41],str[65]; uint8_t rmd160[20]; item = cJSON_CreateObject(); calc_rmd160_sha256(rmd160,myinfo->persistent_pubkey33,33); init_hexbytes_noT(rmd160str,rmd160,20); jaddstr(item,rmd160str,bits256_str(str,myinfo->persistent_priv)); walletitem = cJSON_CreateObject(); jadd(walletitem,"default",item); argjson = cJSON_CreateObject(); jadd(argjson,"wallet",walletitem); myinfo->dirty = (uint32_t)time(NULL); } jaddstr(argjson,"passphrase",passphrase); if ( (str= SuperNET_encryptjson(myinfo,coin,argjson,remoteaddr,password,myinfo->permanentfile,myinfo->decryptstr == 0 ? "" : myinfo->decryptstr)) != 0 ) free(str); myinfo->expiration = (uint32_t)(time(NULL) + 3600); return(SuperNET_activehandle(IGUANA_CALLARGS)); } else return(clonestr("{\"error\":\"need passphrase or wallet doesnt exist\"}")); return(SuperNET_activehandle(IGUANA_CALLARGS)); } #include "../includes/iguana_apiundefs.h" void komodo_ICO_batch(cJSON *array,int32_t batchid) { int32_t i,n,iter; cJSON *item; uint64_t kmdamount,revsamount; char *coinaddr,cmd[512]; double totalKMD,totalREVS; struct supernet_info *myinfo = SuperNET_MYINFO(0); if ( (n= cJSON_GetArraySize(array)) > 0 ) { totalKMD = totalREVS = 0; for (iter=3; iter<4; iter++) for (i=0; i 0 ) { if ( (revsamount= SATOSHIDEN * jdouble(item,"revs_amount")) > 0 ) { printf("# %s KMD %.8f",coinaddr,dstr(kmdamount)); printf(", REVS %.8f\n",dstr(revsamount)); sprintf(cmd,"fiat/revs sendtoaddress %s %.8f",coinaddr,dstr(revsamount)); if ( (iter>>1) == 1 ) { if ( dstr(revsamount) >= 1. && (iter & 1) == 0 ) { printf("curl --url \"http://127.0.0.1:%u\" --data \"{\\\"agent\\\":\\\"dex\\\",\\\"method\\\":\\\"importaddress\\\",\\\"address\\\":\\\"%s\\\",\\\"symbol\\\":\\\"REVS\\\"}\" # %.8f\n",myinfo->rpcport,coinaddr,dstr(revsamount)); printf("sleep 3\n"); } else printf("sleep 1\n"); if ( (iter & 1) != 0 ) { printf("%s\n",cmd); totalREVS += dstr(revsamount); } } } else { if ( iter >= 2 ) continue; } sprintf(cmd,"./komodo-cli sendtoaddress %s %.8f",coinaddr,dstr(kmdamount)); if ( (iter>>1) == 0 ) { printf("# %s KMD %.8f\n",coinaddr,dstr(kmdamount)); if ( (iter & 1) == 0 ) { if ( (0) ) { printf("curl --url \"http://127.0.0.1:%u\" --data \"{\\\"agent\\\":\\\"dex\\\",\\\"method\\\":\\\"importaddress\\\",\\\"address\\\":\\\"%s\\\",\\\"symbol\\\":\\\"KMD\\\"}\" # %.8f\n",myinfo->rpcport,coinaddr,dstr(kmdamount)); printf("sleep 3\n"); } else printf("curl --url \"http://127.0.0.1:%u\" --data \"{\\\"agent\\\":\\\"dex\\\",\\\"method\\\":\\\"listunspent\\\",\\\"address\\\":\\\"%s\\\",\\\"symbol\\\":\\\"KMD\\\"}\"\n",myinfo->rpcport,coinaddr); } else { printf("%s\n",cmd); totalKMD += dstr(kmdamount); printf("sleep 3\n"); } printf("echo \"%.8f <- expected amount %s\"\n\n",dstr(kmdamount),coinaddr); } } } printf("\n# total KMD %.8f REVS %.8f\n",totalKMD,totalREVS); } getchar(); } void komodo_REVS_merge(char *str,char *str2) { char line[1024],line2[1024],*coinaddr; int32_t i,n=0,m=0,k=0; struct supernet_info *myinfo = SuperNET_MYINFO(0); while ( 1 ) { if ( str[n] == 0 || str2[m] == 0 ) break; for (i=0; str[n]!='\n'; n++,i++) line[i] = str[n]; line[i] = 0; n++; for (i=0; str2[m]!='\n'; m++,i++) line2[i] = str2[m]; line2[i] = 0; m++; //if ( is_hexstr(line2,0) != 64 ) { //printf("%d: (%s) (%s)\n",k,line,line2); coinaddr = &line[strlen("fiat/revs sendtoaddress ")]; for (i=0; coinaddr[i]!=' '; i++) ; coinaddr[i] = 0; if ( atof(&coinaddr[i+1]) > 1 ) { printf("curl --url \"http://127.0.0.1:%u\" --data \"{\\\"agent\\\":\\\"dex\\\",\\\"method\\\":\\\"importaddress\\\",\\\"address\\\":\\\"%s\\\",\\\"symbol\\\":\\\"REVS\\\"}\" # %.8f\n",myinfo->rpcport,coinaddr,atof(coinaddr+i+1)); printf("sleep 3\n"); } k++; } } getchar(); } void iguana_main(void *arg) { int32_t usessl = 0,ismainnet = 1, do_OStests = 0; struct supernet_info *myinfo; if ( (IGUANA_BIGENDIAN= iguana_isbigendian()) > 0 ) printf("BIGENDIAN\n"); else if ( IGUANA_BIGENDIAN == 0 ) printf("LITTLE ENDIAN arg.%p\n",arg); else printf("ENDIAN ERROR\n"); mycalloc(0,0,0); #ifdef __APPLE__ char *batchstr,*batchstr2; cJSON *batchjson; long batchsize; char fname[512],fname2[512]; int32_t batchid = 17; sprintf(fname,"REVS.raw"), sprintf(fname2,"REVS.rawtxids"); if ( (0) && (batchstr= OS_filestr(&batchsize,fname)) != 0 && (batchstr2= OS_filestr(&batchsize,fname2)) != 0 ) { komodo_REVS_merge(batchstr,batchstr2); } sprintf(fname,"batch%d.txt",batchid); if ( 1 && (batchstr= OS_filestr(&batchsize,fname)) != 0 ) { if ( (batchjson= cJSON_Parse(batchstr)) != 0 ) { komodo_ICO_batch(batchjson,batchid); free_json(batchjson); } free(batchstr); } #endif myinfo = SuperNET_MYINFO(0); myinfo->rpcport = IGUANA_RPCPORT; decode_hex(CRYPTO777_RMD160,20,CRYPTO777_RMD160STR); decode_hex(CRYPTO777_PUBSECP33,33,CRYPTO777_PUBSECPSTR); iguana_ensuredirs(); iguana_Qinit(); libgfshare_init(myinfo,myinfo->logs,myinfo->exps); myinfo->dpowsock = myinfo->dexsock = myinfo->pubsock = myinfo->subsock = myinfo->reqsock = myinfo->repsock = -1; dex_init(myinfo); myinfo->psockport = 30000; if ( arg != 0 ) { if ( strcmp((char *)arg,"OStests") == 0 ) do_OStests = 1; else if ( strcmp((char *)arg,"notary") == 0 ) { myinfo->rpcport = IGUANA_NOTARYPORT; myinfo->IAMNOTARY = 1; myinfo->DEXEXPLORER = 1; } else if ( strncmp((char *)arg,"-port=",6) == 0 ) { myinfo->rpcport = atoi(&((char *)arg)[6]); printf("OVERRIDE IGUANA port <- %u\n",myinfo->rpcport); } } #ifdef IGUANA_OSTESTS do_OStests = 1; #endif if ( do_OStests != 0 ) { int32_t iguana_OStests(); int32_t retval = iguana_OStests(); printf("OStests retval %d\n",retval); return; } strcpy(myinfo->rpcsymbol,"BTCD"); iguana_urlinit(myinfo,ismainnet,usessl); portable_mutex_init(&myinfo->pending_mutex); portable_mutex_init(&myinfo->dpowmutex); portable_mutex_init(&myinfo->notarymutex); portable_mutex_init(&myinfo->psockmutex); #if LIQUIDITY_PROVIDER myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("nxtae"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bitcoin"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("poloniex"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bittrex"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("btc38"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("huobi"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("coinbase"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("lakebtc"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("quadriga"),0); // prices reversed? myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("okcoin"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("btce"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bitstamp"),0); #endif if ( myinfo->IAMNOTARY == 0 ) { if ( iguana_commandline(myinfo,arg) == 0 ) { iguana_helpinit(myinfo); //iguana_relays_init(myinfo); basilisks_init(myinfo); #ifdef __APPLE__ iguana_appletests(myinfo); #endif char *retstr; if ( (retstr= _dex_getnotaries(myinfo,"KMD")) != 0 ) { printf("INITIAL NOTARIES.(%s)\n",retstr); free(retstr); } } } else { basilisks_init(myinfo); } if ( (0) ) { char *jsonstr = "[\"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828\", \"02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344\", \"03750cf30d739cd7632f77c1c02812dd7a7181628b0558058d4755838117e05339\", \"0394f3529d2e8cc69ffa7a2b55f3761e7be978fa1896ef4c55dc9c275e77e5bf5e\", \"0243c1eeb3777af47187d542e5f8c84f0ac4b05cf5a7ad77faa8cb6d2d56db7823\", \"02bb298844175640a34e908ffdfa2839f77aba3d5edadefee16beb107826e00063\", \"02fa88e549b4b871498f892e527a5d57287916809f8cc3163f641d71c535e8df5a\", \"032f799e370f06476793a122fcd623db7804898fe5aef5572095cfee6353df34bf\", \"02c06fe5401faff4442ef87b7d1b56c2e5a214166615f9a2f2030c71b0cb067ae8\", \"038ac67ca49a8169bcc5de83fe020071095a2c3b2bc4d1c17386977329758956d5\"]"; int32_t i,n; char coinaddr[64]; uint8_t pubkey33[33]; double val = 0.1; cJSON *array; if ( (array= cJSON_Parse(jsonstr)) != 0 ) { n = cJSON_GetArraySize(array); for (i=0; i Z // iguana init nanomsg in own thread