From 18b7795ea23be90b8859cb5619a002a312b669d7 Mon Sep 17 00:00:00 2001 From: SHossain Date: Fri, 12 Oct 2018 13:23:55 +0100 Subject: [PATCH 01/14] Update iguana_notary.c --- iguana/iguana_notary.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index 6b6bf86f1..967fd19a9 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -535,7 +535,7 @@ STRING_ARG(iguana,addnotary,ipaddr) } char NOTARY_CURRENCIES[][65] = { - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "VOTE2018", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL" + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL", "PIRATE", "MGNX", "PGT" }; // "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", From 9d4db8f26a04783453b7474d60b8f607c440c8df Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 6 Dec 2018 02:15:02 -1100 Subject: [PATCH 02/14] Rename --- iguana/{iguana_notary.c => iguana_notary.old} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename iguana/{iguana_notary.c => iguana_notary.old} (100%) diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.old similarity index 100% rename from iguana/iguana_notary.c rename to iguana/iguana_notary.old From 9960d907810de4312025fffb2127f046713fe365 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 6 Dec 2018 02:20:07 -1100 Subject: [PATCH 03/14] -iguana_notary.c --- iguana/iguana_notary.c | 1348 ---------------------------------------- 1 file changed, 1348 deletions(-) delete mode 100755 iguana/iguana_notary.c diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c deleted file mode 100755 index ff1a7c878..000000000 --- a/iguana/iguana_notary.c +++ /dev/null @@ -1,1348 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - - -// Todo list: -// q) investigate if rebroadcast reorged local chain notary tx and scanning mempool is needed - -#define CHECKSIG 0xac - -#include "iguana777.h" -//#include "notaries.h" - -int32_t dpow_datahandler(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint8_t nn_senderind,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen); -uint64_t dpow_maskmin(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); -int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr,char *srccoin); - -#include "dpow/dpow_network.c" -#include "dpow/dpow_rpc.c" -#include "dpow/dpow_tx.c" -#include "dpow/dpow_fsm.c" -#include "dpow/dpow_prices.c" - -void dpow_fifoupdate(struct supernet_info *myinfo,struct dpow_checkpoint *fifo,struct dpow_checkpoint tip) -{ - int32_t i,ind; struct dpow_checkpoint newfifo[DPOW_FIFOSIZE]; - memset(newfifo,0,sizeof(newfifo)); - for (i=DPOW_FIFOSIZE-1; i>0; i--) - { - if ( (0) && bits256_nonz(fifo[i-1].blockhash.hash) != 0 && (tip.blockhash.height - fifo[i-1].blockhash.height) != i ) - printf("(%d != %d) ",(tip.blockhash.height - fifo[i-1].blockhash.height),i); - if ( (ind= (tip.blockhash.height - fifo[i-1].blockhash.height)) >= 0 && ind < DPOW_FIFOSIZE ) - newfifo[ind] = fifo[i-1]; - } - newfifo[0] = tip; - memcpy(fifo,newfifo,sizeof(newfifo)); - //for (i=0; itimestamp = timestamp; - checkpoint->blocktime = blocktime; - checkpoint->blockhash.hash = hash; - checkpoint->blockhash.height = height; -} - -void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) -{ - //struct komodo_ccdataMoMoM mdata; cJSON *blockjson; uint64_t signedmask; struct iguana_info *coin; - void **ptrs; char str[65]; struct dpow_checkpoint checkpoint; int32_t i,ht,suppress=0; struct dpow_block *bp; - dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); - checkpoint = dp->srcfifo[dp->srcconfirms]; - dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); - if ( strcmp(dp->dest,"KMD") == 0 ) - { - if ( dp->DESTHEIGHT < dp->prevDESTHEIGHT+DPOW_CHECKPOINTFREQ ) - { - suppress = 1; - //fprintf(stderr,"suppress %s -> KMD\n",dp->symbol); - } - } - /*if ( strcmp(dp->dest,"KMD") == 0 )//|| strcmp(dp->dest,"CHAIN") == 0 ) - { - //if ( dp->SRCREALTIME == 0 ) - // return; - if ( (coin= iguana_coinfind(dp->symbol)) != 0 ) - { - hash = dpow_getbestblockhash(myinfo,coin); - if ( bits256_nonz(hash) != 0 ) - { - if ( (blockjson= dpow_getblock(myinfo,coin,hash)) != 0 ) - { - height = jint(blockjson,"height"); - if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,height,&mdata) <= 0 ) - { - if ( mdata.pairs != 0 ) - free(mdata.pairs); - blocktime = juint(blockjson,"time"); - free_json(blockjson); - if ( height > 0 && blocktime > 0 ) - { - dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("dynamic set %s/%s %s <- height.%d\n",dp->symbol,dp->dest,bits256_str(str,hash),height); - checkpoint = dp->last; - } else return; - if ( bits256_nonz(dp->activehash) != 0 && bits256_cmp(dp->activehash,checkpoint.blockhash.hash) == 0 ) - { - printf("activehash.(%s) is current checkpoint, skip\n",bits256_str(str,dp->activehash)); - return; - } - else if ( bits256_nonz(dp->lastnotarized) != 0 && bits256_cmp(dp->lastnotarized,checkpoint.blockhash.hash) == 0 ) - { - printf("lastnotarized.(%s) is current checkpoint, skip\n",bits256_str(str,dp->lastnotarized)); - return; - } - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("checkpoint.(%s) is not active and not lastnotarized\n",bits256_str(str,checkpoint.blockhash.hash)); - } else return; - } else return; - } else return; - } else return; - }*/ - if ( dp->freq <= 0 ) - dp->freq = 1; - if ( suppress == 0 && bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % dp->freq) == 0 ) - { - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d freq.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),dp->minsigs,dp->freq); - dpow_heightfind(myinfo,dp,checkpoint.blockhash.height + 1000); - dp->prevDESTHEIGHT = dp->DESTHEIGHT; - ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint) + sizeof(pthread_t)); - ptrs[0] = (void *)myinfo; - ptrs[1] = (void *)dp; - ptrs[2] = (void *)(uint64_t)dp->minsigs; - //if ( strcmp(dp->dest,"KMD") != 0 ) - ptrs[3] = (void *)DPOW_DURATION; - //else ptrs[3] = (void *)(DPOW_DURATION * 60); // essentially try forever for assetchains - ptrs[4] = 0; - memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); - dp->activehash = checkpoint.blockhash.hash; - ht = checkpoint.blockhash.height; - if ( OS_thread_create((void *)((uint64_t)&ptrs[5] + sizeof(struct dpow_checkpoint)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) - { - } - if ( ht > DPOW_MAXFREQ*5 ) - { - if ( (0) && strcmp("CHIPS",dp->symbol) == 0 ) - printf("ht.%d maxblocks.%d\n",ht,dp->maxblocks); - for (i=ht-DPOW_MAXFREQ*5; i>ht-DPOW_MAXFREQ*100&&i>DPOW_MAXFREQ; i--) - { - if ( (bp= dp->blocks[i]) != 0 && bp->state == 0xffffffff ) //(i % DPOW_MAXFREQ) != 0 && - { - if ( dp->currentbp == dp->blocks[i] ) - dp->currentbp = 0; - dp->blocks[i] = 0; - Numallocated--; - free(bp); - } - } - } - } -} - -void dpow_approvedset(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint,bits256 *txs,int32_t numtx) -{ - int32_t i,j; bits256 txid; - if ( txs != 0 ) - { - for (i=0; iapproved[j].hash) == 0 ) - { - if ( bits256_nonz(checkpoint->approved.hash) == 0 || dp->approved[j].height >= checkpoint->approved.height ) - checkpoint->approved = dp->approved[j]; - } - } - } - } - } -} - -void dpow_destconfirm(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint) -{ - int32_t i; - if ( bits256_nonz(checkpoint->approved.hash) != 0 ) - { - for (i=DPOW_FIFOSIZE-1; i>0; i--) - dp->notarized[i] = dp->notarized[i-1]; - dp->notarized[0] = checkpoint->approved; - } -} - -void dpow_destupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) -{ - dp->destupdated = timestamp; - dp->DESTHEIGHT = height; - dpow_checkpointset(myinfo,&dp->destchaintip,height,hash,timestamp,blocktime); - dpow_approvedset(myinfo,dp,&dp->destchaintip,dp->desttx,dp->numdesttx); - dpow_fifoupdate(myinfo,dp->destfifo,dp->destchaintip); - if ( strcmp(dp->dest,"BTC") == 0 ) - { - //printf("%s destupdate ht.%d\n",dp->dest,height); - dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_BTCCONFIRMS]); - } - else dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_KOMODOCONFIRMS*2]); // todo: change to notarized KMD depth -} - -void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) -{ - int32_t height,num; uint32_t blocktime; bits256 blockhash,merkleroot; struct iguana_info *src,*dest; - //if ( strcmp(dp->symbol,"KMD") == 0 ) - { - num = dpow_nanomsg_update(myinfo); - //fprintf(stderr,"nano.%d ",num); - } - src = iguana_coinfind(dp->symbol); - dest = iguana_coinfind(dp->dest); - if ( src != 0 && dest != 0 ) - { - //fprintf(stderr,"dp.%p dPoWupdate (%s -> %s)\n",dp,dp!=0?dp->symbol:"",dp!=0?dp->dest:""); - dp->numdesttx = sizeof(dp->desttx)/sizeof(*dp->desttx); - if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) - { - char str[65]; - if ( (0) && strcmp(dp->symbol,"KMD") == 0 )//|| height != dp->destchaintip.blockhash.height+1 ) - printf("[%s].%d %s %s height.%d vs last.%d\n",dp->symbol,dp->SRCHEIGHT,dp->dest,bits256_str(str,blockhash),height,dp->destchaintip.blockhash.height); - if ( height <= dp->destchaintip.blockhash.height ) - { - printf("iguana_dPoWupdate dest.%s reorg detected %d vs %d\n",dp->dest,height,dp->destchaintip.blockhash.height); - if ( height == dp->destchaintip.blockhash.height && bits256_cmp(blockhash,dp->destchaintip.blockhash.hash) != 0 ) - printf("UNEXPECTED ILLEGAL BLOCK in dest chaintip\n"); - } else dpow_destupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); - } // else printf("error getchaintip for %s\n",dp->dest); - dp->numsrctx = sizeof(dp->srctx)/sizeof(*dp->srctx); - /*if ( (strcmp(dp->dest,"KMD") == 0 || strcmp(dp->dest,"CHAIN") == 0) && dp->SRCHEIGHT < src->longestchain ) - { - //fprintf(stderr,"[I "); - dp->SRCHEIGHT = dpow_issuer_iteration(dp,src,dp->SRCHEIGHT,&dp->SRCREALTIME); - //fprintf(stderr," %d] ",dp->SRCHEIGHT); - }*/ - if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height > 0 ) - { - if ( dp->lastheight == 0 ) - dp->lastheight = height-1; - char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->lastheight); - dp->SRCHEIGHT = height; - if ( height < dp->last.blockhash.height ) - { - printf("iguana_dPoWupdate src.%s reorg detected %d vs %d approved.%d notarized.%d\n",dp->symbol,height,dp->last.blockhash.height,dp->approved[0].height,dp->notarized[0].height); - if ( height <= dp->approved[0].height ) - { - if ( bits256_cmp(blockhash,dp->last.blockhash.hash) != 0 ) - printf("UNEXPECTED ILLEGAL BLOCK in src chaintip\n"); - } - else - { - while ( dp->lastheight <= height ) - { - printf("dp->lastheight.%d <= height.%d\n",dp->lastheight,height); - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); - } - } - } - else //if ( strcmp(dp->symbol,"KMD") == 0 ) - { - while ( dp->lastheight <= height ) - { - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); - } - } - /*else if ( time(NULL) > dp->lastsrcupdate+60 || height != dp->lastheight ) - { - dp->lastsrcupdate = (uint32_t)time(NULL); - dp->lastheight = height; - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight,blockhash,(uint32_t)time(NULL),blocktime); - }*/ - } //else printf("error getchaintip for %s\n",dp->symbol); - } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); -} - -void dpow_addresses() -{ - int32_t i; char coinaddr[64]; uint8_t pubkey[33]; - for (i=0; iDPOWS[myinfo->numdpows]) == 0 ) - myinfo->DPOWS[myinfo->numdpows] = calloc(1,sizeof(*dp)); - if ( (dp= myinfo->DPOWS[myinfo->numdpows]) == 0 ) - return(clonestr("{\"error\":\"dPoW cant allocate memory\"}")); - memset(dp,0,sizeof(*dp)); - destvalid = srcvalid = 0; - if ( myinfo->NOTARY.RELAYID < 0 ) - { - if ( (retstr= basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(myinfo->ipaddr),myinfo->myaddr.persistent)) != 0 ) - { - printf("addrelay.(%s)\n",retstr); - free(retstr); - } - if ( myinfo->NOTARY.RELAYID < 0 ) - return(clonestr("{\"error\":\"must be running as notary node\"}")); - } - if ( dp->symbol[0] != 0 ) - return(clonestr("{\"error\":\"cant dPoW more than one coin at a time\"}")); - if ( pubkey == 0 || pubkey[0] == 0 || is_hexstr(pubkey,0) != 66 ) - return(clonestr("{\"error\":\"need 33 byte pubkey\"}")); - if ( symbol == 0 || symbol[0] == 0 ) - symbol = "KMD"; - if ( dest == 0 || dest[0] == 0 ) - { - if ( strcmp(symbol,"KMD") == 0 ) - dest = "BTC"; - else dest = "KMD"; - } - //if ( myinfo->numdpows == 1 ) - // komodo_assetcoins(-1); - if ( iguana_coinfind(symbol) == 0 ) - return(clonestr("{\"error\":\"cant dPoW an inactive coin\"}")); - if ( strcmp(symbol,"KMD") == 0 && iguana_coinfind("BTC") == 0 ) - return(clonestr("{\"error\":\"cant dPoW KMD without BTC\"}")); - else if ( iguana_coinfind(dest) == 0 ) - return(clonestr("{\"error\":\"cant dPoW without KMD (dest)\"}")); - if ( myinfo->numdpows > 0 ) - { - for (i=0; inumdpows; i++) - if ( strcmp(symbol,myinfo->DPOWS[i]->symbol) == 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"cant dPoW same coin again\"}")); - } - } - strcpy(dp->symbol,symbol); - if ( strcmp(dp->symbol,"KMD") == 0 ) - { - strcpy(dp->dest,"BTC"); - dp->srcconfirms = DPOW_KOMODOCONFIRMS; - } - else - { - strcpy(dp->dest,dest); - dp->srcconfirms = DPOW_THIRDPARTY_CONFIRMS; - } - if ( dp->srcconfirms > DPOW_FIFOSIZE ) - dp->srcconfirms = DPOW_FIFOSIZE; - if ( strcmp("BTC",dp->dest) == 0 ) - { - if ( freq == 0 ) - dp->freq = DPOW_CHECKPOINTFREQ; - else dp->freq = freq; - dp->minsigs = Notaries_BTCminsigs; //DPOW_MINSIGS; - } - else - { - dp->minsigs = Notaries_minsigs; //DPOW_MIN_ASSETCHAIN_SIGS; - if ( freq == 0 && (strcmp("CHIPS",dp->symbol) == 0 || strncmp("TEST",dp->symbol,4) == 0) ) - dp->freq = DPOW_MAXFREQ; - else if ( freq > 2 ) - dp->freq = freq; - else dp->freq = 2; - } - src = iguana_coinfind(dp->symbol); - destcoin = iguana_coinfind(dp->dest); - if ( src == 0 || destcoin == 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"source coin or dest coin not there\"}")); - } - char tmp[67]; - safecopy(tmp,pubkey,sizeof(tmp)); - decode_hex(dp->minerkey33,33,tmp); - - if (strcmp(src->chain->symbol, "HUSH") == 0) - bitcoin_address_ex(src->chain->symbol, srcaddr, 0x1c, src->chain->pubtype, dp->minerkey33, 33); - else - bitcoin_address(srcaddr, src->chain->pubtype, dp->minerkey33, 33); - - if ( (retstr= dpow_validateaddress(myinfo,src,srcaddr)) != 0 ) - { - json = cJSON_Parse(retstr); - if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) - srcvalid = 1; - else - { - srcvalid = 0; - printf("src validation error %s %s %s\n",src->symbol,srcaddr,retstr); - } - free(retstr); - retstr = 0; - } else printf("%s %s didnt return anything\n",src->symbol,srcaddr); - bitcoin_address(destaddr,destcoin->chain->pubtype,dp->minerkey33,33); - if ( (retstr= dpow_validateaddress(myinfo,destcoin,destaddr)) != 0 ) - { - json = cJSON_Parse(retstr); - if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) - destvalid = 1; - else - { - destvalid = 0; - printf("dest validation error %s %s %s\n",src->symbol,srcaddr,retstr); - } - free(retstr); - retstr = 0; - } else printf("%s %s didnt return anything\n",destcoin->symbol,destaddr); - if ( srcvalid <= 0 || destvalid <= 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"source address or dest address has no privkey, importprivkey\"}")); - } - if ( bitcoin_pubkeylen(dp->minerkey33) <= 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"illegal pubkey\"}")); - } - if ( dp->blocks == 0 ) - { - dp->maxblocks = 10000; - dp->blocks = calloc(dp->maxblocks,sizeof(*dp->blocks)); - } - portable_mutex_init(&dp->paxmutex); - portable_mutex_init(&dp->dexmutex); - PAX_init(); - dp->fullCCid = dpow_CCid(myinfo,src); - myinfo->numdpows++; - for (i=0; i<33; i++) - printf("%02x",dp->minerkey33[i]); - printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d CCid.%u\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs,dp->fullCCid); - return(clonestr("{\"result\":\"success\"}")); -} - -char *dpow_passthru(struct iguana_info *coin,char *function,char *hex) -{ - char params[32768]; int32_t len = 0; - if ( hex != 0 && hex[0] != 0 ) - { - len = (int32_t)strlen(hex) >> 1; - if ( len < sizeof(params)-1 ) - decode_hex((uint8_t *)params,(int32_t)strlen(hex),hex); - else len = 0; - } - params[len] = 0; - return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,function,params)); -} - -TWO_STRINGS(zcash,passthru,function,hex) -{ - if ( (coin= iguana_coinfind("ZEC")) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"ZEC not active, start in bitcoind mode\"}")); -} - -TWO_STRINGS(komodo,passthru,function,hex) -{ - if ( (coin= iguana_coinfind("KMD")) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"KMD not active, start in bitcoind mode\"}")); -} - -THREE_STRINGS(iguana,passthru,asset,function,hex) -{ - if ( asset != 0 && (coin= iguana_coinfind(asset)) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"assetchain not active, start in bitcoind mode\"}")); -} - -TWO_STRINGS(dex,send,hex,handler) -{ - uint8_t data[8192]; int32_t datalen; char *retstr; - if ( hex != 0 && (datalen= is_hexstr(hex,0)) > 0 && (datalen>>1) < sizeof(data) ) - { - datalen >>= 1; - decode_hex(data,datalen,hex); - if ( handler == 0 || handler[0] == 0 ) - handler = "DEX"; - if ( (retstr= dex_reqsend(myinfo,handler,data,datalen,1,"")) == 0 ) - return(clonestr("{\"result\":\"success\"}")); - else return(retstr); - } else return(clonestr("{\"error\":\"dex send: invalid hex\"}")); -} - -STRING_ARG(dpow,pending,fiat) -{ - struct dpow_info *dp; char base[64]; int32_t i; - if ( fiat != 0 && fiat[0] != 0 ) - { - for (i=0; fiat[i]!=0; i++) - base[i] = toupper((int32_t)fiat[i]); - base[i] = 0; - for (i=0; inumdpows; i++) - { - dp = myinfo->DPOWS[i]; - if ( strcmp(dp->symbol,base) == 0 ) - return(jprint(dpow_withdraws_pending(dp),1)); - } - } - return(clonestr("[]")); -} - -STRING_ARG(dpow,bindaddr,ipaddr) -{ - uint32_t ipbits; char checkbuf[64]; - if ( ipaddr != 0 && ipaddr[0] != 0 ) - { - ipbits = (uint32_t)calc_ipbits(ipaddr); - expand_ipbits(checkbuf,ipbits); - if ( strcmp(ipaddr,checkbuf) == 0 ) - { - strcpy(myinfo->bindaddr,ipaddr); - return(clonestr("{\"result\":\"success\"}")); - } else return(clonestr("{\"error\":\"invalid bind ipaddr\"}")); - } else return(clonestr("{\"error\":\"no bind ipaddr\"}")); -} - -STRING_ARG(iguana,addnotary,ipaddr) -{ - static int32_t didinit; - if ( didinit == 0 ) - { - dpow_addresses(); - didinit = 1; - } - printf("addnotary (%s) -> (%s)\n",ipaddr,myinfo->ipaddr); - dpow_nanomsginit(myinfo,ipaddr); - return(clonestr("{\"result\":\"notary node added\"}")); -} - -char NOTARY_CURRENCIES[][65] = { - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL", "PIRATE", "MGNX", "PGT", "KMDICE", "DION", "ZEX" -}; - -// "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - -void _iguana_notarystats(char *fname,int32_t totals[64],int32_t dispflag) -{ - FILE *fp; uint64_t signedmask; long fpos,startfpos; int32_t i,height,iter,prevheight; - if ( (fp= fopen(fname,"rb")) != 0 ) - { - printf("opened %s\n",fname); - startfpos = 0; - prevheight = -1; - for (iter=0; iter<2; iter++) - { - while ( 1 ) - { - fpos = ftell(fp); - if (fread(&height,1,sizeof(height),fp) == sizeof(height) && fread(&signedmask,1,sizeof(signedmask),fp) == sizeof(signedmask) ) - { - //printf("%6d %016llx\n",height,(long long)signedmask); - if ( height < prevheight ) - { - startfpos = fpos; - if ( iter == 0 ) - printf("found reversed height %d vs %d\n",height,prevheight); - else printf("fpos.%ld fatal unexpected height reversal %d vs %d\n",fpos,height,prevheight); - } - if ( iter == 1 && (height >= 180000 || strcmp(fname,"signedmasks") != 0) ) - { - for (i=0; i<64; i++) - { - if ( ((1LL << i) & signedmask) != 0 ) - { - totals[i]++; - if ( dispflag > 1 ) - printf("%2d ",i); - } - } - if ( dispflag > 1 ) - printf("height.%d %016llx %s\n",height,(long long)signedmask,fname); - } - prevheight = height; - } else break; - } - if ( iter == 0 ) - { - prevheight = -1; - fseek(fp,startfpos,SEEK_SET); - printf("set startfpos %ld\n",startfpos); - } - } - fclose(fp); - if ( dispflag != 0 ) - { - printf("after %s\n",fname); - for (i=0; i= DPOW_MIN_ASSETCHAIN_SIGS ) - { - notarymask = numnotaries = 0; - for (i=0; i>= 1; - decode_hex(script,len,hexstr); - if ( script[0] == 33 && script[34] == 0xac ) - { - for (j=0; j 0 ) - { - if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) - { - hasnotarization = 1; - *nothtp = 0; - if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) - { - bits256 blockhash,txid,MoM; uint32_t MoMdepth; char symbol[65];//,str[65],str2[65],str3[65]; - vout = jitem(vouts,numvouts-1); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 36*2 && len < sizeof(script)*2 ) - { - len >>= 1; - decode_hex(script,len,hexstr); - if ( dpow_opreturn_parsesrc(&blockhash,nothtp,&txid,symbol,&MoM,&MoMdepth,script,len,mdata) > 0 && strcmp(symbol,coin->symbol) == 0 ) - { - // if ( Notaries_port != DPOW_SOCKPORT ) // keep going till valid MoM found, useful for new chains without any MoM - { - if ( bits256_nonz(MoM) == 0 || MoMdepth == 0 || *nothtp >= height || *nothtp < 0 ) - { - *nothtp = 0; - } - } - if ( mdata->pairs != 0 && mdata->numpairs > 0 ) - { - for (j=0; jnumpairs; j++) - { - if ( mdata->pairs[j].notarization_height > coin->MoMoMheight ) - { - coin->MoMoMheight = mdata->pairs[j].notarization_height; - printf("set %s MoMoMheight <- %d\n",coin->symbol,coin->MoMoMheight); - } - } - } - //printf("%s.%d notarizationht.%d %s -> %s MoM.%s [%d]\n",symbol,height,*nothtp,bits256_str(str,blockhash),bits256_str(str2,txid),bits256_str(str3,MoM),MoMdepth); - } - } - } - } - } - } - } - free_json(txobj); - } - if ( hasnotarization != 0 ) - (*signedmaskp) = notarymask; - return(hasnotarization); -} - -int32_t dpow_hasnotarization(uint64_t *signedmaskp,int32_t *nothtp,struct supernet_info *myinfo,struct iguana_info *coin,cJSON *blockjson,int32_t ht,struct komodo_ccdataMoMoM *mdata) -{ - int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; - *nothtp = 0; - *signedmaskp = 0; - memset(mdata,0,sizeof(*mdata)); - if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) - { - for (i=0; i maxheight ) - break; - blockhash = dpow_getblockhash(myinfo,coin,ht); - if ( (blockjson= dpow_getblock(myinfo,coin,blockhash)) != 0 ) - { - if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,ht,&mdata) > 0 ) - { - if ( mdata.pairs != 0 ) - free(mdata.pairs); - for (j=0; j<64; j++) - if ( ((1LL << j) & signedmask) != 0 ) - masksums[j]++; - } - free_json(blockjson); - } - } - array = cJSON_CreateArray(); - for (i=0; i current - numblocks ) - { - printf("ht.%d %llx vs current.%d - %d\n",height,(long long)signedmask,current,numblocks); - for (j=0; j<64; j++) - if ( ((1LL << j) & signedmask) != 0 ) - vals[j] += (double)DPOW_UTXOSIZE / SATOSHIDEN; - } - } else break; - } - fclose(fp); - } else return(clonestr("{\"error\":\"cant open signedmasks\"}")); - for (sum=j=0; j 0. ) - { - bitcoin_address(coinaddr,0,pubkeys[j],33); // fixed - sprintf(cmd,"bitcoin-cli sendtoaddress %s %f\n",coinaddr,val); - if ( sendflag != 0 && system(cmd) != 0 ) - printf("ERROR with (%s)\n",cmd); - else - { - printf("%s\n",cmd); - sum += val; - } - } - } - printf("%s sent %.8f BTC\n",sendflag!=0?"":"would have",sum); - return(clonestr("{\"result\":\"success\"}")); - } - else return(clonestr("{\"error\":\"cant find BTC\"}")); - } - for (i=0; inumnotaries; i++) - { - item = cJSON_CreateObject(); - jaddstr(item,"notary",Notaries_elected[i][0]); - jaddnum(item,"bestk",bp->notaries[i].bestk); - sprintf(hexstr,"%16llx",(long long)bp->notaries[i].recvmask); - jaddstr(item,"recvmask",hexstr); - sprintf(hexstr,"%16llx",(long long)bp->notaries[i].bestmask); - jaddstr(item,"bestmask",hexstr); - jaddi(retjson,item); - } - return(retjson); -} - -STRING_ARG(dpow,active,maskhex) -{ - uint8_t data[8],revdata[8],pubkeys[64][33]; int32_t i,len,current,n; uint64_t mask; cJSON *infojson,*retjson,*array,*notarray; - array = cJSON_CreateArray(); - notarray = cJSON_CreateArray(); - if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 ) - { - current = jint(infojson,"blocks"); - free_json(infojson); - } else return(clonestr("{\"error\":\"cant get current height\"}")); - n = komodo_notaries("KMD",pubkeys,current); - if ( maskhex == 0 || maskhex[0] == 0 ) - { - return(jprint(dpow_recvmasks(myinfo,myinfo->DPOWS[0],myinfo->DPOWS[0]->currentbp),1)); - - /*mask = myinfo->DPOWS[0]->lastrecvmask; - for (i=0; i>= 1; - memset(data,0,sizeof(data)); - decode_hex(data,len,maskhex); - for (i=0; iDPOWS[0]->cancelratify = 1; - return(clonestr("{\"result\":\"queued dpow cancel ratify\"}")); -} - -ZERO_ARGS(dpow,ipaddrs) -{ - char ipaddr[64]; cJSON *array; int32_t i; - array = cJSON_CreateArray(); - for (i=0; inumdpowipbits; i++) - { - expand_ipbits(ipaddr,myinfo->dpowipbits[i]); - jaddistr(array,ipaddr); - } - return(jprint(array,1)); -} - -TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified) -{ - void **ptrs; bits256 zero; int32_t i; char *source; struct dpow_checkpoint checkpoint; - if ( ratified == 0 ) - return(clonestr("{\"error\":\"no ratified list for dpow ratify\"}")); - memset(zero.bytes,0,sizeof(zero)); - dpow_checkpointset(myinfo,&checkpoint,0,zero,timestamp,timestamp); - ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); - ptrs[0] = (void *)myinfo; - if ( (source= jstr(json,"source")) == 0 ) - source = "KMD"; - ptrs[1] = (void *)myinfo->DPOWS[0]; - for (i=0; inumdpows; i++) - if ( strcmp(myinfo->DPOWS[0]->symbol,source) == 0 ) - { - ptrs[1] = (void *)myinfo->DPOWS[i]; - break; - } - ptrs[2] = (void *)(long)minsigs; - ptrs[3] = (void *)DPOW_RATIFYDURATION; - ptrs[4] = (void *)jprint(ratified,0); - memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); - myinfo->DPOWS[0]->cancelratify = 0; - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) - { - } - return(clonestr("{\"result\":\"started ratification\"}")); -} - -HASH_AND_STRING(dex,gettransaction,txid,symbol) -{ - /*char str[65],url[1024],*retstr; - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); - - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); - }*/ - return(_dex_getrawtransaction(myinfo,symbol,txid)); -} - -HASH_AND_STRING_AND_INT(dex,gettxout,txid,symbol,vout) -{ - /*char str[65],url[1024],*retstr; - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); - }*/ - return(_dex_gettxout(myinfo,symbol,txid,vout)); -} - -TWO_STRINGS(dex,listunspent,symbol,address) -{ - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - char url[1024],*retstr,*coinaddr,*script; int32_t i,n,vout; cJSON *retjson,*data,*item,*item3,*data3; bits256 txid; uint64_t val; - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - data = jarray(&n,retjson,"data"); - data3 = cJSON_CreateArray(); - //[{"hash":"e0a40dac21103e92e0dc9311a0233640489afc5beb5ba3b009848a8e9151dc55","time":"2017-02-21T16:48:28+0000","confirmations":1,"is_coinbase":false,"value":4100000,"index":1,"address":"19rjYdJtRN3qoammX3r1gxy9bvh8p8DmRc","type":"pubkeyhash","multisig":null,"script":"OP_DUP OP_HASH160 6128e7459989d35d530bcd4066c9aaf1f925430a OP_EQUALVERIFY OP_CHECKSIG","script_hex":"76a9146128e7459989d35d530bcd4066c9aaf1f925430a88ac"}] - /*{ - "txid" : "e95d3083baf733dfda2fcd1110fe2937cb3580f8b1b237aad547528440dfa873", - "vout" : 1, - "address" : "RNgdefRo2iRLWqDXEogJrsTw35MgDPQP4R", - "account" : "", - "scriptPubKey" : "76a91493088c5f3546225e0ef6ba9c9c6a74d4c2df877388ac", - "amount" : 150.00000000, - "interest" : 0.30000000, - "confirmations" : 20599, - "spendable" : true - }*/ - for (i=0; iFULLNODE < 0 ) - return(jprint(dpow_listunspent(myinfo,coin,address),1)); - //printf("call _dex_listunspent\n"); - return(_dex_listunspent(myinfo,symbol,address)); -} - -TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions,symbol,address,count,skip) -{ - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - char url[1024],*retstr,*retstr2; cJSON *retjson,*retjson2,*retjson3,*data,*data2; int32_t i,n; - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/transactions?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unconfirmed-transactions?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr2= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 && (retjson2= cJSON_Parse(retstr2)) != 0 ) - { - data = jarray(&n,retjson,"data"); - data2 = jarray(&n,retjson2,"data"); - retjson3 = jduplicate(data); - if ( n > 0 ) - { - for (i=0; i (%s)\n",retstr,retstr2,jprint(retjson3,0)); - free(retstr); - free(retstr2); - free_json(retjson); - free_json(retjson2); - return(jprint(retjson3,1)); - } - } - } - } - return(_dex_listtransactions(myinfo,symbol,address,count,skip)); -} - -STRING_ARG(dex,getinfo,symbol) -{ - return(_dex_getinfo(myinfo,symbol)); -} - -STRING_ARG(dex,getbestblockhash,symbol) -{ - return(_dex_getbestblockhash(myinfo,symbol)); -} - -STRING_ARG(dex,alladdresses,symbol) -{ - return(_dex_alladdresses(myinfo,symbol)); -} - -STRING_AND_INT(dex,getblockhash,symbol,height) -{ - return(_dex_getblockhash(myinfo,symbol,height)); -} - -HASH_AND_STRING(dex,getblock,hash,symbol) -{ - return(_dex_getblock(myinfo,symbol,hash)); -} - -TWO_STRINGS(dex,sendrawtransaction,symbol,signedtx) -{ - return(_dex_sendrawtransaction(myinfo,symbol,signedtx)); -} - -TWO_STRINGS(dex,importaddress,symbol,address) -{ - return(_dex_importaddress(myinfo,symbol,address)); -} - -TWO_STRINGS(dex,checkaddress,symbol,address) -{ - return(_dex_checkaddress(myinfo,symbol,address)); -} - -TWO_STRINGS(dex,validateaddress,symbol,address) -{ - return(_dex_validateaddress(myinfo,symbol,address)); -} - -STRING_ARG(dex,getmessage,argstr) -{ - return(_dex_getmessage(myinfo,argstr)); -} - -STRING_ARG(dex,psock,argstr) -{ - return(_dex_psock(myinfo,argstr)); -} - -STRING_ARG(dex,getnotaries,symbol) -{ - return(clonestr("{\"error\":\"dexgetnotaries deprecated\"}")); - //return(_dex_getnotaries(myinfo,symbol)); -} - -TWO_STRINGS(dex,kvsearch,symbol,key) -{ - if ( key == 0 || key[0] == 0 ) - return(clonestr("{\"error\":\"kvsearch parameter error\"}")); - return(_dex_kvsearch(myinfo,symbol,key)); -} - -THREE_STRINGS_AND_THREE_INTS(dex,kvupdate,symbol,key,value,flags,unused,unusedb) -{ - // need to have some micropayments between client/server, otherwise receiving server incurs costs - if ( key == 0 || key[0] == 0 || value == 0 || value[0] == 0 ) - return(clonestr("{\"error\":\"kvupdate parameter error\"}")); - if ( strcmp(symbol,"KV") == 0 ) - { - if ( flags > 1 ) - return(clonestr("{\"error\":\"only single duration updates via remote access\"}")); - else if ( strlen(key) > 64 || strlen(value) > 256 ) - return(clonestr("{\"error\":\"only keylen <=64 and valuesize <= 256 allowed via remote access\"}")); - else - { - //printf("call _dex_kvupdate.(%s) -> (%s) flags.%d\n",key,value,flags); - return(_dex_kvupdate(myinfo,symbol,key,value,flags)); - } - } else return(clonestr("{\"error\":\"free updates only on KV chain\"}")); -} - -#include "kmd_lookup.h" - -TWO_STRINGS(dex,listunspent2,symbol,address) -{ - cJSON *retjson; - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) - return(clonestr("[]")); - if ( (retjson= kmd_listunspent(myinfo,coin,address)) != 0 ) - return(jprint(retjson,1)); - } - } - if ( symbol != 0 && address != 0 ) - return(_dex_listunspent2(myinfo,symbol,address)); - else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); -} - -TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions2,symbol,address,count,skip) -{ - cJSON *retjson; - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) - return(clonestr("[]")); - if ( (retjson= kmd_listtransactions(myinfo,coin,address,count,skip)) != 0 ) - return(jprint(retjson,1)); - } - } - if ( symbol != 0 && address != 0 ) - return(_dex_listtransactions2(myinfo,symbol,address,count,skip)); - else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); -} - -HASH_AND_STRING_AND_INT(dex,gettxin,txid,symbol,vout) -{ - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_gettxin(coin,txid,vout),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 ) - return(_dex_gettxin(myinfo,symbol,txid,vout)); - else return(clonestr("{\"error\":\"dex gettxin null symbolor coin\"}")); -} - -TWO_STRINGS(dex,listspent,symbol,address) -{ - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_listspent(myinfo,coin,address),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 && address != 0 ) - return(_dex_listspent(myinfo,symbol,address)); - else return(clonestr("{\"error\":\"dex listspent null symbol, address or coin\"}")); -} - -TWO_STRINGS(dex,getbalance,symbol,address) -{ - char url[512],*retstr; cJSON *retjson; uint64_t val; - if ( myinfo->DEXEXPLORER != 0 ) - { - //printf("DEXEXPLORER\n"); - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_getbalance(myinfo,coin,address),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 && address != 0 ) - { - if ( strcmp(symbol,"BTC") == 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - //printf("balance\n"); - if ( (val= j64bits(retjson,"balance")) != 0 ) - { - jdelete(retjson,"balance"); - jaddnum(retjson,"balance",dstr(val)); - } - //printf("sent\n"); - if ( (val= j64bits(retjson,"sent")) != 0 ) - { - jdelete(retjson,"sent"); - jaddnum(retjson,"sent",dstr(val)); - } - //printf("received\n"); - if ( (val= j64bits(retjson,"received")) != 0 ) - { - jdelete(retjson,"received"); - jaddnum(retjson,"received",dstr(val)); - } - //printf("unconfirmed_sent\n"); - if ( (val= j64bits(retjson,"unconfirmed_sent")) != 0 ) - { - jdelete(retjson,"unconfirmed_sent"); - jaddnum(retjson,"unconfirmed_sent",dstr(val)); - } - //printf("unconfirmed_received\n"); - if ( (val= j64bits(retjson,"unconfirmed_received")) != 0 ) - { - jdelete(retjson,"unconfirmed_received"); - jaddnum(retjson,"unconfirmed_received",dstr(val)); - } - //printf("blocktrail.(%s) -> (%s)\n",retstr,jprint(retjson,0)); - free(retstr); - retstr = jprint(retjson,1); - } - } - return(retstr); - } - return(_dex_getbalance(myinfo,symbol,address)); - } else return(clonestr("{\"error\":\"dex getbalance null symbol, address or coin\"}")); -} - -STRING_ARG(dex,explorer,symbol) -{ - if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - myinfo->DEXEXPLORER = 1; - coin->DEXEXPLORER = 1; - return(clonestr("{\"result\":\"success\"}")); - } - return(clonestr("{\"error\":\"coin not active\"}")); -} - -#include "../includes/iguana_apiundefs.h" From 5fa57daecfce47e1fabc6aa4828af38b9d480d87 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 6 Dec 2018 02:20:26 -1100 Subject: [PATCH 04/14] Revert "-iguana_notary.c" This reverts commit 9960d907810de4312025fffb2127f046713fe365. --- iguana/iguana_notary.c | 1348 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1348 insertions(+) create mode 100755 iguana/iguana_notary.c diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c new file mode 100755 index 000000000..ff1a7c878 --- /dev/null +++ b/iguana/iguana_notary.c @@ -0,0 +1,1348 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + +// Todo list: +// q) investigate if rebroadcast reorged local chain notary tx and scanning mempool is needed + +#define CHECKSIG 0xac + +#include "iguana777.h" +//#include "notaries.h" + +int32_t dpow_datahandler(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint8_t nn_senderind,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen); +uint64_t dpow_maskmin(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); +int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr,char *srccoin); + +#include "dpow/dpow_network.c" +#include "dpow/dpow_rpc.c" +#include "dpow/dpow_tx.c" +#include "dpow/dpow_fsm.c" +#include "dpow/dpow_prices.c" + +void dpow_fifoupdate(struct supernet_info *myinfo,struct dpow_checkpoint *fifo,struct dpow_checkpoint tip) +{ + int32_t i,ind; struct dpow_checkpoint newfifo[DPOW_FIFOSIZE]; + memset(newfifo,0,sizeof(newfifo)); + for (i=DPOW_FIFOSIZE-1; i>0; i--) + { + if ( (0) && bits256_nonz(fifo[i-1].blockhash.hash) != 0 && (tip.blockhash.height - fifo[i-1].blockhash.height) != i ) + printf("(%d != %d) ",(tip.blockhash.height - fifo[i-1].blockhash.height),i); + if ( (ind= (tip.blockhash.height - fifo[i-1].blockhash.height)) >= 0 && ind < DPOW_FIFOSIZE ) + newfifo[ind] = fifo[i-1]; + } + newfifo[0] = tip; + memcpy(fifo,newfifo,sizeof(newfifo)); + //for (i=0; itimestamp = timestamp; + checkpoint->blocktime = blocktime; + checkpoint->blockhash.hash = hash; + checkpoint->blockhash.height = height; +} + +void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) +{ + //struct komodo_ccdataMoMoM mdata; cJSON *blockjson; uint64_t signedmask; struct iguana_info *coin; + void **ptrs; char str[65]; struct dpow_checkpoint checkpoint; int32_t i,ht,suppress=0; struct dpow_block *bp; + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + checkpoint = dp->srcfifo[dp->srcconfirms]; + dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); + if ( strcmp(dp->dest,"KMD") == 0 ) + { + if ( dp->DESTHEIGHT < dp->prevDESTHEIGHT+DPOW_CHECKPOINTFREQ ) + { + suppress = 1; + //fprintf(stderr,"suppress %s -> KMD\n",dp->symbol); + } + } + /*if ( strcmp(dp->dest,"KMD") == 0 )//|| strcmp(dp->dest,"CHAIN") == 0 ) + { + //if ( dp->SRCREALTIME == 0 ) + // return; + if ( (coin= iguana_coinfind(dp->symbol)) != 0 ) + { + hash = dpow_getbestblockhash(myinfo,coin); + if ( bits256_nonz(hash) != 0 ) + { + if ( (blockjson= dpow_getblock(myinfo,coin,hash)) != 0 ) + { + height = jint(blockjson,"height"); + if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,height,&mdata) <= 0 ) + { + if ( mdata.pairs != 0 ) + free(mdata.pairs); + blocktime = juint(blockjson,"time"); + free_json(blockjson); + if ( height > 0 && blocktime > 0 ) + { + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("dynamic set %s/%s %s <- height.%d\n",dp->symbol,dp->dest,bits256_str(str,hash),height); + checkpoint = dp->last; + } else return; + if ( bits256_nonz(dp->activehash) != 0 && bits256_cmp(dp->activehash,checkpoint.blockhash.hash) == 0 ) + { + printf("activehash.(%s) is current checkpoint, skip\n",bits256_str(str,dp->activehash)); + return; + } + else if ( bits256_nonz(dp->lastnotarized) != 0 && bits256_cmp(dp->lastnotarized,checkpoint.blockhash.hash) == 0 ) + { + printf("lastnotarized.(%s) is current checkpoint, skip\n",bits256_str(str,dp->lastnotarized)); + return; + } + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("checkpoint.(%s) is not active and not lastnotarized\n",bits256_str(str,checkpoint.blockhash.hash)); + } else return; + } else return; + } else return; + } else return; + }*/ + if ( dp->freq <= 0 ) + dp->freq = 1; + if ( suppress == 0 && bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % dp->freq) == 0 ) + { + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d freq.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),dp->minsigs,dp->freq); + dpow_heightfind(myinfo,dp,checkpoint.blockhash.height + 1000); + dp->prevDESTHEIGHT = dp->DESTHEIGHT; + ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint) + sizeof(pthread_t)); + ptrs[0] = (void *)myinfo; + ptrs[1] = (void *)dp; + ptrs[2] = (void *)(uint64_t)dp->minsigs; + //if ( strcmp(dp->dest,"KMD") != 0 ) + ptrs[3] = (void *)DPOW_DURATION; + //else ptrs[3] = (void *)(DPOW_DURATION * 60); // essentially try forever for assetchains + ptrs[4] = 0; + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + dp->activehash = checkpoint.blockhash.hash; + ht = checkpoint.blockhash.height; + if ( OS_thread_create((void *)((uint64_t)&ptrs[5] + sizeof(struct dpow_checkpoint)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + if ( ht > DPOW_MAXFREQ*5 ) + { + if ( (0) && strcmp("CHIPS",dp->symbol) == 0 ) + printf("ht.%d maxblocks.%d\n",ht,dp->maxblocks); + for (i=ht-DPOW_MAXFREQ*5; i>ht-DPOW_MAXFREQ*100&&i>DPOW_MAXFREQ; i--) + { + if ( (bp= dp->blocks[i]) != 0 && bp->state == 0xffffffff ) //(i % DPOW_MAXFREQ) != 0 && + { + if ( dp->currentbp == dp->blocks[i] ) + dp->currentbp = 0; + dp->blocks[i] = 0; + Numallocated--; + free(bp); + } + } + } + } +} + +void dpow_approvedset(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint,bits256 *txs,int32_t numtx) +{ + int32_t i,j; bits256 txid; + if ( txs != 0 ) + { + for (i=0; iapproved[j].hash) == 0 ) + { + if ( bits256_nonz(checkpoint->approved.hash) == 0 || dp->approved[j].height >= checkpoint->approved.height ) + checkpoint->approved = dp->approved[j]; + } + } + } + } + } +} + +void dpow_destconfirm(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint) +{ + int32_t i; + if ( bits256_nonz(checkpoint->approved.hash) != 0 ) + { + for (i=DPOW_FIFOSIZE-1; i>0; i--) + dp->notarized[i] = dp->notarized[i-1]; + dp->notarized[0] = checkpoint->approved; + } +} + +void dpow_destupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) +{ + dp->destupdated = timestamp; + dp->DESTHEIGHT = height; + dpow_checkpointset(myinfo,&dp->destchaintip,height,hash,timestamp,blocktime); + dpow_approvedset(myinfo,dp,&dp->destchaintip,dp->desttx,dp->numdesttx); + dpow_fifoupdate(myinfo,dp->destfifo,dp->destchaintip); + if ( strcmp(dp->dest,"BTC") == 0 ) + { + //printf("%s destupdate ht.%d\n",dp->dest,height); + dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_BTCCONFIRMS]); + } + else dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_KOMODOCONFIRMS*2]); // todo: change to notarized KMD depth +} + +void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) +{ + int32_t height,num; uint32_t blocktime; bits256 blockhash,merkleroot; struct iguana_info *src,*dest; + //if ( strcmp(dp->symbol,"KMD") == 0 ) + { + num = dpow_nanomsg_update(myinfo); + //fprintf(stderr,"nano.%d ",num); + } + src = iguana_coinfind(dp->symbol); + dest = iguana_coinfind(dp->dest); + if ( src != 0 && dest != 0 ) + { + //fprintf(stderr,"dp.%p dPoWupdate (%s -> %s)\n",dp,dp!=0?dp->symbol:"",dp!=0?dp->dest:""); + dp->numdesttx = sizeof(dp->desttx)/sizeof(*dp->desttx); + if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) + { + char str[65]; + if ( (0) && strcmp(dp->symbol,"KMD") == 0 )//|| height != dp->destchaintip.blockhash.height+1 ) + printf("[%s].%d %s %s height.%d vs last.%d\n",dp->symbol,dp->SRCHEIGHT,dp->dest,bits256_str(str,blockhash),height,dp->destchaintip.blockhash.height); + if ( height <= dp->destchaintip.blockhash.height ) + { + printf("iguana_dPoWupdate dest.%s reorg detected %d vs %d\n",dp->dest,height,dp->destchaintip.blockhash.height); + if ( height == dp->destchaintip.blockhash.height && bits256_cmp(blockhash,dp->destchaintip.blockhash.hash) != 0 ) + printf("UNEXPECTED ILLEGAL BLOCK in dest chaintip\n"); + } else dpow_destupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); + } // else printf("error getchaintip for %s\n",dp->dest); + dp->numsrctx = sizeof(dp->srctx)/sizeof(*dp->srctx); + /*if ( (strcmp(dp->dest,"KMD") == 0 || strcmp(dp->dest,"CHAIN") == 0) && dp->SRCHEIGHT < src->longestchain ) + { + //fprintf(stderr,"[I "); + dp->SRCHEIGHT = dpow_issuer_iteration(dp,src,dp->SRCHEIGHT,&dp->SRCREALTIME); + //fprintf(stderr," %d] ",dp->SRCHEIGHT); + }*/ + if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height > 0 ) + { + if ( dp->lastheight == 0 ) + dp->lastheight = height-1; + char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->lastheight); + dp->SRCHEIGHT = height; + if ( height < dp->last.blockhash.height ) + { + printf("iguana_dPoWupdate src.%s reorg detected %d vs %d approved.%d notarized.%d\n",dp->symbol,height,dp->last.blockhash.height,dp->approved[0].height,dp->notarized[0].height); + if ( height <= dp->approved[0].height ) + { + if ( bits256_cmp(blockhash,dp->last.blockhash.hash) != 0 ) + printf("UNEXPECTED ILLEGAL BLOCK in src chaintip\n"); + } + else + { + while ( dp->lastheight <= height ) + { + printf("dp->lastheight.%d <= height.%d\n",dp->lastheight,height); + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); + } + } + } + else //if ( strcmp(dp->symbol,"KMD") == 0 ) + { + while ( dp->lastheight <= height ) + { + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); + } + } + /*else if ( time(NULL) > dp->lastsrcupdate+60 || height != dp->lastheight ) + { + dp->lastsrcupdate = (uint32_t)time(NULL); + dp->lastheight = height; + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight,blockhash,(uint32_t)time(NULL),blocktime); + }*/ + } //else printf("error getchaintip for %s\n",dp->symbol); + } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); +} + +void dpow_addresses() +{ + int32_t i; char coinaddr[64]; uint8_t pubkey[33]; + for (i=0; iDPOWS[myinfo->numdpows]) == 0 ) + myinfo->DPOWS[myinfo->numdpows] = calloc(1,sizeof(*dp)); + if ( (dp= myinfo->DPOWS[myinfo->numdpows]) == 0 ) + return(clonestr("{\"error\":\"dPoW cant allocate memory\"}")); + memset(dp,0,sizeof(*dp)); + destvalid = srcvalid = 0; + if ( myinfo->NOTARY.RELAYID < 0 ) + { + if ( (retstr= basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(myinfo->ipaddr),myinfo->myaddr.persistent)) != 0 ) + { + printf("addrelay.(%s)\n",retstr); + free(retstr); + } + if ( myinfo->NOTARY.RELAYID < 0 ) + return(clonestr("{\"error\":\"must be running as notary node\"}")); + } + if ( dp->symbol[0] != 0 ) + return(clonestr("{\"error\":\"cant dPoW more than one coin at a time\"}")); + if ( pubkey == 0 || pubkey[0] == 0 || is_hexstr(pubkey,0) != 66 ) + return(clonestr("{\"error\":\"need 33 byte pubkey\"}")); + if ( symbol == 0 || symbol[0] == 0 ) + symbol = "KMD"; + if ( dest == 0 || dest[0] == 0 ) + { + if ( strcmp(symbol,"KMD") == 0 ) + dest = "BTC"; + else dest = "KMD"; + } + //if ( myinfo->numdpows == 1 ) + // komodo_assetcoins(-1); + if ( iguana_coinfind(symbol) == 0 ) + return(clonestr("{\"error\":\"cant dPoW an inactive coin\"}")); + if ( strcmp(symbol,"KMD") == 0 && iguana_coinfind("BTC") == 0 ) + return(clonestr("{\"error\":\"cant dPoW KMD without BTC\"}")); + else if ( iguana_coinfind(dest) == 0 ) + return(clonestr("{\"error\":\"cant dPoW without KMD (dest)\"}")); + if ( myinfo->numdpows > 0 ) + { + for (i=0; inumdpows; i++) + if ( strcmp(symbol,myinfo->DPOWS[i]->symbol) == 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"cant dPoW same coin again\"}")); + } + } + strcpy(dp->symbol,symbol); + if ( strcmp(dp->symbol,"KMD") == 0 ) + { + strcpy(dp->dest,"BTC"); + dp->srcconfirms = DPOW_KOMODOCONFIRMS; + } + else + { + strcpy(dp->dest,dest); + dp->srcconfirms = DPOW_THIRDPARTY_CONFIRMS; + } + if ( dp->srcconfirms > DPOW_FIFOSIZE ) + dp->srcconfirms = DPOW_FIFOSIZE; + if ( strcmp("BTC",dp->dest) == 0 ) + { + if ( freq == 0 ) + dp->freq = DPOW_CHECKPOINTFREQ; + else dp->freq = freq; + dp->minsigs = Notaries_BTCminsigs; //DPOW_MINSIGS; + } + else + { + dp->minsigs = Notaries_minsigs; //DPOW_MIN_ASSETCHAIN_SIGS; + if ( freq == 0 && (strcmp("CHIPS",dp->symbol) == 0 || strncmp("TEST",dp->symbol,4) == 0) ) + dp->freq = DPOW_MAXFREQ; + else if ( freq > 2 ) + dp->freq = freq; + else dp->freq = 2; + } + src = iguana_coinfind(dp->symbol); + destcoin = iguana_coinfind(dp->dest); + if ( src == 0 || destcoin == 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"source coin or dest coin not there\"}")); + } + char tmp[67]; + safecopy(tmp,pubkey,sizeof(tmp)); + decode_hex(dp->minerkey33,33,tmp); + + if (strcmp(src->chain->symbol, "HUSH") == 0) + bitcoin_address_ex(src->chain->symbol, srcaddr, 0x1c, src->chain->pubtype, dp->minerkey33, 33); + else + bitcoin_address(srcaddr, src->chain->pubtype, dp->minerkey33, 33); + + if ( (retstr= dpow_validateaddress(myinfo,src,srcaddr)) != 0 ) + { + json = cJSON_Parse(retstr); + if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) + srcvalid = 1; + else + { + srcvalid = 0; + printf("src validation error %s %s %s\n",src->symbol,srcaddr,retstr); + } + free(retstr); + retstr = 0; + } else printf("%s %s didnt return anything\n",src->symbol,srcaddr); + bitcoin_address(destaddr,destcoin->chain->pubtype,dp->minerkey33,33); + if ( (retstr= dpow_validateaddress(myinfo,destcoin,destaddr)) != 0 ) + { + json = cJSON_Parse(retstr); + if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) + destvalid = 1; + else + { + destvalid = 0; + printf("dest validation error %s %s %s\n",src->symbol,srcaddr,retstr); + } + free(retstr); + retstr = 0; + } else printf("%s %s didnt return anything\n",destcoin->symbol,destaddr); + if ( srcvalid <= 0 || destvalid <= 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"source address or dest address has no privkey, importprivkey\"}")); + } + if ( bitcoin_pubkeylen(dp->minerkey33) <= 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"illegal pubkey\"}")); + } + if ( dp->blocks == 0 ) + { + dp->maxblocks = 10000; + dp->blocks = calloc(dp->maxblocks,sizeof(*dp->blocks)); + } + portable_mutex_init(&dp->paxmutex); + portable_mutex_init(&dp->dexmutex); + PAX_init(); + dp->fullCCid = dpow_CCid(myinfo,src); + myinfo->numdpows++; + for (i=0; i<33; i++) + printf("%02x",dp->minerkey33[i]); + printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d CCid.%u\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs,dp->fullCCid); + return(clonestr("{\"result\":\"success\"}")); +} + +char *dpow_passthru(struct iguana_info *coin,char *function,char *hex) +{ + char params[32768]; int32_t len = 0; + if ( hex != 0 && hex[0] != 0 ) + { + len = (int32_t)strlen(hex) >> 1; + if ( len < sizeof(params)-1 ) + decode_hex((uint8_t *)params,(int32_t)strlen(hex),hex); + else len = 0; + } + params[len] = 0; + return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,function,params)); +} + +TWO_STRINGS(zcash,passthru,function,hex) +{ + if ( (coin= iguana_coinfind("ZEC")) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"ZEC not active, start in bitcoind mode\"}")); +} + +TWO_STRINGS(komodo,passthru,function,hex) +{ + if ( (coin= iguana_coinfind("KMD")) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"KMD not active, start in bitcoind mode\"}")); +} + +THREE_STRINGS(iguana,passthru,asset,function,hex) +{ + if ( asset != 0 && (coin= iguana_coinfind(asset)) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"assetchain not active, start in bitcoind mode\"}")); +} + +TWO_STRINGS(dex,send,hex,handler) +{ + uint8_t data[8192]; int32_t datalen; char *retstr; + if ( hex != 0 && (datalen= is_hexstr(hex,0)) > 0 && (datalen>>1) < sizeof(data) ) + { + datalen >>= 1; + decode_hex(data,datalen,hex); + if ( handler == 0 || handler[0] == 0 ) + handler = "DEX"; + if ( (retstr= dex_reqsend(myinfo,handler,data,datalen,1,"")) == 0 ) + return(clonestr("{\"result\":\"success\"}")); + else return(retstr); + } else return(clonestr("{\"error\":\"dex send: invalid hex\"}")); +} + +STRING_ARG(dpow,pending,fiat) +{ + struct dpow_info *dp; char base[64]; int32_t i; + if ( fiat != 0 && fiat[0] != 0 ) + { + for (i=0; fiat[i]!=0; i++) + base[i] = toupper((int32_t)fiat[i]); + base[i] = 0; + for (i=0; inumdpows; i++) + { + dp = myinfo->DPOWS[i]; + if ( strcmp(dp->symbol,base) == 0 ) + return(jprint(dpow_withdraws_pending(dp),1)); + } + } + return(clonestr("[]")); +} + +STRING_ARG(dpow,bindaddr,ipaddr) +{ + uint32_t ipbits; char checkbuf[64]; + if ( ipaddr != 0 && ipaddr[0] != 0 ) + { + ipbits = (uint32_t)calc_ipbits(ipaddr); + expand_ipbits(checkbuf,ipbits); + if ( strcmp(ipaddr,checkbuf) == 0 ) + { + strcpy(myinfo->bindaddr,ipaddr); + return(clonestr("{\"result\":\"success\"}")); + } else return(clonestr("{\"error\":\"invalid bind ipaddr\"}")); + } else return(clonestr("{\"error\":\"no bind ipaddr\"}")); +} + +STRING_ARG(iguana,addnotary,ipaddr) +{ + static int32_t didinit; + if ( didinit == 0 ) + { + dpow_addresses(); + didinit = 1; + } + printf("addnotary (%s) -> (%s)\n",ipaddr,myinfo->ipaddr); + dpow_nanomsginit(myinfo,ipaddr); + return(clonestr("{\"result\":\"notary node added\"}")); +} + +char NOTARY_CURRENCIES[][65] = { + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL", "PIRATE", "MGNX", "PGT", "KMDICE", "DION", "ZEX" +}; + +// "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", + +void _iguana_notarystats(char *fname,int32_t totals[64],int32_t dispflag) +{ + FILE *fp; uint64_t signedmask; long fpos,startfpos; int32_t i,height,iter,prevheight; + if ( (fp= fopen(fname,"rb")) != 0 ) + { + printf("opened %s\n",fname); + startfpos = 0; + prevheight = -1; + for (iter=0; iter<2; iter++) + { + while ( 1 ) + { + fpos = ftell(fp); + if (fread(&height,1,sizeof(height),fp) == sizeof(height) && fread(&signedmask,1,sizeof(signedmask),fp) == sizeof(signedmask) ) + { + //printf("%6d %016llx\n",height,(long long)signedmask); + if ( height < prevheight ) + { + startfpos = fpos; + if ( iter == 0 ) + printf("found reversed height %d vs %d\n",height,prevheight); + else printf("fpos.%ld fatal unexpected height reversal %d vs %d\n",fpos,height,prevheight); + } + if ( iter == 1 && (height >= 180000 || strcmp(fname,"signedmasks") != 0) ) + { + for (i=0; i<64; i++) + { + if ( ((1LL << i) & signedmask) != 0 ) + { + totals[i]++; + if ( dispflag > 1 ) + printf("%2d ",i); + } + } + if ( dispflag > 1 ) + printf("height.%d %016llx %s\n",height,(long long)signedmask,fname); + } + prevheight = height; + } else break; + } + if ( iter == 0 ) + { + prevheight = -1; + fseek(fp,startfpos,SEEK_SET); + printf("set startfpos %ld\n",startfpos); + } + } + fclose(fp); + if ( dispflag != 0 ) + { + printf("after %s\n",fname); + for (i=0; i= DPOW_MIN_ASSETCHAIN_SIGS ) + { + notarymask = numnotaries = 0; + for (i=0; i>= 1; + decode_hex(script,len,hexstr); + if ( script[0] == 33 && script[34] == 0xac ) + { + for (j=0; j 0 ) + { + if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) + { + hasnotarization = 1; + *nothtp = 0; + if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) + { + bits256 blockhash,txid,MoM; uint32_t MoMdepth; char symbol[65];//,str[65],str2[65],str3[65]; + vout = jitem(vouts,numvouts-1); + if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 36*2 && len < sizeof(script)*2 ) + { + len >>= 1; + decode_hex(script,len,hexstr); + if ( dpow_opreturn_parsesrc(&blockhash,nothtp,&txid,symbol,&MoM,&MoMdepth,script,len,mdata) > 0 && strcmp(symbol,coin->symbol) == 0 ) + { + // if ( Notaries_port != DPOW_SOCKPORT ) // keep going till valid MoM found, useful for new chains without any MoM + { + if ( bits256_nonz(MoM) == 0 || MoMdepth == 0 || *nothtp >= height || *nothtp < 0 ) + { + *nothtp = 0; + } + } + if ( mdata->pairs != 0 && mdata->numpairs > 0 ) + { + for (j=0; jnumpairs; j++) + { + if ( mdata->pairs[j].notarization_height > coin->MoMoMheight ) + { + coin->MoMoMheight = mdata->pairs[j].notarization_height; + printf("set %s MoMoMheight <- %d\n",coin->symbol,coin->MoMoMheight); + } + } + } + //printf("%s.%d notarizationht.%d %s -> %s MoM.%s [%d]\n",symbol,height,*nothtp,bits256_str(str,blockhash),bits256_str(str2,txid),bits256_str(str3,MoM),MoMdepth); + } + } + } + } + } + } + } + free_json(txobj); + } + if ( hasnotarization != 0 ) + (*signedmaskp) = notarymask; + return(hasnotarization); +} + +int32_t dpow_hasnotarization(uint64_t *signedmaskp,int32_t *nothtp,struct supernet_info *myinfo,struct iguana_info *coin,cJSON *blockjson,int32_t ht,struct komodo_ccdataMoMoM *mdata) +{ + int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; + *nothtp = 0; + *signedmaskp = 0; + memset(mdata,0,sizeof(*mdata)); + if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) + { + for (i=0; i maxheight ) + break; + blockhash = dpow_getblockhash(myinfo,coin,ht); + if ( (blockjson= dpow_getblock(myinfo,coin,blockhash)) != 0 ) + { + if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,ht,&mdata) > 0 ) + { + if ( mdata.pairs != 0 ) + free(mdata.pairs); + for (j=0; j<64; j++) + if ( ((1LL << j) & signedmask) != 0 ) + masksums[j]++; + } + free_json(blockjson); + } + } + array = cJSON_CreateArray(); + for (i=0; i current - numblocks ) + { + printf("ht.%d %llx vs current.%d - %d\n",height,(long long)signedmask,current,numblocks); + for (j=0; j<64; j++) + if ( ((1LL << j) & signedmask) != 0 ) + vals[j] += (double)DPOW_UTXOSIZE / SATOSHIDEN; + } + } else break; + } + fclose(fp); + } else return(clonestr("{\"error\":\"cant open signedmasks\"}")); + for (sum=j=0; j 0. ) + { + bitcoin_address(coinaddr,0,pubkeys[j],33); // fixed + sprintf(cmd,"bitcoin-cli sendtoaddress %s %f\n",coinaddr,val); + if ( sendflag != 0 && system(cmd) != 0 ) + printf("ERROR with (%s)\n",cmd); + else + { + printf("%s\n",cmd); + sum += val; + } + } + } + printf("%s sent %.8f BTC\n",sendflag!=0?"":"would have",sum); + return(clonestr("{\"result\":\"success\"}")); + } + else return(clonestr("{\"error\":\"cant find BTC\"}")); + } + for (i=0; inumnotaries; i++) + { + item = cJSON_CreateObject(); + jaddstr(item,"notary",Notaries_elected[i][0]); + jaddnum(item,"bestk",bp->notaries[i].bestk); + sprintf(hexstr,"%16llx",(long long)bp->notaries[i].recvmask); + jaddstr(item,"recvmask",hexstr); + sprintf(hexstr,"%16llx",(long long)bp->notaries[i].bestmask); + jaddstr(item,"bestmask",hexstr); + jaddi(retjson,item); + } + return(retjson); +} + +STRING_ARG(dpow,active,maskhex) +{ + uint8_t data[8],revdata[8],pubkeys[64][33]; int32_t i,len,current,n; uint64_t mask; cJSON *infojson,*retjson,*array,*notarray; + array = cJSON_CreateArray(); + notarray = cJSON_CreateArray(); + if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 ) + { + current = jint(infojson,"blocks"); + free_json(infojson); + } else return(clonestr("{\"error\":\"cant get current height\"}")); + n = komodo_notaries("KMD",pubkeys,current); + if ( maskhex == 0 || maskhex[0] == 0 ) + { + return(jprint(dpow_recvmasks(myinfo,myinfo->DPOWS[0],myinfo->DPOWS[0]->currentbp),1)); + + /*mask = myinfo->DPOWS[0]->lastrecvmask; + for (i=0; i>= 1; + memset(data,0,sizeof(data)); + decode_hex(data,len,maskhex); + for (i=0; iDPOWS[0]->cancelratify = 1; + return(clonestr("{\"result\":\"queued dpow cancel ratify\"}")); +} + +ZERO_ARGS(dpow,ipaddrs) +{ + char ipaddr[64]; cJSON *array; int32_t i; + array = cJSON_CreateArray(); + for (i=0; inumdpowipbits; i++) + { + expand_ipbits(ipaddr,myinfo->dpowipbits[i]); + jaddistr(array,ipaddr); + } + return(jprint(array,1)); +} + +TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified) +{ + void **ptrs; bits256 zero; int32_t i; char *source; struct dpow_checkpoint checkpoint; + if ( ratified == 0 ) + return(clonestr("{\"error\":\"no ratified list for dpow ratify\"}")); + memset(zero.bytes,0,sizeof(zero)); + dpow_checkpointset(myinfo,&checkpoint,0,zero,timestamp,timestamp); + ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); + ptrs[0] = (void *)myinfo; + if ( (source= jstr(json,"source")) == 0 ) + source = "KMD"; + ptrs[1] = (void *)myinfo->DPOWS[0]; + for (i=0; inumdpows; i++) + if ( strcmp(myinfo->DPOWS[0]->symbol,source) == 0 ) + { + ptrs[1] = (void *)myinfo->DPOWS[i]; + break; + } + ptrs[2] = (void *)(long)minsigs; + ptrs[3] = (void *)DPOW_RATIFYDURATION; + ptrs[4] = (void *)jprint(ratified,0); + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + myinfo->DPOWS[0]->cancelratify = 0; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + return(clonestr("{\"result\":\"started ratification\"}")); +} + +HASH_AND_STRING(dex,gettransaction,txid,symbol) +{ + /*char str[65],url[1024],*retstr; + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); + + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); + }*/ + return(_dex_getrawtransaction(myinfo,symbol,txid)); +} + +HASH_AND_STRING_AND_INT(dex,gettxout,txid,symbol,vout) +{ + /*char str[65],url[1024],*retstr; + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); + }*/ + return(_dex_gettxout(myinfo,symbol,txid,vout)); +} + +TWO_STRINGS(dex,listunspent,symbol,address) +{ + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + char url[1024],*retstr,*coinaddr,*script; int32_t i,n,vout; cJSON *retjson,*data,*item,*item3,*data3; bits256 txid; uint64_t val; + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + data = jarray(&n,retjson,"data"); + data3 = cJSON_CreateArray(); + //[{"hash":"e0a40dac21103e92e0dc9311a0233640489afc5beb5ba3b009848a8e9151dc55","time":"2017-02-21T16:48:28+0000","confirmations":1,"is_coinbase":false,"value":4100000,"index":1,"address":"19rjYdJtRN3qoammX3r1gxy9bvh8p8DmRc","type":"pubkeyhash","multisig":null,"script":"OP_DUP OP_HASH160 6128e7459989d35d530bcd4066c9aaf1f925430a OP_EQUALVERIFY OP_CHECKSIG","script_hex":"76a9146128e7459989d35d530bcd4066c9aaf1f925430a88ac"}] + /*{ + "txid" : "e95d3083baf733dfda2fcd1110fe2937cb3580f8b1b237aad547528440dfa873", + "vout" : 1, + "address" : "RNgdefRo2iRLWqDXEogJrsTw35MgDPQP4R", + "account" : "", + "scriptPubKey" : "76a91493088c5f3546225e0ef6ba9c9c6a74d4c2df877388ac", + "amount" : 150.00000000, + "interest" : 0.30000000, + "confirmations" : 20599, + "spendable" : true + }*/ + for (i=0; iFULLNODE < 0 ) + return(jprint(dpow_listunspent(myinfo,coin,address),1)); + //printf("call _dex_listunspent\n"); + return(_dex_listunspent(myinfo,symbol,address)); +} + +TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions,symbol,address,count,skip) +{ + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + char url[1024],*retstr,*retstr2; cJSON *retjson,*retjson2,*retjson3,*data,*data2; int32_t i,n; + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/transactions?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unconfirmed-transactions?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr2= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 && (retjson2= cJSON_Parse(retstr2)) != 0 ) + { + data = jarray(&n,retjson,"data"); + data2 = jarray(&n,retjson2,"data"); + retjson3 = jduplicate(data); + if ( n > 0 ) + { + for (i=0; i (%s)\n",retstr,retstr2,jprint(retjson3,0)); + free(retstr); + free(retstr2); + free_json(retjson); + free_json(retjson2); + return(jprint(retjson3,1)); + } + } + } + } + return(_dex_listtransactions(myinfo,symbol,address,count,skip)); +} + +STRING_ARG(dex,getinfo,symbol) +{ + return(_dex_getinfo(myinfo,symbol)); +} + +STRING_ARG(dex,getbestblockhash,symbol) +{ + return(_dex_getbestblockhash(myinfo,symbol)); +} + +STRING_ARG(dex,alladdresses,symbol) +{ + return(_dex_alladdresses(myinfo,symbol)); +} + +STRING_AND_INT(dex,getblockhash,symbol,height) +{ + return(_dex_getblockhash(myinfo,symbol,height)); +} + +HASH_AND_STRING(dex,getblock,hash,symbol) +{ + return(_dex_getblock(myinfo,symbol,hash)); +} + +TWO_STRINGS(dex,sendrawtransaction,symbol,signedtx) +{ + return(_dex_sendrawtransaction(myinfo,symbol,signedtx)); +} + +TWO_STRINGS(dex,importaddress,symbol,address) +{ + return(_dex_importaddress(myinfo,symbol,address)); +} + +TWO_STRINGS(dex,checkaddress,symbol,address) +{ + return(_dex_checkaddress(myinfo,symbol,address)); +} + +TWO_STRINGS(dex,validateaddress,symbol,address) +{ + return(_dex_validateaddress(myinfo,symbol,address)); +} + +STRING_ARG(dex,getmessage,argstr) +{ + return(_dex_getmessage(myinfo,argstr)); +} + +STRING_ARG(dex,psock,argstr) +{ + return(_dex_psock(myinfo,argstr)); +} + +STRING_ARG(dex,getnotaries,symbol) +{ + return(clonestr("{\"error\":\"dexgetnotaries deprecated\"}")); + //return(_dex_getnotaries(myinfo,symbol)); +} + +TWO_STRINGS(dex,kvsearch,symbol,key) +{ + if ( key == 0 || key[0] == 0 ) + return(clonestr("{\"error\":\"kvsearch parameter error\"}")); + return(_dex_kvsearch(myinfo,symbol,key)); +} + +THREE_STRINGS_AND_THREE_INTS(dex,kvupdate,symbol,key,value,flags,unused,unusedb) +{ + // need to have some micropayments between client/server, otherwise receiving server incurs costs + if ( key == 0 || key[0] == 0 || value == 0 || value[0] == 0 ) + return(clonestr("{\"error\":\"kvupdate parameter error\"}")); + if ( strcmp(symbol,"KV") == 0 ) + { + if ( flags > 1 ) + return(clonestr("{\"error\":\"only single duration updates via remote access\"}")); + else if ( strlen(key) > 64 || strlen(value) > 256 ) + return(clonestr("{\"error\":\"only keylen <=64 and valuesize <= 256 allowed via remote access\"}")); + else + { + //printf("call _dex_kvupdate.(%s) -> (%s) flags.%d\n",key,value,flags); + return(_dex_kvupdate(myinfo,symbol,key,value,flags)); + } + } else return(clonestr("{\"error\":\"free updates only on KV chain\"}")); +} + +#include "kmd_lookup.h" + +TWO_STRINGS(dex,listunspent2,symbol,address) +{ + cJSON *retjson; + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) + return(clonestr("[]")); + if ( (retjson= kmd_listunspent(myinfo,coin,address)) != 0 ) + return(jprint(retjson,1)); + } + } + if ( symbol != 0 && address != 0 ) + return(_dex_listunspent2(myinfo,symbol,address)); + else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); +} + +TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions2,symbol,address,count,skip) +{ + cJSON *retjson; + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) + return(clonestr("[]")); + if ( (retjson= kmd_listtransactions(myinfo,coin,address,count,skip)) != 0 ) + return(jprint(retjson,1)); + } + } + if ( symbol != 0 && address != 0 ) + return(_dex_listtransactions2(myinfo,symbol,address,count,skip)); + else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); +} + +HASH_AND_STRING_AND_INT(dex,gettxin,txid,symbol,vout) +{ + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_gettxin(coin,txid,vout),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 ) + return(_dex_gettxin(myinfo,symbol,txid,vout)); + else return(clonestr("{\"error\":\"dex gettxin null symbolor coin\"}")); +} + +TWO_STRINGS(dex,listspent,symbol,address) +{ + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_listspent(myinfo,coin,address),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 && address != 0 ) + return(_dex_listspent(myinfo,symbol,address)); + else return(clonestr("{\"error\":\"dex listspent null symbol, address or coin\"}")); +} + +TWO_STRINGS(dex,getbalance,symbol,address) +{ + char url[512],*retstr; cJSON *retjson; uint64_t val; + if ( myinfo->DEXEXPLORER != 0 ) + { + //printf("DEXEXPLORER\n"); + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_getbalance(myinfo,coin,address),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 && address != 0 ) + { + if ( strcmp(symbol,"BTC") == 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + //printf("balance\n"); + if ( (val= j64bits(retjson,"balance")) != 0 ) + { + jdelete(retjson,"balance"); + jaddnum(retjson,"balance",dstr(val)); + } + //printf("sent\n"); + if ( (val= j64bits(retjson,"sent")) != 0 ) + { + jdelete(retjson,"sent"); + jaddnum(retjson,"sent",dstr(val)); + } + //printf("received\n"); + if ( (val= j64bits(retjson,"received")) != 0 ) + { + jdelete(retjson,"received"); + jaddnum(retjson,"received",dstr(val)); + } + //printf("unconfirmed_sent\n"); + if ( (val= j64bits(retjson,"unconfirmed_sent")) != 0 ) + { + jdelete(retjson,"unconfirmed_sent"); + jaddnum(retjson,"unconfirmed_sent",dstr(val)); + } + //printf("unconfirmed_received\n"); + if ( (val= j64bits(retjson,"unconfirmed_received")) != 0 ) + { + jdelete(retjson,"unconfirmed_received"); + jaddnum(retjson,"unconfirmed_received",dstr(val)); + } + //printf("blocktrail.(%s) -> (%s)\n",retstr,jprint(retjson,0)); + free(retstr); + retstr = jprint(retjson,1); + } + } + return(retstr); + } + return(_dex_getbalance(myinfo,symbol,address)); + } else return(clonestr("{\"error\":\"dex getbalance null symbol, address or coin\"}")); +} + +STRING_ARG(dex,explorer,symbol) +{ + if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + myinfo->DEXEXPLORER = 1; + coin->DEXEXPLORER = 1; + return(clonestr("{\"result\":\"success\"}")); + } + return(clonestr("{\"error\":\"coin not active\"}")); +} + +#include "../includes/iguana_apiundefs.h" From f304ccf126d271863ca80c7cc9872a22942eeff5 Mon Sep 17 00:00:00 2001 From: jl777 Date: Thu, 6 Dec 2018 02:22:23 -1100 Subject: [PATCH 05/14] + --- iguana/iguana_notary.c | 1348 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1348 insertions(+) create mode 100755 iguana/iguana_notary.c diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c new file mode 100755 index 000000000..ff1a7c878 --- /dev/null +++ b/iguana/iguana_notary.c @@ -0,0 +1,1348 @@ +/****************************************************************************** + * Copyright © 2014-2018 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + + +// Todo list: +// q) investigate if rebroadcast reorged local chain notary tx and scanning mempool is needed + +#define CHECKSIG 0xac + +#include "iguana777.h" +//#include "notaries.h" + +int32_t dpow_datahandler(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint8_t nn_senderind,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen); +uint64_t dpow_maskmin(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); +int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr,char *srccoin); + +#include "dpow/dpow_network.c" +#include "dpow/dpow_rpc.c" +#include "dpow/dpow_tx.c" +#include "dpow/dpow_fsm.c" +#include "dpow/dpow_prices.c" + +void dpow_fifoupdate(struct supernet_info *myinfo,struct dpow_checkpoint *fifo,struct dpow_checkpoint tip) +{ + int32_t i,ind; struct dpow_checkpoint newfifo[DPOW_FIFOSIZE]; + memset(newfifo,0,sizeof(newfifo)); + for (i=DPOW_FIFOSIZE-1; i>0; i--) + { + if ( (0) && bits256_nonz(fifo[i-1].blockhash.hash) != 0 && (tip.blockhash.height - fifo[i-1].blockhash.height) != i ) + printf("(%d != %d) ",(tip.blockhash.height - fifo[i-1].blockhash.height),i); + if ( (ind= (tip.blockhash.height - fifo[i-1].blockhash.height)) >= 0 && ind < DPOW_FIFOSIZE ) + newfifo[ind] = fifo[i-1]; + } + newfifo[0] = tip; + memcpy(fifo,newfifo,sizeof(newfifo)); + //for (i=0; itimestamp = timestamp; + checkpoint->blocktime = blocktime; + checkpoint->blockhash.hash = hash; + checkpoint->blockhash.height = height; +} + +void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) +{ + //struct komodo_ccdataMoMoM mdata; cJSON *blockjson; uint64_t signedmask; struct iguana_info *coin; + void **ptrs; char str[65]; struct dpow_checkpoint checkpoint; int32_t i,ht,suppress=0; struct dpow_block *bp; + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + checkpoint = dp->srcfifo[dp->srcconfirms]; + dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); + if ( strcmp(dp->dest,"KMD") == 0 ) + { + if ( dp->DESTHEIGHT < dp->prevDESTHEIGHT+DPOW_CHECKPOINTFREQ ) + { + suppress = 1; + //fprintf(stderr,"suppress %s -> KMD\n",dp->symbol); + } + } + /*if ( strcmp(dp->dest,"KMD") == 0 )//|| strcmp(dp->dest,"CHAIN") == 0 ) + { + //if ( dp->SRCREALTIME == 0 ) + // return; + if ( (coin= iguana_coinfind(dp->symbol)) != 0 ) + { + hash = dpow_getbestblockhash(myinfo,coin); + if ( bits256_nonz(hash) != 0 ) + { + if ( (blockjson= dpow_getblock(myinfo,coin,hash)) != 0 ) + { + height = jint(blockjson,"height"); + if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,height,&mdata) <= 0 ) + { + if ( mdata.pairs != 0 ) + free(mdata.pairs); + blocktime = juint(blockjson,"time"); + free_json(blockjson); + if ( height > 0 && blocktime > 0 ) + { + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("dynamic set %s/%s %s <- height.%d\n",dp->symbol,dp->dest,bits256_str(str,hash),height); + checkpoint = dp->last; + } else return; + if ( bits256_nonz(dp->activehash) != 0 && bits256_cmp(dp->activehash,checkpoint.blockhash.hash) == 0 ) + { + printf("activehash.(%s) is current checkpoint, skip\n",bits256_str(str,dp->activehash)); + return; + } + else if ( bits256_nonz(dp->lastnotarized) != 0 && bits256_cmp(dp->lastnotarized,checkpoint.blockhash.hash) == 0 ) + { + printf("lastnotarized.(%s) is current checkpoint, skip\n",bits256_str(str,dp->lastnotarized)); + return; + } + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("checkpoint.(%s) is not active and not lastnotarized\n",bits256_str(str,checkpoint.blockhash.hash)); + } else return; + } else return; + } else return; + } else return; + }*/ + if ( dp->freq <= 0 ) + dp->freq = 1; + if ( suppress == 0 && bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % dp->freq) == 0 ) + { + if ( (0) && strcmp("KMD",dp->symbol) == 0 ) + printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d freq.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),dp->minsigs,dp->freq); + dpow_heightfind(myinfo,dp,checkpoint.blockhash.height + 1000); + dp->prevDESTHEIGHT = dp->DESTHEIGHT; + ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint) + sizeof(pthread_t)); + ptrs[0] = (void *)myinfo; + ptrs[1] = (void *)dp; + ptrs[2] = (void *)(uint64_t)dp->minsigs; + //if ( strcmp(dp->dest,"KMD") != 0 ) + ptrs[3] = (void *)DPOW_DURATION; + //else ptrs[3] = (void *)(DPOW_DURATION * 60); // essentially try forever for assetchains + ptrs[4] = 0; + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + dp->activehash = checkpoint.blockhash.hash; + ht = checkpoint.blockhash.height; + if ( OS_thread_create((void *)((uint64_t)&ptrs[5] + sizeof(struct dpow_checkpoint)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + if ( ht > DPOW_MAXFREQ*5 ) + { + if ( (0) && strcmp("CHIPS",dp->symbol) == 0 ) + printf("ht.%d maxblocks.%d\n",ht,dp->maxblocks); + for (i=ht-DPOW_MAXFREQ*5; i>ht-DPOW_MAXFREQ*100&&i>DPOW_MAXFREQ; i--) + { + if ( (bp= dp->blocks[i]) != 0 && bp->state == 0xffffffff ) //(i % DPOW_MAXFREQ) != 0 && + { + if ( dp->currentbp == dp->blocks[i] ) + dp->currentbp = 0; + dp->blocks[i] = 0; + Numallocated--; + free(bp); + } + } + } + } +} + +void dpow_approvedset(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint,bits256 *txs,int32_t numtx) +{ + int32_t i,j; bits256 txid; + if ( txs != 0 ) + { + for (i=0; iapproved[j].hash) == 0 ) + { + if ( bits256_nonz(checkpoint->approved.hash) == 0 || dp->approved[j].height >= checkpoint->approved.height ) + checkpoint->approved = dp->approved[j]; + } + } + } + } + } +} + +void dpow_destconfirm(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint) +{ + int32_t i; + if ( bits256_nonz(checkpoint->approved.hash) != 0 ) + { + for (i=DPOW_FIFOSIZE-1; i>0; i--) + dp->notarized[i] = dp->notarized[i-1]; + dp->notarized[0] = checkpoint->approved; + } +} + +void dpow_destupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) +{ + dp->destupdated = timestamp; + dp->DESTHEIGHT = height; + dpow_checkpointset(myinfo,&dp->destchaintip,height,hash,timestamp,blocktime); + dpow_approvedset(myinfo,dp,&dp->destchaintip,dp->desttx,dp->numdesttx); + dpow_fifoupdate(myinfo,dp->destfifo,dp->destchaintip); + if ( strcmp(dp->dest,"BTC") == 0 ) + { + //printf("%s destupdate ht.%d\n",dp->dest,height); + dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_BTCCONFIRMS]); + } + else dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_KOMODOCONFIRMS*2]); // todo: change to notarized KMD depth +} + +void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) +{ + int32_t height,num; uint32_t blocktime; bits256 blockhash,merkleroot; struct iguana_info *src,*dest; + //if ( strcmp(dp->symbol,"KMD") == 0 ) + { + num = dpow_nanomsg_update(myinfo); + //fprintf(stderr,"nano.%d ",num); + } + src = iguana_coinfind(dp->symbol); + dest = iguana_coinfind(dp->dest); + if ( src != 0 && dest != 0 ) + { + //fprintf(stderr,"dp.%p dPoWupdate (%s -> %s)\n",dp,dp!=0?dp->symbol:"",dp!=0?dp->dest:""); + dp->numdesttx = sizeof(dp->desttx)/sizeof(*dp->desttx); + if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) + { + char str[65]; + if ( (0) && strcmp(dp->symbol,"KMD") == 0 )//|| height != dp->destchaintip.blockhash.height+1 ) + printf("[%s].%d %s %s height.%d vs last.%d\n",dp->symbol,dp->SRCHEIGHT,dp->dest,bits256_str(str,blockhash),height,dp->destchaintip.blockhash.height); + if ( height <= dp->destchaintip.blockhash.height ) + { + printf("iguana_dPoWupdate dest.%s reorg detected %d vs %d\n",dp->dest,height,dp->destchaintip.blockhash.height); + if ( height == dp->destchaintip.blockhash.height && bits256_cmp(blockhash,dp->destchaintip.blockhash.hash) != 0 ) + printf("UNEXPECTED ILLEGAL BLOCK in dest chaintip\n"); + } else dpow_destupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); + } // else printf("error getchaintip for %s\n",dp->dest); + dp->numsrctx = sizeof(dp->srctx)/sizeof(*dp->srctx); + /*if ( (strcmp(dp->dest,"KMD") == 0 || strcmp(dp->dest,"CHAIN") == 0) && dp->SRCHEIGHT < src->longestchain ) + { + //fprintf(stderr,"[I "); + dp->SRCHEIGHT = dpow_issuer_iteration(dp,src,dp->SRCHEIGHT,&dp->SRCREALTIME); + //fprintf(stderr," %d] ",dp->SRCHEIGHT); + }*/ + if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height > 0 ) + { + if ( dp->lastheight == 0 ) + dp->lastheight = height-1; + char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->lastheight); + dp->SRCHEIGHT = height; + if ( height < dp->last.blockhash.height ) + { + printf("iguana_dPoWupdate src.%s reorg detected %d vs %d approved.%d notarized.%d\n",dp->symbol,height,dp->last.blockhash.height,dp->approved[0].height,dp->notarized[0].height); + if ( height <= dp->approved[0].height ) + { + if ( bits256_cmp(blockhash,dp->last.blockhash.hash) != 0 ) + printf("UNEXPECTED ILLEGAL BLOCK in src chaintip\n"); + } + else + { + while ( dp->lastheight <= height ) + { + printf("dp->lastheight.%d <= height.%d\n",dp->lastheight,height); + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); + } + } + } + else //if ( strcmp(dp->symbol,"KMD") == 0 ) + { + while ( dp->lastheight <= height ) + { + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); + } + } + /*else if ( time(NULL) > dp->lastsrcupdate+60 || height != dp->lastheight ) + { + dp->lastsrcupdate = (uint32_t)time(NULL); + dp->lastheight = height; + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight,blockhash,(uint32_t)time(NULL),blocktime); + }*/ + } //else printf("error getchaintip for %s\n",dp->symbol); + } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); +} + +void dpow_addresses() +{ + int32_t i; char coinaddr[64]; uint8_t pubkey[33]; + for (i=0; iDPOWS[myinfo->numdpows]) == 0 ) + myinfo->DPOWS[myinfo->numdpows] = calloc(1,sizeof(*dp)); + if ( (dp= myinfo->DPOWS[myinfo->numdpows]) == 0 ) + return(clonestr("{\"error\":\"dPoW cant allocate memory\"}")); + memset(dp,0,sizeof(*dp)); + destvalid = srcvalid = 0; + if ( myinfo->NOTARY.RELAYID < 0 ) + { + if ( (retstr= basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(myinfo->ipaddr),myinfo->myaddr.persistent)) != 0 ) + { + printf("addrelay.(%s)\n",retstr); + free(retstr); + } + if ( myinfo->NOTARY.RELAYID < 0 ) + return(clonestr("{\"error\":\"must be running as notary node\"}")); + } + if ( dp->symbol[0] != 0 ) + return(clonestr("{\"error\":\"cant dPoW more than one coin at a time\"}")); + if ( pubkey == 0 || pubkey[0] == 0 || is_hexstr(pubkey,0) != 66 ) + return(clonestr("{\"error\":\"need 33 byte pubkey\"}")); + if ( symbol == 0 || symbol[0] == 0 ) + symbol = "KMD"; + if ( dest == 0 || dest[0] == 0 ) + { + if ( strcmp(symbol,"KMD") == 0 ) + dest = "BTC"; + else dest = "KMD"; + } + //if ( myinfo->numdpows == 1 ) + // komodo_assetcoins(-1); + if ( iguana_coinfind(symbol) == 0 ) + return(clonestr("{\"error\":\"cant dPoW an inactive coin\"}")); + if ( strcmp(symbol,"KMD") == 0 && iguana_coinfind("BTC") == 0 ) + return(clonestr("{\"error\":\"cant dPoW KMD without BTC\"}")); + else if ( iguana_coinfind(dest) == 0 ) + return(clonestr("{\"error\":\"cant dPoW without KMD (dest)\"}")); + if ( myinfo->numdpows > 0 ) + { + for (i=0; inumdpows; i++) + if ( strcmp(symbol,myinfo->DPOWS[i]->symbol) == 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"cant dPoW same coin again\"}")); + } + } + strcpy(dp->symbol,symbol); + if ( strcmp(dp->symbol,"KMD") == 0 ) + { + strcpy(dp->dest,"BTC"); + dp->srcconfirms = DPOW_KOMODOCONFIRMS; + } + else + { + strcpy(dp->dest,dest); + dp->srcconfirms = DPOW_THIRDPARTY_CONFIRMS; + } + if ( dp->srcconfirms > DPOW_FIFOSIZE ) + dp->srcconfirms = DPOW_FIFOSIZE; + if ( strcmp("BTC",dp->dest) == 0 ) + { + if ( freq == 0 ) + dp->freq = DPOW_CHECKPOINTFREQ; + else dp->freq = freq; + dp->minsigs = Notaries_BTCminsigs; //DPOW_MINSIGS; + } + else + { + dp->minsigs = Notaries_minsigs; //DPOW_MIN_ASSETCHAIN_SIGS; + if ( freq == 0 && (strcmp("CHIPS",dp->symbol) == 0 || strncmp("TEST",dp->symbol,4) == 0) ) + dp->freq = DPOW_MAXFREQ; + else if ( freq > 2 ) + dp->freq = freq; + else dp->freq = 2; + } + src = iguana_coinfind(dp->symbol); + destcoin = iguana_coinfind(dp->dest); + if ( src == 0 || destcoin == 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"source coin or dest coin not there\"}")); + } + char tmp[67]; + safecopy(tmp,pubkey,sizeof(tmp)); + decode_hex(dp->minerkey33,33,tmp); + + if (strcmp(src->chain->symbol, "HUSH") == 0) + bitcoin_address_ex(src->chain->symbol, srcaddr, 0x1c, src->chain->pubtype, dp->minerkey33, 33); + else + bitcoin_address(srcaddr, src->chain->pubtype, dp->minerkey33, 33); + + if ( (retstr= dpow_validateaddress(myinfo,src,srcaddr)) != 0 ) + { + json = cJSON_Parse(retstr); + if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) + srcvalid = 1; + else + { + srcvalid = 0; + printf("src validation error %s %s %s\n",src->symbol,srcaddr,retstr); + } + free(retstr); + retstr = 0; + } else printf("%s %s didnt return anything\n",src->symbol,srcaddr); + bitcoin_address(destaddr,destcoin->chain->pubtype,dp->minerkey33,33); + if ( (retstr= dpow_validateaddress(myinfo,destcoin,destaddr)) != 0 ) + { + json = cJSON_Parse(retstr); + if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) + destvalid = 1; + else + { + destvalid = 0; + printf("dest validation error %s %s %s\n",src->symbol,srcaddr,retstr); + } + free(retstr); + retstr = 0; + } else printf("%s %s didnt return anything\n",destcoin->symbol,destaddr); + if ( srcvalid <= 0 || destvalid <= 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"source address or dest address has no privkey, importprivkey\"}")); + } + if ( bitcoin_pubkeylen(dp->minerkey33) <= 0 ) + { + dp->symbol[0] = 0; + return(clonestr("{\"error\":\"illegal pubkey\"}")); + } + if ( dp->blocks == 0 ) + { + dp->maxblocks = 10000; + dp->blocks = calloc(dp->maxblocks,sizeof(*dp->blocks)); + } + portable_mutex_init(&dp->paxmutex); + portable_mutex_init(&dp->dexmutex); + PAX_init(); + dp->fullCCid = dpow_CCid(myinfo,src); + myinfo->numdpows++; + for (i=0; i<33; i++) + printf("%02x",dp->minerkey33[i]); + printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d CCid.%u\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs,dp->fullCCid); + return(clonestr("{\"result\":\"success\"}")); +} + +char *dpow_passthru(struct iguana_info *coin,char *function,char *hex) +{ + char params[32768]; int32_t len = 0; + if ( hex != 0 && hex[0] != 0 ) + { + len = (int32_t)strlen(hex) >> 1; + if ( len < sizeof(params)-1 ) + decode_hex((uint8_t *)params,(int32_t)strlen(hex),hex); + else len = 0; + } + params[len] = 0; + return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,function,params)); +} + +TWO_STRINGS(zcash,passthru,function,hex) +{ + if ( (coin= iguana_coinfind("ZEC")) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"ZEC not active, start in bitcoind mode\"}")); +} + +TWO_STRINGS(komodo,passthru,function,hex) +{ + if ( (coin= iguana_coinfind("KMD")) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"KMD not active, start in bitcoind mode\"}")); +} + +THREE_STRINGS(iguana,passthru,asset,function,hex) +{ + if ( asset != 0 && (coin= iguana_coinfind(asset)) != 0 ) + return(dpow_passthru(coin,function,hex)); + else return(clonestr("{\"error\":\"assetchain not active, start in bitcoind mode\"}")); +} + +TWO_STRINGS(dex,send,hex,handler) +{ + uint8_t data[8192]; int32_t datalen; char *retstr; + if ( hex != 0 && (datalen= is_hexstr(hex,0)) > 0 && (datalen>>1) < sizeof(data) ) + { + datalen >>= 1; + decode_hex(data,datalen,hex); + if ( handler == 0 || handler[0] == 0 ) + handler = "DEX"; + if ( (retstr= dex_reqsend(myinfo,handler,data,datalen,1,"")) == 0 ) + return(clonestr("{\"result\":\"success\"}")); + else return(retstr); + } else return(clonestr("{\"error\":\"dex send: invalid hex\"}")); +} + +STRING_ARG(dpow,pending,fiat) +{ + struct dpow_info *dp; char base[64]; int32_t i; + if ( fiat != 0 && fiat[0] != 0 ) + { + for (i=0; fiat[i]!=0; i++) + base[i] = toupper((int32_t)fiat[i]); + base[i] = 0; + for (i=0; inumdpows; i++) + { + dp = myinfo->DPOWS[i]; + if ( strcmp(dp->symbol,base) == 0 ) + return(jprint(dpow_withdraws_pending(dp),1)); + } + } + return(clonestr("[]")); +} + +STRING_ARG(dpow,bindaddr,ipaddr) +{ + uint32_t ipbits; char checkbuf[64]; + if ( ipaddr != 0 && ipaddr[0] != 0 ) + { + ipbits = (uint32_t)calc_ipbits(ipaddr); + expand_ipbits(checkbuf,ipbits); + if ( strcmp(ipaddr,checkbuf) == 0 ) + { + strcpy(myinfo->bindaddr,ipaddr); + return(clonestr("{\"result\":\"success\"}")); + } else return(clonestr("{\"error\":\"invalid bind ipaddr\"}")); + } else return(clonestr("{\"error\":\"no bind ipaddr\"}")); +} + +STRING_ARG(iguana,addnotary,ipaddr) +{ + static int32_t didinit; + if ( didinit == 0 ) + { + dpow_addresses(); + didinit = 1; + } + printf("addnotary (%s) -> (%s)\n",ipaddr,myinfo->ipaddr); + dpow_nanomsginit(myinfo,ipaddr); + return(clonestr("{\"result\":\"notary node added\"}")); +} + +char NOTARY_CURRENCIES[][65] = { + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL", "PIRATE", "MGNX", "PGT", "KMDICE", "DION", "ZEX" +}; + +// "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", + +void _iguana_notarystats(char *fname,int32_t totals[64],int32_t dispflag) +{ + FILE *fp; uint64_t signedmask; long fpos,startfpos; int32_t i,height,iter,prevheight; + if ( (fp= fopen(fname,"rb")) != 0 ) + { + printf("opened %s\n",fname); + startfpos = 0; + prevheight = -1; + for (iter=0; iter<2; iter++) + { + while ( 1 ) + { + fpos = ftell(fp); + if (fread(&height,1,sizeof(height),fp) == sizeof(height) && fread(&signedmask,1,sizeof(signedmask),fp) == sizeof(signedmask) ) + { + //printf("%6d %016llx\n",height,(long long)signedmask); + if ( height < prevheight ) + { + startfpos = fpos; + if ( iter == 0 ) + printf("found reversed height %d vs %d\n",height,prevheight); + else printf("fpos.%ld fatal unexpected height reversal %d vs %d\n",fpos,height,prevheight); + } + if ( iter == 1 && (height >= 180000 || strcmp(fname,"signedmasks") != 0) ) + { + for (i=0; i<64; i++) + { + if ( ((1LL << i) & signedmask) != 0 ) + { + totals[i]++; + if ( dispflag > 1 ) + printf("%2d ",i); + } + } + if ( dispflag > 1 ) + printf("height.%d %016llx %s\n",height,(long long)signedmask,fname); + } + prevheight = height; + } else break; + } + if ( iter == 0 ) + { + prevheight = -1; + fseek(fp,startfpos,SEEK_SET); + printf("set startfpos %ld\n",startfpos); + } + } + fclose(fp); + if ( dispflag != 0 ) + { + printf("after %s\n",fname); + for (i=0; i= DPOW_MIN_ASSETCHAIN_SIGS ) + { + notarymask = numnotaries = 0; + for (i=0; i>= 1; + decode_hex(script,len,hexstr); + if ( script[0] == 33 && script[34] == 0xac ) + { + for (j=0; j 0 ) + { + if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) + { + hasnotarization = 1; + *nothtp = 0; + if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) + { + bits256 blockhash,txid,MoM; uint32_t MoMdepth; char symbol[65];//,str[65],str2[65],str3[65]; + vout = jitem(vouts,numvouts-1); + if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 36*2 && len < sizeof(script)*2 ) + { + len >>= 1; + decode_hex(script,len,hexstr); + if ( dpow_opreturn_parsesrc(&blockhash,nothtp,&txid,symbol,&MoM,&MoMdepth,script,len,mdata) > 0 && strcmp(symbol,coin->symbol) == 0 ) + { + // if ( Notaries_port != DPOW_SOCKPORT ) // keep going till valid MoM found, useful for new chains without any MoM + { + if ( bits256_nonz(MoM) == 0 || MoMdepth == 0 || *nothtp >= height || *nothtp < 0 ) + { + *nothtp = 0; + } + } + if ( mdata->pairs != 0 && mdata->numpairs > 0 ) + { + for (j=0; jnumpairs; j++) + { + if ( mdata->pairs[j].notarization_height > coin->MoMoMheight ) + { + coin->MoMoMheight = mdata->pairs[j].notarization_height; + printf("set %s MoMoMheight <- %d\n",coin->symbol,coin->MoMoMheight); + } + } + } + //printf("%s.%d notarizationht.%d %s -> %s MoM.%s [%d]\n",symbol,height,*nothtp,bits256_str(str,blockhash),bits256_str(str2,txid),bits256_str(str3,MoM),MoMdepth); + } + } + } + } + } + } + } + free_json(txobj); + } + if ( hasnotarization != 0 ) + (*signedmaskp) = notarymask; + return(hasnotarization); +} + +int32_t dpow_hasnotarization(uint64_t *signedmaskp,int32_t *nothtp,struct supernet_info *myinfo,struct iguana_info *coin,cJSON *blockjson,int32_t ht,struct komodo_ccdataMoMoM *mdata) +{ + int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; + *nothtp = 0; + *signedmaskp = 0; + memset(mdata,0,sizeof(*mdata)); + if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) + { + for (i=0; i maxheight ) + break; + blockhash = dpow_getblockhash(myinfo,coin,ht); + if ( (blockjson= dpow_getblock(myinfo,coin,blockhash)) != 0 ) + { + if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,ht,&mdata) > 0 ) + { + if ( mdata.pairs != 0 ) + free(mdata.pairs); + for (j=0; j<64; j++) + if ( ((1LL << j) & signedmask) != 0 ) + masksums[j]++; + } + free_json(blockjson); + } + } + array = cJSON_CreateArray(); + for (i=0; i current - numblocks ) + { + printf("ht.%d %llx vs current.%d - %d\n",height,(long long)signedmask,current,numblocks); + for (j=0; j<64; j++) + if ( ((1LL << j) & signedmask) != 0 ) + vals[j] += (double)DPOW_UTXOSIZE / SATOSHIDEN; + } + } else break; + } + fclose(fp); + } else return(clonestr("{\"error\":\"cant open signedmasks\"}")); + for (sum=j=0; j 0. ) + { + bitcoin_address(coinaddr,0,pubkeys[j],33); // fixed + sprintf(cmd,"bitcoin-cli sendtoaddress %s %f\n",coinaddr,val); + if ( sendflag != 0 && system(cmd) != 0 ) + printf("ERROR with (%s)\n",cmd); + else + { + printf("%s\n",cmd); + sum += val; + } + } + } + printf("%s sent %.8f BTC\n",sendflag!=0?"":"would have",sum); + return(clonestr("{\"result\":\"success\"}")); + } + else return(clonestr("{\"error\":\"cant find BTC\"}")); + } + for (i=0; inumnotaries; i++) + { + item = cJSON_CreateObject(); + jaddstr(item,"notary",Notaries_elected[i][0]); + jaddnum(item,"bestk",bp->notaries[i].bestk); + sprintf(hexstr,"%16llx",(long long)bp->notaries[i].recvmask); + jaddstr(item,"recvmask",hexstr); + sprintf(hexstr,"%16llx",(long long)bp->notaries[i].bestmask); + jaddstr(item,"bestmask",hexstr); + jaddi(retjson,item); + } + return(retjson); +} + +STRING_ARG(dpow,active,maskhex) +{ + uint8_t data[8],revdata[8],pubkeys[64][33]; int32_t i,len,current,n; uint64_t mask; cJSON *infojson,*retjson,*array,*notarray; + array = cJSON_CreateArray(); + notarray = cJSON_CreateArray(); + if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 ) + { + current = jint(infojson,"blocks"); + free_json(infojson); + } else return(clonestr("{\"error\":\"cant get current height\"}")); + n = komodo_notaries("KMD",pubkeys,current); + if ( maskhex == 0 || maskhex[0] == 0 ) + { + return(jprint(dpow_recvmasks(myinfo,myinfo->DPOWS[0],myinfo->DPOWS[0]->currentbp),1)); + + /*mask = myinfo->DPOWS[0]->lastrecvmask; + for (i=0; i>= 1; + memset(data,0,sizeof(data)); + decode_hex(data,len,maskhex); + for (i=0; iDPOWS[0]->cancelratify = 1; + return(clonestr("{\"result\":\"queued dpow cancel ratify\"}")); +} + +ZERO_ARGS(dpow,ipaddrs) +{ + char ipaddr[64]; cJSON *array; int32_t i; + array = cJSON_CreateArray(); + for (i=0; inumdpowipbits; i++) + { + expand_ipbits(ipaddr,myinfo->dpowipbits[i]); + jaddistr(array,ipaddr); + } + return(jprint(array,1)); +} + +TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified) +{ + void **ptrs; bits256 zero; int32_t i; char *source; struct dpow_checkpoint checkpoint; + if ( ratified == 0 ) + return(clonestr("{\"error\":\"no ratified list for dpow ratify\"}")); + memset(zero.bytes,0,sizeof(zero)); + dpow_checkpointset(myinfo,&checkpoint,0,zero,timestamp,timestamp); + ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); + ptrs[0] = (void *)myinfo; + if ( (source= jstr(json,"source")) == 0 ) + source = "KMD"; + ptrs[1] = (void *)myinfo->DPOWS[0]; + for (i=0; inumdpows; i++) + if ( strcmp(myinfo->DPOWS[0]->symbol,source) == 0 ) + { + ptrs[1] = (void *)myinfo->DPOWS[i]; + break; + } + ptrs[2] = (void *)(long)minsigs; + ptrs[3] = (void *)DPOW_RATIFYDURATION; + ptrs[4] = (void *)jprint(ratified,0); + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + myinfo->DPOWS[0]->cancelratify = 0; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + return(clonestr("{\"result\":\"started ratification\"}")); +} + +HASH_AND_STRING(dex,gettransaction,txid,symbol) +{ + /*char str[65],url[1024],*retstr; + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); + + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); + }*/ + return(_dex_getrawtransaction(myinfo,symbol,txid)); +} + +HASH_AND_STRING_AND_INT(dex,gettxout,txid,symbol,vout) +{ + /*char str[65],url[1024],*retstr; + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); + }*/ + return(_dex_gettxout(myinfo,symbol,txid,vout)); +} + +TWO_STRINGS(dex,listunspent,symbol,address) +{ + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + char url[1024],*retstr,*coinaddr,*script; int32_t i,n,vout; cJSON *retjson,*data,*item,*item3,*data3; bits256 txid; uint64_t val; + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + data = jarray(&n,retjson,"data"); + data3 = cJSON_CreateArray(); + //[{"hash":"e0a40dac21103e92e0dc9311a0233640489afc5beb5ba3b009848a8e9151dc55","time":"2017-02-21T16:48:28+0000","confirmations":1,"is_coinbase":false,"value":4100000,"index":1,"address":"19rjYdJtRN3qoammX3r1gxy9bvh8p8DmRc","type":"pubkeyhash","multisig":null,"script":"OP_DUP OP_HASH160 6128e7459989d35d530bcd4066c9aaf1f925430a OP_EQUALVERIFY OP_CHECKSIG","script_hex":"76a9146128e7459989d35d530bcd4066c9aaf1f925430a88ac"}] + /*{ + "txid" : "e95d3083baf733dfda2fcd1110fe2937cb3580f8b1b237aad547528440dfa873", + "vout" : 1, + "address" : "RNgdefRo2iRLWqDXEogJrsTw35MgDPQP4R", + "account" : "", + "scriptPubKey" : "76a91493088c5f3546225e0ef6ba9c9c6a74d4c2df877388ac", + "amount" : 150.00000000, + "interest" : 0.30000000, + "confirmations" : 20599, + "spendable" : true + }*/ + for (i=0; iFULLNODE < 0 ) + return(jprint(dpow_listunspent(myinfo,coin,address),1)); + //printf("call _dex_listunspent\n"); + return(_dex_listunspent(myinfo,symbol,address)); +} + +TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions,symbol,address,count,skip) +{ + if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + char url[1024],*retstr,*retstr2; cJSON *retjson,*retjson2,*retjson3,*data,*data2; int32_t i,n; + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/transactions?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unconfirmed-transactions?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr2= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 && (retjson2= cJSON_Parse(retstr2)) != 0 ) + { + data = jarray(&n,retjson,"data"); + data2 = jarray(&n,retjson2,"data"); + retjson3 = jduplicate(data); + if ( n > 0 ) + { + for (i=0; i (%s)\n",retstr,retstr2,jprint(retjson3,0)); + free(retstr); + free(retstr2); + free_json(retjson); + free_json(retjson2); + return(jprint(retjson3,1)); + } + } + } + } + return(_dex_listtransactions(myinfo,symbol,address,count,skip)); +} + +STRING_ARG(dex,getinfo,symbol) +{ + return(_dex_getinfo(myinfo,symbol)); +} + +STRING_ARG(dex,getbestblockhash,symbol) +{ + return(_dex_getbestblockhash(myinfo,symbol)); +} + +STRING_ARG(dex,alladdresses,symbol) +{ + return(_dex_alladdresses(myinfo,symbol)); +} + +STRING_AND_INT(dex,getblockhash,symbol,height) +{ + return(_dex_getblockhash(myinfo,symbol,height)); +} + +HASH_AND_STRING(dex,getblock,hash,symbol) +{ + return(_dex_getblock(myinfo,symbol,hash)); +} + +TWO_STRINGS(dex,sendrawtransaction,symbol,signedtx) +{ + return(_dex_sendrawtransaction(myinfo,symbol,signedtx)); +} + +TWO_STRINGS(dex,importaddress,symbol,address) +{ + return(_dex_importaddress(myinfo,symbol,address)); +} + +TWO_STRINGS(dex,checkaddress,symbol,address) +{ + return(_dex_checkaddress(myinfo,symbol,address)); +} + +TWO_STRINGS(dex,validateaddress,symbol,address) +{ + return(_dex_validateaddress(myinfo,symbol,address)); +} + +STRING_ARG(dex,getmessage,argstr) +{ + return(_dex_getmessage(myinfo,argstr)); +} + +STRING_ARG(dex,psock,argstr) +{ + return(_dex_psock(myinfo,argstr)); +} + +STRING_ARG(dex,getnotaries,symbol) +{ + return(clonestr("{\"error\":\"dexgetnotaries deprecated\"}")); + //return(_dex_getnotaries(myinfo,symbol)); +} + +TWO_STRINGS(dex,kvsearch,symbol,key) +{ + if ( key == 0 || key[0] == 0 ) + return(clonestr("{\"error\":\"kvsearch parameter error\"}")); + return(_dex_kvsearch(myinfo,symbol,key)); +} + +THREE_STRINGS_AND_THREE_INTS(dex,kvupdate,symbol,key,value,flags,unused,unusedb) +{ + // need to have some micropayments between client/server, otherwise receiving server incurs costs + if ( key == 0 || key[0] == 0 || value == 0 || value[0] == 0 ) + return(clonestr("{\"error\":\"kvupdate parameter error\"}")); + if ( strcmp(symbol,"KV") == 0 ) + { + if ( flags > 1 ) + return(clonestr("{\"error\":\"only single duration updates via remote access\"}")); + else if ( strlen(key) > 64 || strlen(value) > 256 ) + return(clonestr("{\"error\":\"only keylen <=64 and valuesize <= 256 allowed via remote access\"}")); + else + { + //printf("call _dex_kvupdate.(%s) -> (%s) flags.%d\n",key,value,flags); + return(_dex_kvupdate(myinfo,symbol,key,value,flags)); + } + } else return(clonestr("{\"error\":\"free updates only on KV chain\"}")); +} + +#include "kmd_lookup.h" + +TWO_STRINGS(dex,listunspent2,symbol,address) +{ + cJSON *retjson; + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) + return(clonestr("[]")); + if ( (retjson= kmd_listunspent(myinfo,coin,address)) != 0 ) + return(jprint(retjson,1)); + } + } + if ( symbol != 0 && address != 0 ) + return(_dex_listunspent2(myinfo,symbol,address)); + else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); +} + +TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions2,symbol,address,count,skip) +{ + cJSON *retjson; + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) + return(clonestr("[]")); + if ( (retjson= kmd_listtransactions(myinfo,coin,address,count,skip)) != 0 ) + return(jprint(retjson,1)); + } + } + if ( symbol != 0 && address != 0 ) + return(_dex_listtransactions2(myinfo,symbol,address,count,skip)); + else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); +} + +HASH_AND_STRING_AND_INT(dex,gettxin,txid,symbol,vout) +{ + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_gettxin(coin,txid,vout),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 ) + return(_dex_gettxin(myinfo,symbol,txid,vout)); + else return(clonestr("{\"error\":\"dex gettxin null symbolor coin\"}")); +} + +TWO_STRINGS(dex,listspent,symbol,address) +{ + if ( myinfo->DEXEXPLORER != 0 ) + { + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_listspent(myinfo,coin,address),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 && address != 0 ) + return(_dex_listspent(myinfo,symbol,address)); + else return(clonestr("{\"error\":\"dex listspent null symbol, address or coin\"}")); +} + +TWO_STRINGS(dex,getbalance,symbol,address) +{ + char url[512],*retstr; cJSON *retjson; uint64_t val; + if ( myinfo->DEXEXPLORER != 0 ) + { + //printf("DEXEXPLORER\n"); + if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) + return(jprint(kmd_getbalance(myinfo,coin,address),1)); + if ( coin != 0 ) + coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); + } + if ( symbol != 0 && address != 0 ) + { + if ( strcmp(symbol,"BTC") == 0 && myinfo->blocktrail_apikey[0] != 0 ) + { + sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s?api_key=%s",address,myinfo->blocktrail_apikey); + if ( (retstr= issue_curl(url)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + //printf("balance\n"); + if ( (val= j64bits(retjson,"balance")) != 0 ) + { + jdelete(retjson,"balance"); + jaddnum(retjson,"balance",dstr(val)); + } + //printf("sent\n"); + if ( (val= j64bits(retjson,"sent")) != 0 ) + { + jdelete(retjson,"sent"); + jaddnum(retjson,"sent",dstr(val)); + } + //printf("received\n"); + if ( (val= j64bits(retjson,"received")) != 0 ) + { + jdelete(retjson,"received"); + jaddnum(retjson,"received",dstr(val)); + } + //printf("unconfirmed_sent\n"); + if ( (val= j64bits(retjson,"unconfirmed_sent")) != 0 ) + { + jdelete(retjson,"unconfirmed_sent"); + jaddnum(retjson,"unconfirmed_sent",dstr(val)); + } + //printf("unconfirmed_received\n"); + if ( (val= j64bits(retjson,"unconfirmed_received")) != 0 ) + { + jdelete(retjson,"unconfirmed_received"); + jaddnum(retjson,"unconfirmed_received",dstr(val)); + } + //printf("blocktrail.(%s) -> (%s)\n",retstr,jprint(retjson,0)); + free(retstr); + retstr = jprint(retjson,1); + } + } + return(retstr); + } + return(_dex_getbalance(myinfo,symbol,address)); + } else return(clonestr("{\"error\":\"dex getbalance null symbol, address or coin\"}")); +} + +STRING_ARG(dex,explorer,symbol) +{ + if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 ) + { + myinfo->DEXEXPLORER = 1; + coin->DEXEXPLORER = 1; + return(clonestr("{\"result\":\"success\"}")); + } + return(clonestr("{\"error\":\"coin not active\"}")); +} + +#include "../includes/iguana_apiundefs.h" From 24e546d86f263706406a9ad64cb3d382e5c68382 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 15 Dec 2018 03:39:37 -1100 Subject: [PATCH 06/14] Set KMD to sapling --- basilisk/basilisk_bitcoin.c | 1 - iguana/iguana777.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index cda0bf52c..2b90568ca 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -594,7 +594,6 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi uint32_t txversion = 1; // txversion = 1 for non-overwintered and non-sapling coins if (coin->sapling != 0) txversion = 4; - if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,txversion,0)) != 0 ) { if ( duplicates <= 0 ) diff --git a/iguana/iguana777.c b/iguana/iguana777.c index 167d8543b..b21ab4058 100755 --- a/iguana/iguana777.c +++ b/iguana/iguana777.c @@ -1136,7 +1136,7 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers, if ( jobj(json,"cache") != 0 ) coin->enableCACHE = juint(json,"cache"); - coin->sapling = 0; + coin->sapling = (strcmp("KMD",coin->symbol) == 0); if (jobj(json, "sapling") != 0) { coin->sapling = juint(json, "sapling"); From b85286f487ec61ad6bf705c71f851dd6bffb929c Mon Sep 17 00:00:00 2001 From: jl777 Date: Fri, 21 Dec 2018 05:06:48 -1100 Subject: [PATCH 07/14] Update nav --- iguana/exchanges/prices/autoprice | 4 ++-- iguana/exchanges/supernet | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/iguana/exchanges/prices/autoprice b/iguana/exchanges/prices/autoprice index 4d7fa7733..9511e7bad 100755 --- a/iguana/exchanges/prices/autoprice +++ b/iguana/exchanges/prices/autoprice @@ -35,11 +35,11 @@ source trackbtc #source revs #source trackbtc -sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}" +sharkholdings="{\"coin\":\"iota\",\"balance\":0}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}" curl --url "http://127.0.0.1:7783" --data "{\"base\":\"MSHARK\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"margin\":$margin,\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[$sharkholdings],\"divisor\":1400000}" -curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":600000}, {\"coin\":\"bitcoin\",\"balance\":486}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}" +curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":10000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":400000}, {\"coin\":\"bitcoin\",\"balance\":486}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}, {\"coin\":\"verus\",\"balance\":2650000}],\"divisor\":777777}" curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"HODL\",\"rel\":\"KMD\",\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}" diff --git a/iguana/exchanges/supernet b/iguana/exchanges/supernet index 20595997b..7209cce88 100755 --- a/iguana/exchanges/supernet +++ b/iguana/exchanges/supernet @@ -15,5 +15,5 @@ echo supernet curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\"}" echo supernet -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":600000}, {\"coin\":\"bitcoin\",\"balance\":486}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2350000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":10000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":400000}, {\"coin\":\"bitcoin\",\"balance\":486}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2350000}, {\"coin\":\"verus\",\"balance\":1650000}],\"divisor\":777777}" From 390ac34308e1ff42675785a046da800219ee8b46 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Fri, 8 Feb 2019 09:57:18 -0800 Subject: [PATCH 08/14] Add GIN coin --- iguana/coins/gin_7776 | 1 + 1 file changed, 1 insertion(+) create mode 100644 iguana/coins/gin_7776 diff --git a/iguana/coins/gin_7776 b/iguana/coins/gin_7776 new file mode 100644 index 000000000..f11b7c38b --- /dev/null +++ b/iguana/coins/gin_7776 @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7776/" --data "{"conf":"gincoin.conf","path":"${HOME#"/"}/.gincoincore","prefetchlag":-1,"poll":1,"active":1,"agent":"iguana","method":"addcoin","newcoin":"GIN","startpend":64,"endpend":64,"services":0,"maxpeers":512,"RELAY":-1,"VALIDATE":0,"portp2p":10111,"minconfirms":1}" From 86cba09ca5f3e2f016f4a0140974b47df73e123f Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Fri, 8 Feb 2019 13:06:16 -0800 Subject: [PATCH 09/14] set exec bit on gin --- iguana/coins/gin_7776 | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 iguana/coins/gin_7776 diff --git a/iguana/coins/gin_7776 b/iguana/coins/gin_7776 old mode 100644 new mode 100755 From a14276e7bd2c850af6e043e17d04f136f80f17ed Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sat, 9 Feb 2019 03:22:47 +0300 Subject: [PATCH 10/14] + GIN --- iguana/coins/gin_7776 | 3 +++ iguana/dpowassets | 1 + iguana/m_notary_run | 1 + 3 files changed, 5 insertions(+) create mode 100755 iguana/coins/gin_7776 diff --git a/iguana/coins/gin_7776 b/iguana/coins/gin_7776 new file mode 100755 index 000000000..c9725237a --- /dev/null +++ b/iguana/coins/gin_7776 @@ -0,0 +1,3 @@ +#!/bin/bash +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"gincoin.conf\",\"path\":\"${HOME#"/"}/.gincoincore\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"GIN\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":10111,\"minconfirms\":1,\"name\":\"gincoin\",\"netmagic\":\"bf0c6bbd\",\"p2p\":10111,\"rpc\":10211,\"pubval\":38,\"p2shval\":10,\"wifval\":198}" + diff --git a/iguana/dpowassets b/iguana/dpowassets index 5162ee878..82668b11e 100755 --- a/iguana/dpowassets +++ b/iguana/dpowassets @@ -50,4 +50,5 @@ curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dp curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"ZEX\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"KSB\",\"pubkey\":\"$pubkey\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"OUR\",\"pubkey\":\"$pubkey\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"GIN\",\"pubkey\":\"$pubkey\"}" diff --git a/iguana/m_notary_run b/iguana/m_notary_run index edf749b38..6b207073d 100755 --- a/iguana/m_notary_run +++ b/iguana/m_notary_run @@ -106,6 +106,7 @@ coins/dion_7776 coins/zex_7776 coins/ksb_7776 coins/our_7776 +coins/gin_7776 #curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}" From cd351b0a93bc5c140719cee012edcfc14f394c62 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 9 Feb 2019 04:09:40 -1100 Subject: [PATCH 11/14] Small opreturn forGIN --- iguana/dpow/dpow_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iguana/dpow/dpow_rpc.c b/iguana/dpow/dpow_rpc.c index 5858ecfdc..8b51ac2d2 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -24,7 +24,7 @@ uint64_t dpow_utxosize(char *symbol) int32_t dpow_smallopreturn(char *symbol) { - if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) + if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"GIN") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) return(1); else return(0); } From 3768397cdfa298ab358554ecf0c4590f23f4588c Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 9 Feb 2019 04:12:55 -1100 Subject: [PATCH 12/14] Revert "Merge branch 'beta' into dev" This reverts commit e4c68c09038f943c8cc1b64c3f1ffdb6c771ec58, reversing changes made to 4f58ac2a5819683ae5b1e157562323bb9838f059. --- iguana/iguana_notary.old | 1348 -------------------------------------- 1 file changed, 1348 deletions(-) delete mode 100755 iguana/iguana_notary.old diff --git a/iguana/iguana_notary.old b/iguana/iguana_notary.old deleted file mode 100755 index ff1a7c878..000000000 --- a/iguana/iguana_notary.old +++ /dev/null @@ -1,1348 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2018 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - - -// Todo list: -// q) investigate if rebroadcast reorged local chain notary tx and scanning mempool is needed - -#define CHECKSIG 0xac - -#include "iguana777.h" -//#include "notaries.h" - -int32_t dpow_datahandler(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint8_t nn_senderind,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen); -uint64_t dpow_maskmin(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); -int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr,char *srccoin); - -#include "dpow/dpow_network.c" -#include "dpow/dpow_rpc.c" -#include "dpow/dpow_tx.c" -#include "dpow/dpow_fsm.c" -#include "dpow/dpow_prices.c" - -void dpow_fifoupdate(struct supernet_info *myinfo,struct dpow_checkpoint *fifo,struct dpow_checkpoint tip) -{ - int32_t i,ind; struct dpow_checkpoint newfifo[DPOW_FIFOSIZE]; - memset(newfifo,0,sizeof(newfifo)); - for (i=DPOW_FIFOSIZE-1; i>0; i--) - { - if ( (0) && bits256_nonz(fifo[i-1].blockhash.hash) != 0 && (tip.blockhash.height - fifo[i-1].blockhash.height) != i ) - printf("(%d != %d) ",(tip.blockhash.height - fifo[i-1].blockhash.height),i); - if ( (ind= (tip.blockhash.height - fifo[i-1].blockhash.height)) >= 0 && ind < DPOW_FIFOSIZE ) - newfifo[ind] = fifo[i-1]; - } - newfifo[0] = tip; - memcpy(fifo,newfifo,sizeof(newfifo)); - //for (i=0; itimestamp = timestamp; - checkpoint->blocktime = blocktime; - checkpoint->blockhash.hash = hash; - checkpoint->blockhash.height = height; -} - -void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) -{ - //struct komodo_ccdataMoMoM mdata; cJSON *blockjson; uint64_t signedmask; struct iguana_info *coin; - void **ptrs; char str[65]; struct dpow_checkpoint checkpoint; int32_t i,ht,suppress=0; struct dpow_block *bp; - dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); - checkpoint = dp->srcfifo[dp->srcconfirms]; - dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); - if ( strcmp(dp->dest,"KMD") == 0 ) - { - if ( dp->DESTHEIGHT < dp->prevDESTHEIGHT+DPOW_CHECKPOINTFREQ ) - { - suppress = 1; - //fprintf(stderr,"suppress %s -> KMD\n",dp->symbol); - } - } - /*if ( strcmp(dp->dest,"KMD") == 0 )//|| strcmp(dp->dest,"CHAIN") == 0 ) - { - //if ( dp->SRCREALTIME == 0 ) - // return; - if ( (coin= iguana_coinfind(dp->symbol)) != 0 ) - { - hash = dpow_getbestblockhash(myinfo,coin); - if ( bits256_nonz(hash) != 0 ) - { - if ( (blockjson= dpow_getblock(myinfo,coin,hash)) != 0 ) - { - height = jint(blockjson,"height"); - if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,height,&mdata) <= 0 ) - { - if ( mdata.pairs != 0 ) - free(mdata.pairs); - blocktime = juint(blockjson,"time"); - free_json(blockjson); - if ( height > 0 && blocktime > 0 ) - { - dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("dynamic set %s/%s %s <- height.%d\n",dp->symbol,dp->dest,bits256_str(str,hash),height); - checkpoint = dp->last; - } else return; - if ( bits256_nonz(dp->activehash) != 0 && bits256_cmp(dp->activehash,checkpoint.blockhash.hash) == 0 ) - { - printf("activehash.(%s) is current checkpoint, skip\n",bits256_str(str,dp->activehash)); - return; - } - else if ( bits256_nonz(dp->lastnotarized) != 0 && bits256_cmp(dp->lastnotarized,checkpoint.blockhash.hash) == 0 ) - { - printf("lastnotarized.(%s) is current checkpoint, skip\n",bits256_str(str,dp->lastnotarized)); - return; - } - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("checkpoint.(%s) is not active and not lastnotarized\n",bits256_str(str,checkpoint.blockhash.hash)); - } else return; - } else return; - } else return; - } else return; - }*/ - if ( dp->freq <= 0 ) - dp->freq = 1; - if ( suppress == 0 && bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % dp->freq) == 0 ) - { - if ( (0) && strcmp("KMD",dp->symbol) == 0 ) - printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d freq.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),dp->minsigs,dp->freq); - dpow_heightfind(myinfo,dp,checkpoint.blockhash.height + 1000); - dp->prevDESTHEIGHT = dp->DESTHEIGHT; - ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint) + sizeof(pthread_t)); - ptrs[0] = (void *)myinfo; - ptrs[1] = (void *)dp; - ptrs[2] = (void *)(uint64_t)dp->minsigs; - //if ( strcmp(dp->dest,"KMD") != 0 ) - ptrs[3] = (void *)DPOW_DURATION; - //else ptrs[3] = (void *)(DPOW_DURATION * 60); // essentially try forever for assetchains - ptrs[4] = 0; - memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); - dp->activehash = checkpoint.blockhash.hash; - ht = checkpoint.blockhash.height; - if ( OS_thread_create((void *)((uint64_t)&ptrs[5] + sizeof(struct dpow_checkpoint)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) - { - } - if ( ht > DPOW_MAXFREQ*5 ) - { - if ( (0) && strcmp("CHIPS",dp->symbol) == 0 ) - printf("ht.%d maxblocks.%d\n",ht,dp->maxblocks); - for (i=ht-DPOW_MAXFREQ*5; i>ht-DPOW_MAXFREQ*100&&i>DPOW_MAXFREQ; i--) - { - if ( (bp= dp->blocks[i]) != 0 && bp->state == 0xffffffff ) //(i % DPOW_MAXFREQ) != 0 && - { - if ( dp->currentbp == dp->blocks[i] ) - dp->currentbp = 0; - dp->blocks[i] = 0; - Numallocated--; - free(bp); - } - } - } - } -} - -void dpow_approvedset(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint,bits256 *txs,int32_t numtx) -{ - int32_t i,j; bits256 txid; - if ( txs != 0 ) - { - for (i=0; iapproved[j].hash) == 0 ) - { - if ( bits256_nonz(checkpoint->approved.hash) == 0 || dp->approved[j].height >= checkpoint->approved.height ) - checkpoint->approved = dp->approved[j]; - } - } - } - } - } -} - -void dpow_destconfirm(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_checkpoint *checkpoint) -{ - int32_t i; - if ( bits256_nonz(checkpoint->approved.hash) != 0 ) - { - for (i=DPOW_FIFOSIZE-1; i>0; i--) - dp->notarized[i] = dp->notarized[i-1]; - dp->notarized[0] = checkpoint->approved; - } -} - -void dpow_destupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) -{ - dp->destupdated = timestamp; - dp->DESTHEIGHT = height; - dpow_checkpointset(myinfo,&dp->destchaintip,height,hash,timestamp,blocktime); - dpow_approvedset(myinfo,dp,&dp->destchaintip,dp->desttx,dp->numdesttx); - dpow_fifoupdate(myinfo,dp->destfifo,dp->destchaintip); - if ( strcmp(dp->dest,"BTC") == 0 ) - { - //printf("%s destupdate ht.%d\n",dp->dest,height); - dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_BTCCONFIRMS]); - } - else dpow_destconfirm(myinfo,dp,&dp->destfifo[DPOW_KOMODOCONFIRMS*2]); // todo: change to notarized KMD depth -} - -void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) -{ - int32_t height,num; uint32_t blocktime; bits256 blockhash,merkleroot; struct iguana_info *src,*dest; - //if ( strcmp(dp->symbol,"KMD") == 0 ) - { - num = dpow_nanomsg_update(myinfo); - //fprintf(stderr,"nano.%d ",num); - } - src = iguana_coinfind(dp->symbol); - dest = iguana_coinfind(dp->dest); - if ( src != 0 && dest != 0 ) - { - //fprintf(stderr,"dp.%p dPoWupdate (%s -> %s)\n",dp,dp!=0?dp->symbol:"",dp!=0?dp->dest:""); - dp->numdesttx = sizeof(dp->desttx)/sizeof(*dp->desttx); - if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) - { - char str[65]; - if ( (0) && strcmp(dp->symbol,"KMD") == 0 )//|| height != dp->destchaintip.blockhash.height+1 ) - printf("[%s].%d %s %s height.%d vs last.%d\n",dp->symbol,dp->SRCHEIGHT,dp->dest,bits256_str(str,blockhash),height,dp->destchaintip.blockhash.height); - if ( height <= dp->destchaintip.blockhash.height ) - { - printf("iguana_dPoWupdate dest.%s reorg detected %d vs %d\n",dp->dest,height,dp->destchaintip.blockhash.height); - if ( height == dp->destchaintip.blockhash.height && bits256_cmp(blockhash,dp->destchaintip.blockhash.hash) != 0 ) - printf("UNEXPECTED ILLEGAL BLOCK in dest chaintip\n"); - } else dpow_destupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); - } // else printf("error getchaintip for %s\n",dp->dest); - dp->numsrctx = sizeof(dp->srctx)/sizeof(*dp->srctx); - /*if ( (strcmp(dp->dest,"KMD") == 0 || strcmp(dp->dest,"CHAIN") == 0) && dp->SRCHEIGHT < src->longestchain ) - { - //fprintf(stderr,"[I "); - dp->SRCHEIGHT = dpow_issuer_iteration(dp,src,dp->SRCHEIGHT,&dp->SRCREALTIME); - //fprintf(stderr," %d] ",dp->SRCHEIGHT); - }*/ - if ( (height= dpow_getchaintip(myinfo,&merkleroot,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height > 0 ) - { - if ( dp->lastheight == 0 ) - dp->lastheight = height-1; - char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->lastheight); - dp->SRCHEIGHT = height; - if ( height < dp->last.blockhash.height ) - { - printf("iguana_dPoWupdate src.%s reorg detected %d vs %d approved.%d notarized.%d\n",dp->symbol,height,dp->last.blockhash.height,dp->approved[0].height,dp->notarized[0].height); - if ( height <= dp->approved[0].height ) - { - if ( bits256_cmp(blockhash,dp->last.blockhash.hash) != 0 ) - printf("UNEXPECTED ILLEGAL BLOCK in src chaintip\n"); - } - else - { - while ( dp->lastheight <= height ) - { - printf("dp->lastheight.%d <= height.%d\n",dp->lastheight,height); - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); - } - } - } - else //if ( strcmp(dp->symbol,"KMD") == 0 ) - { - while ( dp->lastheight <= height ) - { - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); - } - } - /*else if ( time(NULL) > dp->lastsrcupdate+60 || height != dp->lastheight ) - { - dp->lastsrcupdate = (uint32_t)time(NULL); - dp->lastheight = height; - blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); - dpow_srcupdate(myinfo,dp,dp->lastheight,blockhash,(uint32_t)time(NULL),blocktime); - }*/ - } //else printf("error getchaintip for %s\n",dp->symbol); - } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); -} - -void dpow_addresses() -{ - int32_t i; char coinaddr[64]; uint8_t pubkey[33]; - for (i=0; iDPOWS[myinfo->numdpows]) == 0 ) - myinfo->DPOWS[myinfo->numdpows] = calloc(1,sizeof(*dp)); - if ( (dp= myinfo->DPOWS[myinfo->numdpows]) == 0 ) - return(clonestr("{\"error\":\"dPoW cant allocate memory\"}")); - memset(dp,0,sizeof(*dp)); - destvalid = srcvalid = 0; - if ( myinfo->NOTARY.RELAYID < 0 ) - { - if ( (retstr= basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(myinfo->ipaddr),myinfo->myaddr.persistent)) != 0 ) - { - printf("addrelay.(%s)\n",retstr); - free(retstr); - } - if ( myinfo->NOTARY.RELAYID < 0 ) - return(clonestr("{\"error\":\"must be running as notary node\"}")); - } - if ( dp->symbol[0] != 0 ) - return(clonestr("{\"error\":\"cant dPoW more than one coin at a time\"}")); - if ( pubkey == 0 || pubkey[0] == 0 || is_hexstr(pubkey,0) != 66 ) - return(clonestr("{\"error\":\"need 33 byte pubkey\"}")); - if ( symbol == 0 || symbol[0] == 0 ) - symbol = "KMD"; - if ( dest == 0 || dest[0] == 0 ) - { - if ( strcmp(symbol,"KMD") == 0 ) - dest = "BTC"; - else dest = "KMD"; - } - //if ( myinfo->numdpows == 1 ) - // komodo_assetcoins(-1); - if ( iguana_coinfind(symbol) == 0 ) - return(clonestr("{\"error\":\"cant dPoW an inactive coin\"}")); - if ( strcmp(symbol,"KMD") == 0 && iguana_coinfind("BTC") == 0 ) - return(clonestr("{\"error\":\"cant dPoW KMD without BTC\"}")); - else if ( iguana_coinfind(dest) == 0 ) - return(clonestr("{\"error\":\"cant dPoW without KMD (dest)\"}")); - if ( myinfo->numdpows > 0 ) - { - for (i=0; inumdpows; i++) - if ( strcmp(symbol,myinfo->DPOWS[i]->symbol) == 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"cant dPoW same coin again\"}")); - } - } - strcpy(dp->symbol,symbol); - if ( strcmp(dp->symbol,"KMD") == 0 ) - { - strcpy(dp->dest,"BTC"); - dp->srcconfirms = DPOW_KOMODOCONFIRMS; - } - else - { - strcpy(dp->dest,dest); - dp->srcconfirms = DPOW_THIRDPARTY_CONFIRMS; - } - if ( dp->srcconfirms > DPOW_FIFOSIZE ) - dp->srcconfirms = DPOW_FIFOSIZE; - if ( strcmp("BTC",dp->dest) == 0 ) - { - if ( freq == 0 ) - dp->freq = DPOW_CHECKPOINTFREQ; - else dp->freq = freq; - dp->minsigs = Notaries_BTCminsigs; //DPOW_MINSIGS; - } - else - { - dp->minsigs = Notaries_minsigs; //DPOW_MIN_ASSETCHAIN_SIGS; - if ( freq == 0 && (strcmp("CHIPS",dp->symbol) == 0 || strncmp("TEST",dp->symbol,4) == 0) ) - dp->freq = DPOW_MAXFREQ; - else if ( freq > 2 ) - dp->freq = freq; - else dp->freq = 2; - } - src = iguana_coinfind(dp->symbol); - destcoin = iguana_coinfind(dp->dest); - if ( src == 0 || destcoin == 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"source coin or dest coin not there\"}")); - } - char tmp[67]; - safecopy(tmp,pubkey,sizeof(tmp)); - decode_hex(dp->minerkey33,33,tmp); - - if (strcmp(src->chain->symbol, "HUSH") == 0) - bitcoin_address_ex(src->chain->symbol, srcaddr, 0x1c, src->chain->pubtype, dp->minerkey33, 33); - else - bitcoin_address(srcaddr, src->chain->pubtype, dp->minerkey33, 33); - - if ( (retstr= dpow_validateaddress(myinfo,src,srcaddr)) != 0 ) - { - json = cJSON_Parse(retstr); - if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) - srcvalid = 1; - else - { - srcvalid = 0; - printf("src validation error %s %s %s\n",src->symbol,srcaddr,retstr); - } - free(retstr); - retstr = 0; - } else printf("%s %s didnt return anything\n",src->symbol,srcaddr); - bitcoin_address(destaddr,destcoin->chain->pubtype,dp->minerkey33,33); - if ( (retstr= dpow_validateaddress(myinfo,destcoin,destaddr)) != 0 ) - { - json = cJSON_Parse(retstr); - if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 ) - destvalid = 1; - else - { - destvalid = 0; - printf("dest validation error %s %s %s\n",src->symbol,srcaddr,retstr); - } - free(retstr); - retstr = 0; - } else printf("%s %s didnt return anything\n",destcoin->symbol,destaddr); - if ( srcvalid <= 0 || destvalid <= 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"source address or dest address has no privkey, importprivkey\"}")); - } - if ( bitcoin_pubkeylen(dp->minerkey33) <= 0 ) - { - dp->symbol[0] = 0; - return(clonestr("{\"error\":\"illegal pubkey\"}")); - } - if ( dp->blocks == 0 ) - { - dp->maxblocks = 10000; - dp->blocks = calloc(dp->maxblocks,sizeof(*dp->blocks)); - } - portable_mutex_init(&dp->paxmutex); - portable_mutex_init(&dp->dexmutex); - PAX_init(); - dp->fullCCid = dpow_CCid(myinfo,src); - myinfo->numdpows++; - for (i=0; i<33; i++) - printf("%02x",dp->minerkey33[i]); - printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d CCid.%u\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs,dp->fullCCid); - return(clonestr("{\"result\":\"success\"}")); -} - -char *dpow_passthru(struct iguana_info *coin,char *function,char *hex) -{ - char params[32768]; int32_t len = 0; - if ( hex != 0 && hex[0] != 0 ) - { - len = (int32_t)strlen(hex) >> 1; - if ( len < sizeof(params)-1 ) - decode_hex((uint8_t *)params,(int32_t)strlen(hex),hex); - else len = 0; - } - params[len] = 0; - return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,function,params)); -} - -TWO_STRINGS(zcash,passthru,function,hex) -{ - if ( (coin= iguana_coinfind("ZEC")) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"ZEC not active, start in bitcoind mode\"}")); -} - -TWO_STRINGS(komodo,passthru,function,hex) -{ - if ( (coin= iguana_coinfind("KMD")) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"KMD not active, start in bitcoind mode\"}")); -} - -THREE_STRINGS(iguana,passthru,asset,function,hex) -{ - if ( asset != 0 && (coin= iguana_coinfind(asset)) != 0 ) - return(dpow_passthru(coin,function,hex)); - else return(clonestr("{\"error\":\"assetchain not active, start in bitcoind mode\"}")); -} - -TWO_STRINGS(dex,send,hex,handler) -{ - uint8_t data[8192]; int32_t datalen; char *retstr; - if ( hex != 0 && (datalen= is_hexstr(hex,0)) > 0 && (datalen>>1) < sizeof(data) ) - { - datalen >>= 1; - decode_hex(data,datalen,hex); - if ( handler == 0 || handler[0] == 0 ) - handler = "DEX"; - if ( (retstr= dex_reqsend(myinfo,handler,data,datalen,1,"")) == 0 ) - return(clonestr("{\"result\":\"success\"}")); - else return(retstr); - } else return(clonestr("{\"error\":\"dex send: invalid hex\"}")); -} - -STRING_ARG(dpow,pending,fiat) -{ - struct dpow_info *dp; char base[64]; int32_t i; - if ( fiat != 0 && fiat[0] != 0 ) - { - for (i=0; fiat[i]!=0; i++) - base[i] = toupper((int32_t)fiat[i]); - base[i] = 0; - for (i=0; inumdpows; i++) - { - dp = myinfo->DPOWS[i]; - if ( strcmp(dp->symbol,base) == 0 ) - return(jprint(dpow_withdraws_pending(dp),1)); - } - } - return(clonestr("[]")); -} - -STRING_ARG(dpow,bindaddr,ipaddr) -{ - uint32_t ipbits; char checkbuf[64]; - if ( ipaddr != 0 && ipaddr[0] != 0 ) - { - ipbits = (uint32_t)calc_ipbits(ipaddr); - expand_ipbits(checkbuf,ipbits); - if ( strcmp(ipaddr,checkbuf) == 0 ) - { - strcpy(myinfo->bindaddr,ipaddr); - return(clonestr("{\"result\":\"success\"}")); - } else return(clonestr("{\"error\":\"invalid bind ipaddr\"}")); - } else return(clonestr("{\"error\":\"no bind ipaddr\"}")); -} - -STRING_ARG(iguana,addnotary,ipaddr) -{ - static int32_t didinit; - if ( didinit == 0 ) - { - dpow_addresses(); - didinit = 1; - } - printf("addnotary (%s) -> (%s)\n",ipaddr,myinfo->ipaddr); - dpow_nanomsginit(myinfo,ipaddr); - return(clonestr("{\"result\":\"notary node added\"}")); -} - -char NOTARY_CURRENCIES[][65] = { - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL", "PIRATE", "MGNX", "PGT", "KMDICE", "DION", "ZEX" -}; - -// "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - -void _iguana_notarystats(char *fname,int32_t totals[64],int32_t dispflag) -{ - FILE *fp; uint64_t signedmask; long fpos,startfpos; int32_t i,height,iter,prevheight; - if ( (fp= fopen(fname,"rb")) != 0 ) - { - printf("opened %s\n",fname); - startfpos = 0; - prevheight = -1; - for (iter=0; iter<2; iter++) - { - while ( 1 ) - { - fpos = ftell(fp); - if (fread(&height,1,sizeof(height),fp) == sizeof(height) && fread(&signedmask,1,sizeof(signedmask),fp) == sizeof(signedmask) ) - { - //printf("%6d %016llx\n",height,(long long)signedmask); - if ( height < prevheight ) - { - startfpos = fpos; - if ( iter == 0 ) - printf("found reversed height %d vs %d\n",height,prevheight); - else printf("fpos.%ld fatal unexpected height reversal %d vs %d\n",fpos,height,prevheight); - } - if ( iter == 1 && (height >= 180000 || strcmp(fname,"signedmasks") != 0) ) - { - for (i=0; i<64; i++) - { - if ( ((1LL << i) & signedmask) != 0 ) - { - totals[i]++; - if ( dispflag > 1 ) - printf("%2d ",i); - } - } - if ( dispflag > 1 ) - printf("height.%d %016llx %s\n",height,(long long)signedmask,fname); - } - prevheight = height; - } else break; - } - if ( iter == 0 ) - { - prevheight = -1; - fseek(fp,startfpos,SEEK_SET); - printf("set startfpos %ld\n",startfpos); - } - } - fclose(fp); - if ( dispflag != 0 ) - { - printf("after %s\n",fname); - for (i=0; i= DPOW_MIN_ASSETCHAIN_SIGS ) - { - notarymask = numnotaries = 0; - for (i=0; i>= 1; - decode_hex(script,len,hexstr); - if ( script[0] == 33 && script[34] == 0xac ) - { - for (j=0; j 0 ) - { - if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) - { - hasnotarization = 1; - *nothtp = 0; - if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) - { - bits256 blockhash,txid,MoM; uint32_t MoMdepth; char symbol[65];//,str[65],str2[65],str3[65]; - vout = jitem(vouts,numvouts-1); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 36*2 && len < sizeof(script)*2 ) - { - len >>= 1; - decode_hex(script,len,hexstr); - if ( dpow_opreturn_parsesrc(&blockhash,nothtp,&txid,symbol,&MoM,&MoMdepth,script,len,mdata) > 0 && strcmp(symbol,coin->symbol) == 0 ) - { - // if ( Notaries_port != DPOW_SOCKPORT ) // keep going till valid MoM found, useful for new chains without any MoM - { - if ( bits256_nonz(MoM) == 0 || MoMdepth == 0 || *nothtp >= height || *nothtp < 0 ) - { - *nothtp = 0; - } - } - if ( mdata->pairs != 0 && mdata->numpairs > 0 ) - { - for (j=0; jnumpairs; j++) - { - if ( mdata->pairs[j].notarization_height > coin->MoMoMheight ) - { - coin->MoMoMheight = mdata->pairs[j].notarization_height; - printf("set %s MoMoMheight <- %d\n",coin->symbol,coin->MoMoMheight); - } - } - } - //printf("%s.%d notarizationht.%d %s -> %s MoM.%s [%d]\n",symbol,height,*nothtp,bits256_str(str,blockhash),bits256_str(str2,txid),bits256_str(str3,MoM),MoMdepth); - } - } - } - } - } - } - } - free_json(txobj); - } - if ( hasnotarization != 0 ) - (*signedmaskp) = notarymask; - return(hasnotarization); -} - -int32_t dpow_hasnotarization(uint64_t *signedmaskp,int32_t *nothtp,struct supernet_info *myinfo,struct iguana_info *coin,cJSON *blockjson,int32_t ht,struct komodo_ccdataMoMoM *mdata) -{ - int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; - *nothtp = 0; - *signedmaskp = 0; - memset(mdata,0,sizeof(*mdata)); - if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) - { - for (i=0; i maxheight ) - break; - blockhash = dpow_getblockhash(myinfo,coin,ht); - if ( (blockjson= dpow_getblock(myinfo,coin,blockhash)) != 0 ) - { - if ( dpow_hasnotarization(&signedmask,¬ht,myinfo,coin,blockjson,ht,&mdata) > 0 ) - { - if ( mdata.pairs != 0 ) - free(mdata.pairs); - for (j=0; j<64; j++) - if ( ((1LL << j) & signedmask) != 0 ) - masksums[j]++; - } - free_json(blockjson); - } - } - array = cJSON_CreateArray(); - for (i=0; i current - numblocks ) - { - printf("ht.%d %llx vs current.%d - %d\n",height,(long long)signedmask,current,numblocks); - for (j=0; j<64; j++) - if ( ((1LL << j) & signedmask) != 0 ) - vals[j] += (double)DPOW_UTXOSIZE / SATOSHIDEN; - } - } else break; - } - fclose(fp); - } else return(clonestr("{\"error\":\"cant open signedmasks\"}")); - for (sum=j=0; j 0. ) - { - bitcoin_address(coinaddr,0,pubkeys[j],33); // fixed - sprintf(cmd,"bitcoin-cli sendtoaddress %s %f\n",coinaddr,val); - if ( sendflag != 0 && system(cmd) != 0 ) - printf("ERROR with (%s)\n",cmd); - else - { - printf("%s\n",cmd); - sum += val; - } - } - } - printf("%s sent %.8f BTC\n",sendflag!=0?"":"would have",sum); - return(clonestr("{\"result\":\"success\"}")); - } - else return(clonestr("{\"error\":\"cant find BTC\"}")); - } - for (i=0; inumnotaries; i++) - { - item = cJSON_CreateObject(); - jaddstr(item,"notary",Notaries_elected[i][0]); - jaddnum(item,"bestk",bp->notaries[i].bestk); - sprintf(hexstr,"%16llx",(long long)bp->notaries[i].recvmask); - jaddstr(item,"recvmask",hexstr); - sprintf(hexstr,"%16llx",(long long)bp->notaries[i].bestmask); - jaddstr(item,"bestmask",hexstr); - jaddi(retjson,item); - } - return(retjson); -} - -STRING_ARG(dpow,active,maskhex) -{ - uint8_t data[8],revdata[8],pubkeys[64][33]; int32_t i,len,current,n; uint64_t mask; cJSON *infojson,*retjson,*array,*notarray; - array = cJSON_CreateArray(); - notarray = cJSON_CreateArray(); - if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 ) - { - current = jint(infojson,"blocks"); - free_json(infojson); - } else return(clonestr("{\"error\":\"cant get current height\"}")); - n = komodo_notaries("KMD",pubkeys,current); - if ( maskhex == 0 || maskhex[0] == 0 ) - { - return(jprint(dpow_recvmasks(myinfo,myinfo->DPOWS[0],myinfo->DPOWS[0]->currentbp),1)); - - /*mask = myinfo->DPOWS[0]->lastrecvmask; - for (i=0; i>= 1; - memset(data,0,sizeof(data)); - decode_hex(data,len,maskhex); - for (i=0; iDPOWS[0]->cancelratify = 1; - return(clonestr("{\"result\":\"queued dpow cancel ratify\"}")); -} - -ZERO_ARGS(dpow,ipaddrs) -{ - char ipaddr[64]; cJSON *array; int32_t i; - array = cJSON_CreateArray(); - for (i=0; inumdpowipbits; i++) - { - expand_ipbits(ipaddr,myinfo->dpowipbits[i]); - jaddistr(array,ipaddr); - } - return(jprint(array,1)); -} - -TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified) -{ - void **ptrs; bits256 zero; int32_t i; char *source; struct dpow_checkpoint checkpoint; - if ( ratified == 0 ) - return(clonestr("{\"error\":\"no ratified list for dpow ratify\"}")); - memset(zero.bytes,0,sizeof(zero)); - dpow_checkpointset(myinfo,&checkpoint,0,zero,timestamp,timestamp); - ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); - ptrs[0] = (void *)myinfo; - if ( (source= jstr(json,"source")) == 0 ) - source = "KMD"; - ptrs[1] = (void *)myinfo->DPOWS[0]; - for (i=0; inumdpows; i++) - if ( strcmp(myinfo->DPOWS[0]->symbol,source) == 0 ) - { - ptrs[1] = (void *)myinfo->DPOWS[i]; - break; - } - ptrs[2] = (void *)(long)minsigs; - ptrs[3] = (void *)DPOW_RATIFYDURATION; - ptrs[4] = (void *)jprint(ratified,0); - memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); - myinfo->DPOWS[0]->cancelratify = 0; - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) - { - } - return(clonestr("{\"result\":\"started ratification\"}")); -} - -HASH_AND_STRING(dex,gettransaction,txid,symbol) -{ - /*char str[65],url[1024],*retstr; - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); - - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); - }*/ - return(_dex_getrawtransaction(myinfo,symbol,txid)); -} - -HASH_AND_STRING_AND_INT(dex,gettxout,txid,symbol,vout) -{ - /*char str[65],url[1024],*retstr; - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/transaction/%s?api_key=%s",bits256_str(str,txid),myinfo->blocktrail_apikey); - }*/ - return(_dex_gettxout(myinfo,symbol,txid,vout)); -} - -TWO_STRINGS(dex,listunspent,symbol,address) -{ - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - char url[1024],*retstr,*coinaddr,*script; int32_t i,n,vout; cJSON *retjson,*data,*item,*item3,*data3; bits256 txid; uint64_t val; - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unspent-outputs?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - data = jarray(&n,retjson,"data"); - data3 = cJSON_CreateArray(); - //[{"hash":"e0a40dac21103e92e0dc9311a0233640489afc5beb5ba3b009848a8e9151dc55","time":"2017-02-21T16:48:28+0000","confirmations":1,"is_coinbase":false,"value":4100000,"index":1,"address":"19rjYdJtRN3qoammX3r1gxy9bvh8p8DmRc","type":"pubkeyhash","multisig":null,"script":"OP_DUP OP_HASH160 6128e7459989d35d530bcd4066c9aaf1f925430a OP_EQUALVERIFY OP_CHECKSIG","script_hex":"76a9146128e7459989d35d530bcd4066c9aaf1f925430a88ac"}] - /*{ - "txid" : "e95d3083baf733dfda2fcd1110fe2937cb3580f8b1b237aad547528440dfa873", - "vout" : 1, - "address" : "RNgdefRo2iRLWqDXEogJrsTw35MgDPQP4R", - "account" : "", - "scriptPubKey" : "76a91493088c5f3546225e0ef6ba9c9c6a74d4c2df877388ac", - "amount" : 150.00000000, - "interest" : 0.30000000, - "confirmations" : 20599, - "spendable" : true - }*/ - for (i=0; iFULLNODE < 0 ) - return(jprint(dpow_listunspent(myinfo,coin,address),1)); - //printf("call _dex_listunspent\n"); - return(_dex_listunspent(myinfo,symbol,address)); -} - -TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions,symbol,address,count,skip) -{ - if ( symbol != 0 && strcmp(symbol,"BTC") == 0 && (coin= iguana_coinfind("BTC")) != 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - char url[1024],*retstr,*retstr2; cJSON *retjson,*retjson2,*retjson3,*data,*data2; int32_t i,n; - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/transactions?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s/unconfirmed-transactions?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr2= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 && (retjson2= cJSON_Parse(retstr2)) != 0 ) - { - data = jarray(&n,retjson,"data"); - data2 = jarray(&n,retjson2,"data"); - retjson3 = jduplicate(data); - if ( n > 0 ) - { - for (i=0; i (%s)\n",retstr,retstr2,jprint(retjson3,0)); - free(retstr); - free(retstr2); - free_json(retjson); - free_json(retjson2); - return(jprint(retjson3,1)); - } - } - } - } - return(_dex_listtransactions(myinfo,symbol,address,count,skip)); -} - -STRING_ARG(dex,getinfo,symbol) -{ - return(_dex_getinfo(myinfo,symbol)); -} - -STRING_ARG(dex,getbestblockhash,symbol) -{ - return(_dex_getbestblockhash(myinfo,symbol)); -} - -STRING_ARG(dex,alladdresses,symbol) -{ - return(_dex_alladdresses(myinfo,symbol)); -} - -STRING_AND_INT(dex,getblockhash,symbol,height) -{ - return(_dex_getblockhash(myinfo,symbol,height)); -} - -HASH_AND_STRING(dex,getblock,hash,symbol) -{ - return(_dex_getblock(myinfo,symbol,hash)); -} - -TWO_STRINGS(dex,sendrawtransaction,symbol,signedtx) -{ - return(_dex_sendrawtransaction(myinfo,symbol,signedtx)); -} - -TWO_STRINGS(dex,importaddress,symbol,address) -{ - return(_dex_importaddress(myinfo,symbol,address)); -} - -TWO_STRINGS(dex,checkaddress,symbol,address) -{ - return(_dex_checkaddress(myinfo,symbol,address)); -} - -TWO_STRINGS(dex,validateaddress,symbol,address) -{ - return(_dex_validateaddress(myinfo,symbol,address)); -} - -STRING_ARG(dex,getmessage,argstr) -{ - return(_dex_getmessage(myinfo,argstr)); -} - -STRING_ARG(dex,psock,argstr) -{ - return(_dex_psock(myinfo,argstr)); -} - -STRING_ARG(dex,getnotaries,symbol) -{ - return(clonestr("{\"error\":\"dexgetnotaries deprecated\"}")); - //return(_dex_getnotaries(myinfo,symbol)); -} - -TWO_STRINGS(dex,kvsearch,symbol,key) -{ - if ( key == 0 || key[0] == 0 ) - return(clonestr("{\"error\":\"kvsearch parameter error\"}")); - return(_dex_kvsearch(myinfo,symbol,key)); -} - -THREE_STRINGS_AND_THREE_INTS(dex,kvupdate,symbol,key,value,flags,unused,unusedb) -{ - // need to have some micropayments between client/server, otherwise receiving server incurs costs - if ( key == 0 || key[0] == 0 || value == 0 || value[0] == 0 ) - return(clonestr("{\"error\":\"kvupdate parameter error\"}")); - if ( strcmp(symbol,"KV") == 0 ) - { - if ( flags > 1 ) - return(clonestr("{\"error\":\"only single duration updates via remote access\"}")); - else if ( strlen(key) > 64 || strlen(value) > 256 ) - return(clonestr("{\"error\":\"only keylen <=64 and valuesize <= 256 allowed via remote access\"}")); - else - { - //printf("call _dex_kvupdate.(%s) -> (%s) flags.%d\n",key,value,flags); - return(_dex_kvupdate(myinfo,symbol,key,value,flags)); - } - } else return(clonestr("{\"error\":\"free updates only on KV chain\"}")); -} - -#include "kmd_lookup.h" - -TWO_STRINGS(dex,listunspent2,symbol,address) -{ - cJSON *retjson; - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) - return(clonestr("[]")); - if ( (retjson= kmd_listunspent(myinfo,coin,address)) != 0 ) - return(jprint(retjson,1)); - } - } - if ( symbol != 0 && address != 0 ) - return(_dex_listunspent2(myinfo,symbol,address)); - else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); -} - -TWO_STRINGS_AND_TWO_DOUBLES(dex,listtransactions2,symbol,address,count,skip) -{ - cJSON *retjson; - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - if ( strcmp(coin->symbol,"BTC") == 0 || coin->DEXEXPLORER == 0 ) - return(clonestr("[]")); - if ( (retjson= kmd_listtransactions(myinfo,coin,address,count,skip)) != 0 ) - return(jprint(retjson,1)); - } - } - if ( symbol != 0 && address != 0 ) - return(_dex_listtransactions2(myinfo,symbol,address,count,skip)); - else return(clonestr("{\"error\":\"dex listunspent2 null symbol, address or coin\"}")); -} - -HASH_AND_STRING_AND_INT(dex,gettxin,txid,symbol,vout) -{ - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_gettxin(coin,txid,vout),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 ) - return(_dex_gettxin(myinfo,symbol,txid,vout)); - else return(clonestr("{\"error\":\"dex gettxin null symbolor coin\"}")); -} - -TWO_STRINGS(dex,listspent,symbol,address) -{ - if ( myinfo->DEXEXPLORER != 0 ) - { - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_listspent(myinfo,coin,address),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 && address != 0 ) - return(_dex_listspent(myinfo,symbol,address)); - else return(clonestr("{\"error\":\"dex listspent null symbol, address or coin\"}")); -} - -TWO_STRINGS(dex,getbalance,symbol,address) -{ - char url[512],*retstr; cJSON *retjson; uint64_t val; - if ( myinfo->DEXEXPLORER != 0 ) - { - //printf("DEXEXPLORER\n"); - if ( symbol != 0 && address != 0 && (coin= iguana_coinfind(symbol)) != 0 && coin->DEXEXPLORER != 0 ) - return(jprint(kmd_getbalance(myinfo,coin,address),1)); - if ( coin != 0 ) - coin->DEXEXPLORER = myinfo->DEXEXPLORER * myinfo->IAMNOTARY * (iguana_isnotarychain(coin->symbol) >= 0); - } - if ( symbol != 0 && address != 0 ) - { - if ( strcmp(symbol,"BTC") == 0 && myinfo->blocktrail_apikey[0] != 0 ) - { - sprintf(url,"https://api.blocktrail.com/v1/btc/address/%s?api_key=%s",address,myinfo->blocktrail_apikey); - if ( (retstr= issue_curl(url)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - //printf("balance\n"); - if ( (val= j64bits(retjson,"balance")) != 0 ) - { - jdelete(retjson,"balance"); - jaddnum(retjson,"balance",dstr(val)); - } - //printf("sent\n"); - if ( (val= j64bits(retjson,"sent")) != 0 ) - { - jdelete(retjson,"sent"); - jaddnum(retjson,"sent",dstr(val)); - } - //printf("received\n"); - if ( (val= j64bits(retjson,"received")) != 0 ) - { - jdelete(retjson,"received"); - jaddnum(retjson,"received",dstr(val)); - } - //printf("unconfirmed_sent\n"); - if ( (val= j64bits(retjson,"unconfirmed_sent")) != 0 ) - { - jdelete(retjson,"unconfirmed_sent"); - jaddnum(retjson,"unconfirmed_sent",dstr(val)); - } - //printf("unconfirmed_received\n"); - if ( (val= j64bits(retjson,"unconfirmed_received")) != 0 ) - { - jdelete(retjson,"unconfirmed_received"); - jaddnum(retjson,"unconfirmed_received",dstr(val)); - } - //printf("blocktrail.(%s) -> (%s)\n",retstr,jprint(retjson,0)); - free(retstr); - retstr = jprint(retjson,1); - } - } - return(retstr); - } - return(_dex_getbalance(myinfo,symbol,address)); - } else return(clonestr("{\"error\":\"dex getbalance null symbol, address or coin\"}")); -} - -STRING_ARG(dex,explorer,symbol) -{ - if ( symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 ) - { - myinfo->DEXEXPLORER = 1; - coin->DEXEXPLORER = 1; - return(clonestr("{\"result\":\"success\"}")); - } - return(clonestr("{\"error\":\"coin not active\"}")); -} - -#include "../includes/iguana_apiundefs.h" From d5a05106b06dcb86e4ca5c72fe5c3a6dd0abacfa Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 9 Feb 2019 04:14:02 -1100 Subject: [PATCH 13/14] Small I-return --- iguana/dpow/dpow_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iguana/dpow/dpow_rpc.c b/iguana/dpow/dpow_rpc.c index 5858ecfdc..8b51ac2d2 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -24,7 +24,7 @@ uint64_t dpow_utxosize(char *symbol) int32_t dpow_smallopreturn(char *symbol) { - if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) + if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"GIN") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) return(1); else return(0); } From d32073b74aaf075d51d8a4a5d550ab2113597ef5 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 9 Feb 2019 04:17:18 -1100 Subject: [PATCH 14/14] GIN with small opret --- iguana/dpow/dpow_rpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iguana/dpow/dpow_rpc.c b/iguana/dpow/dpow_rpc.c index 5858ecfdc..8b51ac2d2 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -24,7 +24,7 @@ uint64_t dpow_utxosize(char *symbol) int32_t dpow_smallopreturn(char *symbol) { - if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) + if ( strcmp(symbol,"GAME") == 0 || strcmp(symbol,"GIN") == 0 || strcmp(symbol,"EMC2") == 0 || strcmp(symbol,"HUSH") == 0 ) return(1); else return(0); }