diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index 6bd3824f8..be5c899d9 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -792,7 +792,7 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende { if ( strcmp((char *)basilisk_services[i][0],type) == 0 ) { - if ( (coin != 0 && coin->FULLNODE != 0) || myinfo->NOTARY.RELAYID >= 0 ) // iguana node + if ( (coin != 0 && coin->FULLNODE > 0) || myinfo->NOTARY.RELAYID >= 0 ) // iguana node { //printf("\n call %s from_basilisk.%d (%s)\n",addr->ipaddr,from_basilisk,type); if ( (retstr= (*basilisk_services[i][1])(myinfo,type,addr,remoteaddr,basilisktag,valsobj,data,datalen,hash,from_basilisk)) != 0 ) @@ -940,8 +940,13 @@ void basilisks_loop(void *arg) basilisk_iteration(myinfo); basilisk_p2pQ_process(myinfo,777); if ( myinfo->NOTARY.RELAYID >= 0 ) - endmilli = startmilli + 250; - else endmilli = startmilli + 1000; + { + iguana_dPoWupdate(myinfo); + endmilli = startmilli + 500; + } + else if ( myinfo->IAMLP != 0 ) + endmilli = startmilli + 1000; + else endmilli = startmilli + 2000; while ( OS_milliseconds() < endmilli ) usleep(10000); iter++; @@ -992,7 +997,7 @@ HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) timeoutmillis = BASILISK_TIMEOUT; if ( coin != 0 ) { - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { if ( (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) { diff --git a/basilisk/basilisk.h b/basilisk/basilisk.h index 9b9d45ab6..2f8e95527 100755 --- a/basilisk/basilisk.h +++ b/basilisk/basilisk.h @@ -17,7 +17,7 @@ #define H_BASILISK_H //#define BASILISK_DISABLESENDTX -#define BASILISK_DISABLEWAITTX +//#define BASILISK_DISABLEWAITTX #include "../iguana/iguana777.h" @@ -25,16 +25,14 @@ #define BASILISK_MINFANOUT 8 #define BASILISK_MAXFANOUT 64 #define BASILISK_DEFAULTDIFF 0x1effffff -#define BASILISK_MAXRELAYS 64 #define BASILISK_DEXDURATION 180 #define BASILISK_MSGDURATION 60 #define BASILISK_MAXFUTUREBLOCK 60 -//#define BASILISK_MAXBLOCKLAG 600 #define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t))) #define INSTANTDEX_DECKSIZE 1000 -#define INSTANTDEX_LOCKTIME 300 //(3600*2 + 300*2) +#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) #define INSTANTDEX_INSURANCEDIV 777 #define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" #define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" diff --git a/basilisk/basilisk_DEX.c b/basilisk/basilisk_DEX.c index 6fb4493c9..9340b1318 100755 --- a/basilisk/basilisk_DEX.c +++ b/basilisk/basilisk_DEX.c @@ -479,7 +479,7 @@ ZERO_ARGS(InstantDEX,allcoins) { if ( coin->virtualchain != 0 ) jaddistr(virtual,coin->symbol); - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) jaddistr(full,coin->symbol); else jaddistr(basilisk,coin->symbol); } diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index a11646b56..4da5b0066 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -290,7 +290,7 @@ int32_t basilisk_bitcoinscan(struct iguana_info *coin,uint8_t origblockspace[IGU int32_t basilisk_bitcoinavail(struct iguana_info *coin) { - if ( coin->VALIDATENODE != 0 || coin->FULLNODE != 0 ) + if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 ) return(1); //else if ( coin->chain->serverport[0] != 0 ) // return(1); @@ -392,7 +392,7 @@ void *basilisk_bitcoinvalue(struct basilisk_item *Lptr,struct supernet_info *myi vout = jint(valsobj,"vout"); if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 ) { - if ( (coin->VALIDATENODE != 0 || coin->FULLNODE != 0) )//&& coinaddr != 0 && coinaddr[0] != 0 ) + if ( (coin->VALIDATENODE > 0 || coin->FULLNODE > 0) )//&& coinaddr != 0 && coinaddr[0] != 0 ) { if ( iguana_RTunspentindfind(myinfo,coin,&outpt,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount,0) == 0 ) { @@ -447,7 +447,7 @@ void *basilisk_getinfo(struct basilisk_item *Lptr,struct supernet_info *myinfo,s return(clonestr("{\"error\":\"null valsobj\"}")); if ( (myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0) && strcmp(coin->symbol,"NOTARY") != 0 ) return(0); - if ( coin->VALIDATENODE != 0 || coin->FULLNODE != 0 ) + if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 ) { infojson = iguana_getinfo(myinfo,coin); Lptr->retstr = jprint(infojson,1); @@ -542,9 +542,9 @@ int32_t basilisk_vins_validate(struct supernet_info *myinfo,struct iguana_info * return(retval); } -char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,bits256 privkey,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag) +char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag,cJSON *addresses) { - uint8_t script[35],pubkey33[33]; int32_t i,spendlen; cJSON *txobj=0,*addresses=0,*vins=0; char *rawtx=0,*signedtx,changeaddr[64]; + uint8_t script[35]; int32_t i,spendlen; cJSON *txobj=0,*vins=0; char *rawtx=0,*signedtx,changeaddr[64]; *completedp = 0; if ( signedtxidp != 0 ) memset(signedtxidp,0,sizeof(*signedtxidp)); @@ -553,11 +553,9 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi { if ( duplicates <= 0 ) duplicates = 1; - bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); spendlen = bitcoin_pubkeyspend(script,0,pubkey33); for (i=0; itxfee + duplicates*coin->txfee/10,addresses,0,0,0,0,"127.0.0.1",0,1); printf("duplicatesTX.(%s)\n",rawtx); if ( signedtxidp != 0 ) @@ -577,8 +575,6 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi free_json(vins); if ( txobj != 0 ) free_json(txobj); - if ( addresses != 0 ) - free_json(addresses); return(rawtx); } @@ -903,7 +899,7 @@ HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr) basilisktag = rand(); if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) timeoutmillis = BASILISK_TIMEOUT; - if ( coin->FULLNODE != 0 && (ptr= basilisk_bitcoinvalue(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) + if ( coin->FULLNODE > 0 && (ptr= basilisk_bitcoinvalue(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) { retstr = ptr->retstr, ptr->retstr = 0; ptr->finished = OS_milliseconds() + 10000; diff --git a/basilisk/basilisk_swap.c b/basilisk/basilisk_swap.c index 0d19d950d..15783d5e4 100755 --- a/basilisk/basilisk_swap.c +++ b/basilisk/basilisk_swap.c @@ -1764,32 +1764,12 @@ int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap basilisk_sendstate(myinfo,swap,data,maxlen); basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); } - if ( retval != 0 ) - { - printf("end of atomic swap\n"); - if ( swap->I.iambob != 0 && swap->bobdeposit.txbytes != 0 ) - { - printf("BOB reclaims refund\n"); - basilisk_bobdeposit_refund(myinfo,swap,0); - if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000) == 0 ) // use secretBn - { - printf("Bob submit error getting refund of deposit\n"); - } - else - { - // maybe wait for bobrefund to be confirmed - for (j=datalen=0; j<32; j++) - data[datalen++] = swap->I.privBn.bytes[j]; - basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); - } - } - } return(retval); } void basilisk_swaploop(void *_swap) { - uint8_t *data; uint32_t expiration; int32_t retval=0,i,maxlen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; + uint8_t *data; uint32_t expiration; int32_t retval=0,i,j,datalen,maxlen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; myinfo = swap->myinfo; fprintf(stderr,"start swap\n"); maxlen = 1024*1024 + sizeof(*swap); @@ -1906,6 +1886,25 @@ void basilisk_swaploop(void *_swap) sleep(1); basilisk_sendstate(myinfo,swap,data,maxlen); basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits); + if ( time(NULL) > swap->I.expiration ) + break; + } + printf("end of atomic swap\n"); + if ( swap->I.iambob != 0 && swap->bobdeposit.txbytes != 0 ) + { + printf("BOB reclaims refund\n"); + basilisk_bobdeposit_refund(myinfo,swap,0); + if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000) == 0 ) // use secretBn + { + printf("Bob submit error getting refund of deposit\n"); + } + else + { + // maybe wait for bobrefund to be confirmed + for (j=datalen=0; j<32; j++) + data[datalen++] = swap->I.privBn.bytes[j]; + basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv); + } } printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits); basilisk_swap_purge(myinfo,swap); diff --git a/gecko/gecko_delayedPoW.c b/gecko/gecko_delayedPoW.c index 280f3065f..f903842b1 100755 --- a/gecko/gecko_delayedPoW.c +++ b/gecko/gecko_delayedPoW.c @@ -120,7 +120,7 @@ int32_t gecko_hashstampsupdate(struct iguana_info *coin,struct gecko_sequence *s int32_t gecko_sequpdate(struct supernet_info *myinfo,char *symbol,uint32_t reftimestamp) { struct gecko_sequence *seq=0; int32_t max=0,firstpossible=0; struct iguana_info *coin; struct iguana_block *block; - if ( (coin= iguana_coinfind(symbol)) != 0 && (coin->FULLNODE != 0 || coin->VALIDATENODE != 0) ) + if ( (coin= iguana_coinfind(symbol)) != 0 && (coin->FULLNODE > 0 || coin->VALIDATENODE > 0) ) { if ( strcmp(symbol,"BTCD") == 0 ) { diff --git a/iguana/dPoW.h b/iguana/dPoW.h new file mode 100755 index 000000000..f13bb8e9b --- /dev/null +++ b/iguana/dPoW.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#ifndef INCLUDE_DPOW_H +#define INCLUDE_DPOW_H + +#define DPOW_BTCSTR "BTCD" +#define DPOW_UTXOSIZE 6000 + +#define DPOW_FIFOSIZE 64 +#define DPOW_MAXTX 8192 +#define DPOW_THIRDPARTY_CONFIRMS 10 +#define DPOW_KOMODOCONFIRMS 10 +#define DPOW_BTCCONFIRMS 1 +#define DPOW_MAXRELAYS 64 + +struct komodo_notaries +{ + struct basilisk_relay RELAYS[DPOW_MAXRELAYS]; + int32_t NUMRELAYS,RELAYID; +}; + +struct dpow_hashheight { bits256 hash; int32_t height; }; + +struct dpow_checkpoint { struct dpow_hashheight blockhash,approved; bits256 miner; uint32_t blocktime,timestamp; }; + +struct dpow_info +{ + char symbol[16],dest[16]; uint8_t minerkey33[33],minerid; + struct dpow_checkpoint checkpoint,last,destchaintip,srcfifo[DPOW_FIFOSIZE],destfifo[DPOW_FIFOSIZE]; + struct dpow_hashheight approved[DPOW_FIFOSIZE],notarized[DPOW_FIFOSIZE]; + bits256 srctx[DPOW_MAXTX],desttx[DPOW_MAXTX]; + uint32_t destupdated,srcconfirms,numdesttx,numsrctx; +}; + + +#endif diff --git a/iguana/iguana777.c b/iguana/iguana777.c index c175aeb15..5618c4be3 100755 --- a/iguana/iguana777.c +++ b/iguana/iguana777.c @@ -856,6 +856,8 @@ void iguana_coinloop(void *arg) { if ( (coin= coins[i]) != 0 ) { + if ( coin->FULLNODE < 0 ) + continue; if ( strcmp(coin->symbol,"NOTARY") == 0 ) { if ( myinfo->expiration != 0 && (myinfo->IAMLP != 0 || myinfo->DEXactive > now) ) @@ -951,7 +953,7 @@ void iguana_coinloop(void *arg) } } } - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { if ( coin->peers->numranked > 0 ) iguana_send_ping(myinfo,coin,coin->peers->ranked[rand() % coin->peers->numranked]); @@ -964,7 +966,7 @@ void iguana_coinloop(void *arg) coin->peers->lastmetrics = iguana_updatemetrics(myinfo,coin); // ranks peers } } - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 || coin->MAXPEERS == 1 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 || coin->MAXPEERS == 1 ) { //portable_mutex_lock(&coin->allcoins_mutex); coin->busy_processing = 1; @@ -1104,12 +1106,12 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers, return(0); } if ( jobj(json,"RELAY") != 0 ) - coin->FULLNODE = juint(json,"RELAY"); + coin->FULLNODE = jint(json,"RELAY"); else coin->FULLNODE = (strcmp(coin->symbol,"BTCD") == 0); if ( jobj(json,"VALIDATE") != 0 ) coin->VALIDATENODE = juint(json,"VALIDATE"); else coin->VALIDATENODE = (strcmp(coin->symbol,"BTCD") == 0); - if ( coin->VALIDATENODE != 0 || coin->FULLNODE != 0 ) + if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 ) SuperNET_MYINFO(0)->IAMRELAY++; #ifdef __PNACL coin->VALIDATENODE = coin->FULLNODE = 0; diff --git a/iguana/iguana777.h b/iguana/iguana777.h index fe7542295..cf7ae9c0e 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -52,6 +52,7 @@ struct exchange_info; #include "../includes/iguana_types.h" #include "../includes/iguana_structs.h" #include "../basilisk/basilisk.h" +#include "dPoW.h" struct supernet_address { @@ -63,12 +64,6 @@ struct supernet_address struct liquidity_info { char base[64],rel[64]; double profit,refprice; }; struct message_info { int32_t msgcount; bits256 refhash,msghashes[64]; uint32_t timestamps[64]; }; -struct komodo_notaries -{ - struct basilisk_relay RELAYS[BASILISK_MAXRELAYS]; - int32_t NUMRELAYS,RELAYID; -}; - struct supernet_info { struct supernet_address myaddr; @@ -90,6 +85,7 @@ struct supernet_info void *ctx; uint8_t *pingbuf; FILE *dexfp; + struct dpow_info DPOW; struct delayedPoW_info dPoW; struct basilisk_spend *spends; int32_t numspends; struct peggy_info *PEGS; diff --git a/iguana/iguana_accept.c b/iguana/iguana_accept.c index 343f12b0c..74ee5c8f3 100755 --- a/iguana/iguana_accept.c +++ b/iguana/iguana_accept.c @@ -199,7 +199,7 @@ int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_in //char str[65]; printf("send type.%d %s -> (%s)\n",msg->type,bits256_str(str,msg->hash2),msg->addr->ipaddr); if ( msg->type == MSG_BLOCK ) { - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { if ( (addr= msg->addr) != 0 && (len= iguana_peerblockrequest(myinfo,coin,coin->blockspace,(int32_t)(coin->blockspacesize - sizeof(struct iguana_msghdr)),0,msg->hash2,0)) > 0 ) { @@ -210,7 +210,7 @@ int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_in } else if ( msg->type == MSG_TX ) { - if ( coin->FULLNODE != 0 || coin->VALIDATENODE ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { if ( (tx= iguana_txidfind(coin,&height,&T,msg->hash2,coin->bundlescount-1)) != 0 ) { diff --git a/iguana/iguana_blocks.c b/iguana/iguana_blocks.c index e908e6b12..b25f4bca9 100755 --- a/iguana/iguana_blocks.c +++ b/iguana/iguana_blocks.c @@ -125,7 +125,7 @@ void iguana_blockcopy(uint8_t zcash,uint8_t auxpow,struct iguana_info *coin,stru iguana_blocksizecheck("blockcopy src",coin->chain->zcash,origblock); if ( block->RO.allocsize != origblock->RO.allocsize ) printf("missing space for zcash block.%d origblock.%d\n",block->RO.allocsize,origblock->RO.allocsize); - else + //else { struct iguana_zblock *zblock = (void *)block; struct iguana_zblock *origzblock = (void *)origblock; diff --git a/iguana/iguana_chains.c b/iguana/iguana_chains.c index 30042426e..4ef81eb7d 100755 --- a/iguana/iguana_chains.c +++ b/iguana/iguana_chains.c @@ -500,7 +500,7 @@ void iguana_chaininit(struct supernet_info *myinfo,struct iguana_chain *chain,in chain->bundlesize = _IGUANA_BLOCKHASHES; } if ( chain->zcash != 0 ) - chain->bundlesize = 500; + chain->bundlesize = 1000; if ( strcmp(chain->symbol,"BTC") == 0 ) chain->bundlesize = 100; decode_hex((uint8_t *)chain->genesis_hashdata,32,(char *)chain->genesis_hash); diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index 28aa3e38f..0552d7a46 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -537,7 +537,7 @@ struct iguana_info *iguana_coinstart(struct supernet_info *myinfo,struct iguana_ printf("%s MYSERVICES.%llx\n",coin->symbol,(long long)coin->myservices); if ( coin->virtualchain == 0 && coin->peers != 0 ) { - if ( myinfo->IAMNOTARY != 0 || (coin->myservices & NODE_NETWORK) != 0 || (coin->FULLNODE != 0 || coin->VALIDATENODE != 0) ) + if ( myinfo->IAMNOTARY != 0 || (coin->myservices & NODE_NETWORK) != 0 || (coin->FULLNODE > 0 || coin->VALIDATENODE > 0) ) { if ( coin->peers->acceptloop == 0 && coin->peers->localaddr == 0 ) { diff --git a/iguana/iguana_msg.c b/iguana/iguana_msg.c index 536343946..69d115c89 100755 --- a/iguana/iguana_msg.c +++ b/iguana/iguana_msg.c @@ -385,7 +385,7 @@ int32_t iguana_send_version(struct iguana_info *coin,struct iguana_peer *addr,ui msg.nServices = (myservices & NODE_NETWORK); msg.nTime = (int64_t)time(NULL); msg.nonce = coin->instance_nonce; - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) sprintf(msg.strSubVer,"/iguana 0.00/"); else sprintf(msg.strSubVer,"/basilisk 0.00/"); //printf("SEND.(%s) -> (%s)\n",msg.strSubVer,addr->ipaddr); @@ -404,7 +404,7 @@ int32_t iguana_send_VPNversion(struct iguana_info *coin,struct iguana_peer *addr msg.nServices = (myservices & NODE_NETWORK); msg.nTime = (int64_t)time(NULL); msg.nonce = 0;//coin->instance_nonce; - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) sprintf(msg.strSubVer,"/iguana 0.00/"); else sprintf(msg.strSubVer,"/basilisk 0.00/"); msg.nStartingHeight = coin->blocks.hwmchain.height; @@ -416,7 +416,7 @@ void iguana_supernet_ping(struct supernet_info *myinfo,struct iguana_info *coin, { if ( addr->supernet != 0 || addr->basilisk != 0 ) { - //if ( coin->FULLNODE != 0 ) + //if ( coin->FULLNODE > 0 ) // basilisk_relays_send(myinfo,addr); //printf("send getpeers to %s\n",addr->ipaddr); //printf("maybe send basilisk ping here?\n"); diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index e173f86aa..dacb5298d 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -14,8 +14,861 @@ ******************************************************************************/ #include "iguana777.h" +#include "notaries.h" +struct dpow_entry +{ + bits256 prev_hash; + uint64_t mask; + int32_t prev_vout,height; + uint8_t pubkey[33],k,siglen,sig[76]; +}; + +bits256 dpow_getbestblockhash(struct supernet_info *myinfo,struct iguana_info *coin) +{ + char *retstr; bits256 blockhash; + memset(blockhash.bytes,0,sizeof(blockhash)); + if ( coin->FULLNODE < 0 ) + { + if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getbestblockhash","")) != 0 ) + { + printf("getbestblockhash.(%s)\n",retstr); + if ( is_hexstr(retstr,0) == sizeof(blockhash)*2 ) + decode_hex(blockhash.bytes,sizeof(blockhash),retstr); + free(retstr); + } + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + blockhash = coin->blocks.hwmchain.RO.hash2; + } + else + { + + } + return(blockhash); +} + +cJSON *dpow_getblock(struct supernet_info *myinfo,struct iguana_info *coin,bits256 blockhash) +{ + char buf[128],str[65],*retstr=0; cJSON *json = 0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"\"%s\"",bits256_str(str,blockhash)); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getblock",buf); + printf("getblock.(%s)\n",retstr); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + retstr = bitcoinrpc_getblock(myinfo,coin,0,0,blockhash,1,0); + } + else + { + return(0); + } + if ( retstr != 0 ) + { + json = cJSON_Parse(retstr); + free(retstr); + } + return(json); +} + +cJSON *dpow_gettransaction(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) +{ + char buf[128],str[65],*retstr=0,*rawtx=0; cJSON *json = 0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); + if ( (rawtx= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",buf)) != 0 ) + { + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"decoderawtransaction",rawtx); + printf("decoderawtransaction.(%s)\n",retstr); + free(rawtx); + } + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + retstr = bitcoinrpc_getrawtransaction(myinfo,coin,0,0,txid,1); + } + else + { + return(0); + } + if ( retstr != 0 ) + { + json = cJSON_Parse(retstr); + free(retstr); + } + return(json); +} + +cJSON *dpow_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr) +{ + char buf[128],*retstr; cJSON *json = 0; + if ( coin->FULLNODE < 0 ) + { + sprintf(buf,"1, %d, [\"%s\"]",coin->longestchain,coinaddr); + if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",buf)) != 0 ) + { + json = cJSON_Parse(retstr); + printf("listunspent.(%s)\n",retstr); + free(retstr); + } + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + json = iguana_listunspents(myinfo,coin,0,1,coin->longestchain,""); + } + else + { + return(0); + } + return(json); +} + +char *dpow_signrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx,cJSON *vins) +{ + cJSON *array,*privkeys,*item; char *wifstr,*str,*paramstr,*retstr; uint8_t script[256]; int32_t i,n,len,hashtype; struct vin_info V; struct iguana_waddress *waddr; struct iguana_waccount *wacct; + if ( coin->FULLNODE < 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,rawtx); + jaddi(array,vins); + paramstr = jprint(array,1); + retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"signrawtransaction",paramstr); + printf("signrawtransaction.(%s) params.(%s)\n",retstr,paramstr); + free(paramstr); + return(retstr); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + privkeys = cJSON_CreateArray(); + if ( (n= cJSON_GetArraySize(vins)) > 0 ) + { + for (i=0; i 0 && strlen(str) < sizeof(script)*2 ) + { + len = (int32_t)strlen(str) >> 1; + decode_hex(script,len,str); + V.spendlen = len; + memcpy(V.spendscript,script,len); + if ( (hashtype= _iguana_calcrmd160(coin,&V)) >= 0 && V.coinaddr[0] != 0 ) + { + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,V.coinaddr)) != 0 ) + { + if ( bits256_nonz(waddr->privkey) != 0 ) + { + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 ) + { + wifstr = waddr->wifstr; + } + } + } + } + } + jaddistr(privkeys,wifstr); + } + } + retstr = bitcoinrpc_signrawtransaction(myinfo,coin,0,0,rawtx,vins,privkeys,"ALL"); + free_json(privkeys); + return(retstr); + } + else + { + return(0); + } +} + +char *dpow_sendrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *signedtx) +{ + bits256 txid; cJSON *json; + if ( coin->FULLNODE < 0 ) + { + printf("sendrawtransaction.(%s)\n",signedtx); + return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"sendrawtransaction",signedtx)); + } + else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) + { + txid = iguana_sendrawtransaction(myinfo,coin,signedtx); + json = cJSON_CreateObject(); + jaddbits256(json,"result",txid); + return(jprint(json,1)); + } + else + { + return(0); + } +} + +int32_t dpow_haveutxo(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr) +{ + int32_t i,n,vout,haveutxo = 0; bits256 txid; cJSON *unspents,*item; uint64_t satoshis; char *str; uint8_t script[35]; + memset(txidp,0,sizeof(*txidp)); + *voutp = -1; + if ( (unspents= dpow_listunspent(myinfo,coin,coinaddr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(unspents)) > 0 ) + { + /*{ + "txid" : "34bc21b40d6baf38e2db5be5353dd0bcc9fe416485a2a68753541ed2f9c194b1", + "vout" : 0, + "address" : "RFBmvBaRybj9io1UpgWM4pzgufc3E4yza7", + "scriptPubKey" : "21039a3f7373ae91588b9edd76a9088b2871f62f3438d172b9f18e0581f64887404aac", + "amount" : 3.00000000, + "confirmations" : 4282, + "spendable" : true + },*/ + for (i=0; iDPOW.minerkey33,33) == 0 ) + { + txid = jbits256(item,"txid"); + vout = jint(item,"vout"); + if ( bits256_nonz(txid) != 0 && vout >= 0 ) + { + if ( *voutp < 0 ) + { + *voutp = vout; + *txidp = txid; + } + haveutxo++; + } + } + } + } + } + } + free_json(unspents); + } + return(haveutxo); +} + +int32_t dpow_message_utxo(bits256 *hashmsgp,bits256 *txidp,int32_t *voutp,cJSON *json) +{ + cJSON *msgobj,*item; uint8_t key[BASILISK_KEYSIZE],data[sizeof(bits256)*2+1]; char *keystr,*hexstr; int32_t i,j,n,datalen,retval = -1; + *voutp = -1; + memset(txidp,0,sizeof(*txidp)); + if ( (msgobj= jarray(&n,json,"messages")) != 0 ) + { + for (i=0; i 0 ) + { + decode_hex(key,BASILISK_KEYSIZE,keystr); + datalen >>= 1; + if ( datalen < sizeof(data) ) + { + decode_hex(data,datalen,hexstr); + if ( datalen == sizeof(data) ) + { + for (j=0; jbytes[j] = data[j]; + txidp->bytes[j] = data[j + sizeof(bits256)]; + } + *voutp = data[sizeof(bits256) * 2]; + retval = datalen; + } + } else printf("datalen.%d >= maxlen.%d\n",datalen,(int32_t)sizeof(data)); + } + } + } + return(retval); +} + +int32_t dpow_message_most(uint8_t *k_masks,int32_t num,cJSON *json,int32_t lastflag) +{ + cJSON *msgobj,*item; uint8_t key[BASILISK_KEYSIZE],data[128]; char *keystr,*hexstr; int32_t duplicate,i,j,n,datalen,most = 0; + if ( (msgobj= jarray(&n,json,"messages")) != 0 ) + { + for (i=0; i 0 ) + { + decode_hex(key,BASILISK_KEYSIZE,keystr); + datalen >>= 1; + if ( datalen < sizeof(data) ) + { + decode_hex(data,datalen,hexstr); + for (j=duplicate=0; j= maxlen.%d\n",datalen,(int32_t)sizeof(data)); + } + } + } + if ( lastflag != 0 && num > 0 ) + { + for (j=0; j most ) + { + most = n; + memcpy(&k_masks[num << 7],&k_masks[i << 7],1 << 7); + } + } + } + return(num); +} + +cJSON *dpow_createtx(struct iguana_info *coin,cJSON **vinsp,struct dpow_entry notaries[DPOW_MAXRELAYS],int32_t numnotaries,int32_t height,int32_t lastk,uint64_t mask,int32_t usesigs) +{ + int32_t i,j,m=0; char scriptstr[256]; cJSON *txobj=0,*vins=0,*item; uint64_t satoshis; uint8_t script[35]; + if ( (txobj= bitcoin_txcreate(coin->chain->isPoS,0,1,0)) != 0 ) + { + vins = cJSON_CreateArray(); + for (j=0; j 0 ) + { + init_hexbytes_noT(scriptstr,notaries[i].sig,notaries[i].siglen); + jaddstr(item,"scriptSig",scriptstr); + } + jaddi(vins,item); + bitcoin_txinput(coin,txobj,notaries[i].prev_hash,notaries[i].prev_vout,0xffffffff,script,sizeof(script),0,0,0,0); + m++; + if ( m == numnotaries/2+1 && i == lastk ) + break; + } + } + satoshis = DPOW_UTXOSIZE * m * .76; + script[0] = 33; + decode_hex(script+1,33,CRYPTO777_PUBSECPSTR); + script[34] = 0xac; + txobj = bitcoin_txoutput(txobj,script,sizeof(script),satoshis); + } + *vinsp = vins; + return(txobj); +} + +int32_t dpow_signedtxgen(struct supernet_info *myinfo,struct dpow_info *dp,struct iguana_info *coin,bits256 *signedtxidp,char *signedtx,uint64_t mask,int32_t lastk,struct dpow_entry notaries[DPOW_MAXRELAYS],int32_t numnotaries,int32_t height,int32_t myind) +{ + int32_t i,j,siglen,m=0; char *rawtx,*sigstr; cJSON *txobj,*sigobj,*txobj2,*vins,*item,*vin; uint8_t data[128],extraspace[8192],serialized[16384]; bits256 txid,srchash,desthash; struct iguana_msgtx msgtx; uint32_t channel; + channel = 's' | ('i' << 8) | ('g' << 16) | ('s' << 24); + for (j=0; jDPOW.minerkey33[j]; + if ( (txobj= dpow_createtx(coin,&vins,notaries,numnotaries,height,lastk,mask,0)) != 0 ) + { + if ( (rawtx= bitcoin_json2hex(myinfo,coin,&txid,txobj,0)) != 0 ) + { + if ( (signedtx= dpow_signrawtransaction(myinfo,coin,rawtx,vins)) != 0 ) + { + memset(&msgtx,0,sizeof(msgtx)); + if ( (txobj2= bitcoin_hex2json(coin,height,&txid,&msgtx,rawtx,extraspace,sizeof(extraspace),serialized,vins,1)) != 0 ) + { + if ( (vin= jarray(&m,txobj2,"vin")) != 0 && myind < m ) + { + item = jitem(vin,myind); + if ( (sigobj= jobj(item,"scriptSig")) != 0 && (sigstr= jstr(sigobj,"hex")) != 0 ) + { + siglen = (int32_t)strlen(sigstr) >> 1; + data[0] = myind; + data[1] = lastk; + iguana_rwnum(1,&data[2],sizeof(mask),(uint8_t *)&mask); + data[10] = siglen; + decode_hex(data+11,siglen,sigstr); + for (i=0; iDPOW.minerkey33[j]; + num = 0; + k_masks = calloc(4096,128); + for (i=0; i 0 ) + { + k = k_masks[(num << 7) + 1]; + iguana_rwnum(0,&k_masks[(num << 7) + 2],sizeof(mask),(uint8_t *)&mask); + *lastkp = k; + *maskp = mask; + if ( (most= dpow_k_masks_match(notaries,numnotaries,k_masks,num,k,mask,height)) >= numnotaries/2+1 ) + { + if ( (txobj= dpow_createtx(coin,&vins,notaries,numnotaries,height,k,mask,1)) != 0 ) + { + if ( (rawtx= bitcoin_json2hex(myinfo,coin,signedtxidp,txobj,0)) != 0 ) + { + strcpy(signedtx,rawtx); + free(rawtx); + } + free_json(txobj); + free_json(vins); + } + } + } + free(k_masks); + return(most); +} + +void dpow_txidupdate(struct supernet_info *myinfo,struct dpow_info *dp,struct iguana_info *coin,uint64_t *recvmaskp,uint32_t channel,int32_t height,struct dpow_entry notaries[DPOW_MAXRELAYS],int32_t numnotaries,int32_t myind,bits256 hashmsg) +{ + int32_t i,j,k,m; cJSON *item,*retarray; bits256 desthash,srchash,checkmsg; + for (i=0; ichain->pubtype,myinfo->DPOW.minerkey33,33); + if ( bits256_nonz(hashmsg) == 0 ) + return(0xffffffff); + for (j=0; jDPOW.minerkey33[j]; + switch ( state ) + { + case 0: + if ( (haveutxo= dpow_haveutxo(myinfo,coin,&txid,&vout,coinaddr)) != 0 ) + state = 1; + if ( haveutxo < 10 ) + { + addresses = cJSON_CreateArray(); + jaddistr(addresses,coinaddr); + if ( (rawtx= iguana_utxoduplicates(myinfo,coin,myinfo->DPOW.minerkey33,DPOW_UTXOSIZE,10,&completed,&signedtxid,0,addresses)) != 0 ) + { + if ( (sendtx= dpow_sendrawtransaction(myinfo,coin,rawtx)) != 0 ) + { + printf("sendrawtransaction.(%s)\n",sendtx); + free(sendtx); + } + free(rawtx); + } + free_json(addresses); + } + break; + case 1: // wait for utxo, send utxo to all other nodes + if ( (haveutxo= dpow_haveutxo(myinfo,coin,&txid,&vout,coinaddr)) != 0 && vout >= 0 && vout < 0x100 ) + { + for (i=(myind % incr); i numnotaries/2 ) + state = 3; + break; + case 3: // create rawtx, sign, send rawtx + sig to all other nodes + dpow_txidupdate(myinfo,dp,coin,recvmaskp,channel,heightmsg,notaries,numnotaries,myind,hashmsg); + k = 0; + if ( bitweight(*recvmaskp) > numnotaries/2+1 ) + { + mask = 0; + for (j=m=0; j= numnotaries/2+1 ) + break; + } + } + } else mask = *recvmaskp; + if ( bitweight(mask) == numnotaries/2+1 ) + { + if ( dpow_signedtxgen(myinfo,dp,coin,signedtxidp,signedtx,mask,k,notaries,numnotaries,heightmsg,myind) == 0 ) + state = 4; + } else printf("mask.%llx wt.%d\n",(long long)mask,bitweight(mask)); + break; + case 4: // wait for N/2+1 signed tx and broadcast + dpow_txidupdate(myinfo,dp,coin,recvmaskp,channel,heightmsg,notaries,numnotaries,myind,hashmsg); + if ( (m= dpow_mostsignedtx(myinfo,dp,coin,signedtxidp,signedtx,&mask,&k,notaries,numnotaries,heightmsg,myind)) > 0 ) + { + if ( m >= numnotaries/2+1 ) + { + if ( (retstr= dpow_sendrawtransaction(myinfo,coin,signedtx)) != 0 ) + { + printf("sendrawtransaction.(%s)\n",retstr); + free(retstr); + } + state = 0xffffffff; + } + else + { + dpow_signedtxgen(myinfo,dp,coin,signedtxidp,signedtx,mask,k,notaries,numnotaries,heightmsg,myind); + } + } + break; + } + return(state); +} + +void dpow_statemachinestart(void *ptr) +{ + struct supernet_info *myinfo; struct dpow_info *dp; struct dpow_checkpoint checkpoint; void **ptrs = ptr; + int32_t i,n,myind = -1; uint64_t recvmask = 0; uint32_t srcstate=0,deststate=0; struct iguana_info *src,*dest; struct dpow_hashheight srchash,desthash; char signedtx[16384],str[65],coinaddr[64]; bits256 signedtxid; struct dpow_entry notaries[DPOW_MAXRELAYS]; + memset(notaries,0,sizeof(notaries)); + myinfo = ptrs[0]; + dp = ptrs[1]; + memcpy(&checkpoint,&ptrs[2],sizeof(checkpoint)); + printf("statemachinestart %s->%s %s ht.%d\n",dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height); + src = iguana_coinfind(dp->symbol); + dest = iguana_coinfind(dp->dest); + n = (int32_t)(sizeof(Notaries)/sizeof(*Notaries)); + for (i=0; ichain->pubtype,notaries[i].pubkey,33); + printf("%s.%d ",coinaddr,i); + if ( memcmp(notaries[i].pubkey,myinfo->DPOW.minerkey33,33) == 0 ) + myind = i; + } + bitcoin_address(coinaddr,src->chain->pubtype,myinfo->DPOW.minerkey33,33); + if ( myind < 0 ) + { + printf("statemachinestart this node %s is not official notary\n",coinaddr); + free(ptr); + return; + } + dp->checkpoint = checkpoint; + srchash = checkpoint.blockhash; + desthash = dp->notarized[0]; + printf("DPOW statemachine checkpoint.%d src.%p dest.%p\n",checkpoint.blockhash.height,src,dest); + while ( src != 0 && dest != 0 && (srcstate != 0xffffffff || deststate != 0xffffffff) ) + { + sleep(10); + if ( dp->checkpoint.blockhash.height > checkpoint.blockhash.height ) + { + printf("abort ht.%d due to new checkpoint.%d\n",checkpoint.blockhash.height,dp->checkpoint.blockhash.height); + break; + } + if ( srcstate == 0 ) + srcstate = dpow_statemachineiterate(myinfo,dp,src,srcstate,srchash.hash,srchash.height,notaries,n,myind,&recvmask,&signedtxid,signedtx); + if ( deststate == 0 ) + deststate = dpow_statemachineiterate(myinfo,dp,dest,deststate,desthash.hash,desthash.height,notaries,n,myind,&recvmask,&signedtxid,signedtx); + } + free(ptr); +} + +int32_t dpow_getchaintip(struct supernet_info *myinfo,bits256 *blockhashp,uint32_t *blocktimep,bits256 *txs,uint32_t *numtxp,struct iguana_info *coin) +{ + int32_t n,i,height = -1,maxtx = *numtxp; bits256 besthash; cJSON *array,*json; + *numtxp = *blocktimep = 0; + besthash = dpow_getbestblockhash(myinfo,coin); + if ( bits256_nonz(besthash) != 0 ) + { + if ( (json= dpow_getblock(myinfo,coin,besthash)) != 0 ) + { + if ( (height= juint(json,"height")) != 0 && (*blocktimep= juint(json,"time")) != 0 ) + { + if ( (array= jarray(&n,json,"tx")) != 0 ) + { + for (i=0; i0; i--) + { + if ( (offset= (tip.blockhash.height - fifo[i].blockhash.height)) >= 0 && offset < DPOW_FIFOSIZE ) + newfifo[offset] = fifo[i]; + } + newfifo[0] = tip; + memcpy(fifo,newfifo,sizeof(newfifo)); +} + +void dpow_checkpointset(struct supernet_info *myinfo,struct dpow_checkpoint *checkpoint,int32_t height,bits256 hash,uint32_t timestamp,uint32_t blocktime) +{ + checkpoint->timestamp = 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) +{ + void **ptrs; + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); + if ( dp->destupdated != 0 && bits256_nonz(dp->srcfifo[dp->srcconfirms].blockhash.hash) != 0 ) + { + ptrs = calloc(1,sizeof(void *)*2 + sizeof(struct dpow_checkpoint)); + ptrs[0] = (void *)myinfo; + ptrs[1] = (void *)dp; + memcpy(&ptrs[2],&dp->srcfifo[dp->srcconfirms],sizeof(dp->srcfifo[dp->srcconfirms])); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + dp->destupdated = 0; + } +} + +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; + 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,DPOW_BTCSTR) == 0 ) + 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) +{ + int32_t height; uint32_t blocktime; bits256 blockhash; struct iguana_info *src,*dest; struct dpow_info *dp = &myinfo->DPOW; + if ( strcmp(dp->symbol,"KMD") == 0 ) + { + strcpy(dp->dest,DPOW_BTCSTR); + dp->srcconfirms = DPOW_KOMODOCONFIRMS; + } + else + { + strcpy(dp->dest,"KMD"); + dp->srcconfirms = DPOW_THIRDPARTY_CONFIRMS; + } + if ( dp->srcconfirms > DPOW_FIFOSIZE ) + dp->srcconfirms = DPOW_FIFOSIZE; + src = iguana_coinfind(dp->symbol); + dest = iguana_coinfind(dp->dest); + if ( src != 0 && dest != 0 ) + { + dp->numdesttx = sizeof(dp->desttx)/sizeof(*dp->desttx); + if ( (height= dpow_getchaintip(myinfo,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) + { + printf("%s got height.%d vs last.%d\n",dp->dest,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); + } + dp->numsrctx = sizeof(dp->srctx)/sizeof(*dp->srctx); + if ( (height= dpow_getchaintip(myinfo,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height >= 0 ) + { + printf("%s got height.%d vs last.%d\n",dp->symbol,height,dp->last.blockhash.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 dpow_srcupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); + } else dpow_srcupdate(myinfo,dp,height,blockhash,(uint32_t)time(NULL),blocktime); + } + } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); +} #include "../includes/iguana_apidefs.h" +TWO_STRINGS(iguana,dpow,symbol,pubkey) +{ + if ( myinfo->NOTARY.RELAYID < 0 ) + return(clonestr("{\"error\":\"must be running as notary node\"}")); + if ( myinfo->DPOW.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 ( iguana_coinfind(symbol) == 0 ) + return(clonestr("{\"error\":\"cant dPoW an inactive coin\"}")); + if ( strcmp(symbol,"KMD") == 0 && iguana_coinfind(DPOW_BTCSTR) == 0 ) + return(clonestr("{\"error\":\"cant dPoW KMD without BTC\"}")); + else if ( strcmp(symbol,"KMD") != 0 && iguana_coinfind("KMD") == 0 ) + return(clonestr("{\"error\":\"cant dPoW without KMD\"}")); + decode_hex(myinfo->DPOW.minerkey33,33,pubkey); + if ( bitcoin_pubkeylen(myinfo->DPOW.minerkey33) <= 0 ) + return(clonestr("{\"error\":\"illegal pubkey\"}")); + strcpy(myinfo->DPOW.symbol,symbol); + return(clonestr("{\"result\":\"success\"}")); +} + #include "../includes/iguana_apiundefs.h" diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index 2c9a3cad6..151759a1e 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -384,7 +384,7 @@ char *iguana_calcrawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJS void iguana_RTunspentslock(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins) { struct iguana_outpoint spentpt; char coinaddr[64]; int32_t i,RTspentflag,num,spentheight,lockedflag; - if ( coin->MAXPEERS == 1 || coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->MAXPEERS == 1 || coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { num = cJSON_GetArraySize(vins); for (i=0; ichain->isPoS,locktime,locktime==0?coin->chain->normal_txversion:coin->chain->locktime_txversion,0)) != 0 ) + if ( coin != 0 && (txobj= bitcoin_txcreate(coin->chain->isPoS,locktime,1,0)) != 0 ) { iguana_createvins(myinfo,coin,txobj,vins); if ( (n= cJSON_GetArraySize(vouts)) > 0 ) @@ -1394,18 +1394,25 @@ S_A_I_S(bitcoinrpc,sendmany,fromaccount,payments,minconf,comment) THREE_INTS(iguana,splitfunds,satoshis,duplicates,sendflag) { - char *rawtx; int32_t completed; cJSON *retjson; bits256 signedtxid; + char *rawtx; uint8_t pubkey33[33]; int32_t completed; cJSON *retjson,*addresses; bits256 signedtxid; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); if ( myinfo->expiration == 0 ) return(clonestr("{\"error\":\"need to unlock wallet\"}")); + if ( coin == 0 ) + return(clonestr("{\"error\":\"need active coin\"}")); retjson = cJSON_CreateObject(); - if ( (rawtx= iguana_utxoduplicates(myinfo,coin,myinfo->persistent_priv,satoshis,duplicates,&completed,&signedtxid,sendflag)) != 0 ) + bitcoin_pubkey33(myinfo->ctx,pubkey33,myinfo->persistent_priv); + addresses = iguana_getaddressesbyaccount(myinfo,coin,"*"); + if ( (rawtx= iguana_utxoduplicates(myinfo,coin,pubkey33,satoshis,duplicates,&completed,&signedtxid,sendflag,addresses)) != 0 ) { jaddstr(retjson,"result",rawtx); jaddbits256(retjson,"txid",signedtxid); jadd(retjson,"completed",completed != 0 ? jtrue() : jfalse()); + free(rawtx); } else jaddstr(retjson,"error","couldnt create duplicates tx"); + if ( addresses != 0 ) + free_json(addresses); return(jprint(retjson,1)); } diff --git a/iguana/iguana_peers.c b/iguana/iguana_peers.c index 5584d5b51..07115facd 100755 --- a/iguana/iguana_peers.c +++ b/iguana/iguana_peers.c @@ -1161,7 +1161,7 @@ int32_t iguana_peerslotinit(struct iguana_info *coin,struct iguana_peer *addr,in printf("iguana_peerslotinit cant create.(%s)\n",fname); return(-1); } - if ( coin->MAXPEERS == 1 || coin->VALIDATENODE != 0 || coin->FULLNODE != 0 ) + if ( coin->MAXPEERS == 1 || coin->VALIDATENODE > 0 || coin->FULLNODE > 0 ) { iguana_vinsfname(coin,0,fname,addr->addrind); if ( (addr->vinsfp= fopen(fname,"rb+")) != 0 ) diff --git a/iguana/iguana_sign.c b/iguana/iguana_sign.c index dd9b44d59..467000ef4 100755 --- a/iguana/iguana_sign.c +++ b/iguana/iguana_sign.c @@ -1435,8 +1435,11 @@ int32_t iguana_signrawtransaction(struct supernet_info *myinfo,struct iguana_inf { item = jitem(privkeys,i); privkeystr = jstr(item,0); + if ( privkeystr == 0 || privkeystr[0] == 0 ) + continue; privkey = iguana_str2priv(myinfo,coin,privkeystr); - V->signers[i].privkey = privkey; + if ( i < V->N ) + V->signers[i].privkey = privkey; if ( i < numinputs ) V[i].signers[0].privkey = privkey; if ( bits256_nonz(privkey) != 0 ) diff --git a/iguana/iguana_unspents.c b/iguana/iguana_unspents.c index 3e5a295db..fcbe8b8b6 100755 --- a/iguana/iguana_unspents.c +++ b/iguana/iguana_unspents.c @@ -1071,7 +1071,7 @@ int32_t iguana_unspentfindjson(cJSON *destarray,cJSON *item) cJSON *iguana_RTlistunspent(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *argarray,int32_t minconf,int32_t maxconf,char *remoteaddr,int32_t includespends) { uint64_t total = 0; int32_t i,j,m,n,numrmds,numunspents=0; char *coinaddr,*retstr; uint8_t *rmdarray; cJSON *vals,*unspents,*item,*array,*retjson,*retarray; bits256 hash; - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { retjson = cJSON_CreateArray(); rmdarray = iguana_rmdarray(myinfo,coin,&numrmds,argarray,0); @@ -1168,7 +1168,7 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info * } memset(pubkey,0,sizeof(pubkey)); //remains = required * 1.1 + coin->txfee; - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) { for (i=numunspents=0; iFULLNODE == 0 && coin->VALIDATENODE == 0 ) { if ( (array= iguana_RTlistunspent(myinfo,coin,addresses,minconf,1<<30,remoteaddr,0)) != 0 ) { @@ -1207,6 +1207,38 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info * free_json(array); } } + else + { + for (i=numunspents=0; i 0 ) + { + for (i=0; i= max )//|| sum > 10*required ) + break; + } + } + free_json(array); + } + } + } + } *totalp = sum; printf("numunspents.%d max.%d sum %.8f required %.8f\n",numunspents,max,dstr(sum),dstr(required)); return(numunspents); diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index 3fa57a181..75beed8e6 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -1139,7 +1139,7 @@ ZERO_ARGS(bitcoinrpc,getinfo) struct basilisk_item Lptr,*ptr; int32_t incr,i,j,m,n,longest; cJSON *valsobj,*getinfoobj=0,*array,*item,*fullnodes; if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); - if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) + if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) return(jprint(iguana_getinfo(myinfo,coin),1)); else { diff --git a/iguana/notaries.h b/iguana/notaries.h new file mode 100755 index 000000000..dd24efe1f --- /dev/null +++ b/iguana/notaries.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Copyright © 2014-2016 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. * + * * + ******************************************************************************/ + +#ifndef INCLUDE_NOTARIES_H +#define INCLUDE_NOTARIES_H + +char *Notaries[][2] = +{ + { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "jl777_testC", "020e0f6fe6e0fcdcac541eb728d6fe538a12adff20412b3c8a7fa892b223a47c2f" }, + /*{ "badass_EU", "034ca7bf1b9f084643960525a01d96949f36fdca35fe27f88ae9b167d496a75aa2" }, + { "crackers_NA", "03d40a9123a081c1513e5900f8bf47590952fd0d5587f64715b4b65af8d6be4985" }, + { "movecrypto_EU", "025b1e33dba14a0d4645e88f14992137e5c185708c7a2c219caffdf32dd6405e6e" }, + { "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" }, + { "pondsea_SH", "027ee1eebfe2bd62239c3e4a859c2e19861fc44b8d77fa569d6527f6f3cdf5925d" }, + { "locomb_EU", "0252c7a960606f53ea562207561b2be1a62bd2801944bb5ac41b5591fe03c7f0e5" }, + { "jeezy_EU", "035e05eca2eb3aab88a6e10c368b9f039cd6f5e02e4e6dc554eb7f552991915280" }, + { "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" }, + { "nxtswe_EU", "0393b7d10b7d723a1e26452a02755f229150e6626423859e1ae69771f1f374d09e" }, + { "crackers_EU", "024612bc1b43cf67692f243b5acbeb90e1f5704cd2f19c0741207ccc5fb218251e" }, + { "traderbill_EU", "03267254424fb00792b9d5cac7124849b70520e125dc0107946c44aecb9aab50fa" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, + { "Server1","0221876c8259764224dc1a7b70ec956f3fbe9a768cd77f13082cfa60eb6aa2d068"}, + { "Server2","03c7c14e6b1f94585bb571cf3ee5eb9b9ab54bd23d0acb8cf13edad1c515842b66"}, + { "Server3","02d28f8992ff0cd68c5d558cf55ec5b3ada25151519a6cea8cef1bac04c40023b6"}, + { "Server4","02adc84814fee5864e67fd1b76f97fbe74d6bd07c62335e2f1da918f46d08d84ba"}, + { "Server5","033dcf1c8308a00533fd3206c2db4f38ace0e08ae089a93efd873c8a2f80c4a620"}, + { "Server6","030f9f354cc8e2eaead1d978cc4db7009715083220fe48252fb0b0680d3a63d5a4"}, + { "Server7","0235d73cf8bc250e7a7032898423f24e240f1267a3c809a557daa3c17108d7585e"}, + { "Server8","03feea6d8ce239043baa9f3c9a1f15213dd4ac73df2bae5da71034f803dc005587"}, + { "Server9","02bfe32e6ce78c3795f0a2aa7e0dd47c51c674742f99ba9a0aec6d0d82d3d476b0"}, + { "Server10","037b46bdc3933fda6f47d14c8931fb8fffc4db85e0981ec4857fd56ee43300a29a"}, + { "Server11","03e6e375c5d36ebfbef9bd97c8cacb2d7a8f54bf89926ebde77fe7cc8cfb3c8e89"}, + { "Server12","032eff141519c1c4b111b1e51e9c4306c9dcfab9357fd27291daa5c6b3736c59d7"}, + { "Server13","03ae5eb57512a756031f7fd516d0f46e984632f73855fdf53fd4a08fbdef284af0"}, + { "Server14","03755d02c5aab06def772438d2a3b3d98d316091747e12b4e85b3a253cf757a730"}, + { "Server15","0260348f92cde87639ba9afc9f02b2c71ab52dc5faa00d175d0e331f71c05a521c"}, + { "Server16","02714f1922b72cce03633720402783de4962432adb3d3e38c95da754d43926e6f5"}, + { "Server17","028a2957cd7b428c3ba7ee2974e8dbbed0ee836721d00db6ea66db8f65c163a582"}, + { "Server18","033b24621b85b0593a7dae5867d112d8b80406369b8b07dde8be6ec6eb123de5aa"}, + { "Server19","0334556377815054bc39eb67186b02bd44ffe5acc9547516de0a639bcb947e2afb"}, + { "Server20","02564d75bed700f431eaabd087d1fbf59a566775ec146a65ad5137cd6ca0ff9c6d"}, + { "Server21","02345e3f2d281b0109cdcae6c70728027801060f231fc740b258c48aa43d75de0d"}, + { "Server22","0224991d534b187e9636d47253b2769fba299a0649c39615f2f31997052345c37c"}, + { "Server23","021a5deb5336e7d914f84616243c12e45268941449f7f0eb6e9d6772e0a605a9af"}, + { "Server24","036f5ae3b01b030acf6d6bc987feec5de5c340ff43887834af18fb0dee3961967c"}, + { "Server25","0377e432331fcca2e39324fdb815ab91171f26d7b838de04b39e4a5787966bf10c"}, + { "Server26","02ac499362e35c2d47b83c3c985abced6f3cb8b3f5c872a1b5806e2abba175a497"}, + { "Server27","0269611d0a1eedc67c323b2e17d332731e267c4c25716f1fa956ce027f7bae787f"}, + { "Server28","0203835a4c208a2a7ae5bafea393f04aaf6e863c93a3bd61f3a59a2383b1f7af31"}, + { "Server29","02ffc70831ca50e4d44f67462405fba12df7b01477e55c12ef6e696e4b1522ce3b"}, + { "Server30","022ab58e8ee541952f9f992890335097fa18479b5f66ad5f1f4a0e8f60959f3d19"},*/ +}; + +#endif diff --git a/iguana/tests/dpow b/iguana/tests/dpow new file mode 100755 index 000000000..b48b34107 --- /dev/null +++ b/iguana/tests/dpow @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"KMD\",\"pubkey\":\"020e0f6fe6e0fcdcac541eb728d6fe538a12adff20412b3c8a7fa892b223a47c2f\"}" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 8ac55a7c4..c9380cf20 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -13,6 +13,8 @@ * * ******************************************************************************/ +TWO_STRINGS(iguana,dpow,symbol,pubkey); + #ifdef INCLUDE_PAX ZERO_ARGS(pax,start); #endif diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index a16236466..43755fa95 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -495,7 +495,11 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson); int32_t iguana_inv2poll(struct supernet_info *myinfo,struct iguana_info *coin); struct iguana_bundlereq *iguana_bundlereq(struct iguana_info *coin,struct iguana_peer *addr,int32_t type,uint8_t *data,int32_t datalen); void instantdex_FSMinit(); -char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,bits256 privkey,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag); +cJSON *basilisk_channelget(struct supernet_info *myinfo,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,int32_t width); +int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t duration); +cJSON *dpow_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr); +void iguana_dPoWupdate(struct supernet_info *myinfo); +char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag,cJSON *addresses); int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); void iguana_RTunspentslock(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins); char *iguana_calcrawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJSON **vinsp,cJSON *txobj,int64_t satoshis,char *changeaddr,int64_t txfee,cJSON *addresses,int32_t minconf,uint8_t *opreturn,int32_t oplen,int64_t burnamount,char *remoteaddr,struct vin_info *V,int32_t maxmode);