diff --git a/iguana/dPoW.h b/iguana/dPoW.h index 6f547c97a..fd4336762 100755 --- a/iguana/dPoW.h +++ b/iguana/dPoW.h @@ -17,9 +17,13 @@ #define INCLUDE_DPOW_H #define DPOW_CHECKPOINTFREQ 10 -#define DPOW_M(bp) (7) // (((bp)->numnotaries >> 1) + 1) +#define DPOW_MINSIGS 7 +#define DPOW_M(bp) ((bp)->minsigs) // (((bp)->numnotaries >> 1) + 1) #define DPOW_VERSION 0x0205 #define DPOW_UTXOSIZE 10000 +#define DPOW_MINOUTPUT 6000 +#define DPOW_DURATION 300 +#define DPOW_RATIFYDURATION (3600 * 24) #define DPOW_UTXOCHANNEL ('d' | ('P' << 8) | ('o' << 16) | ('W' << 24)) #define DPOW_SIGCHANNEL ('s' | ('i' << 8) | ('g' << 16) | ('s' << 24)) @@ -76,7 +80,11 @@ struct komodo_notaries struct dpow_hashheight { bits256 hash; int32_t height; }; -struct dpow_checkpoint { struct dpow_hashheight blockhash,approved; bits256 miner; uint32_t blocktime,timestamp; }; +struct dpow_checkpoint +{ + struct dpow_hashheight blockhash,approved; + bits256 miner; uint32_t blocktime,timestamp; +}; struct dpow_block { @@ -86,8 +94,10 @@ struct dpow_block uint64_t recvmask,bestmask; struct dpow_entry notaries[DPOW_MAXRELAYS]; uint32_t state,timestamp,waiting,sigcrcs[2],txidcrcs[2],utxocrcs[2]; - int32_t height,numnotaries,completed; + int32_t height,numnotaries,completed,minsigs,duration,numratified; int8_t bestk; + cJSON *ratified; + uint8_t ratified_pubkeys[DPOW_MAXRELAYS][33]; char handles[DPOW_MAXRELAYS][32]; char signedtx[32768];//,rawtx[32768]; }; @@ -97,7 +107,7 @@ struct dpow_info 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,lastsplit,crcs[1024]; + uint32_t destupdated,srcconfirms,numdesttx,numsrctx,lastsplit,cancelratify,crcs[1024]; int32_t sock; struct dpow_block **blocks; }; diff --git a/iguana/dpow/dpow_fsm.c b/iguana/dpow/dpow_fsm.c index c0b7bf23b..2c9d44c8f 100755 --- a/iguana/dpow/dpow_fsm.c +++ b/iguana/dpow/dpow_fsm.c @@ -356,7 +356,7 @@ uint32_t dpow_statemachineiterate(struct supernet_info *myinfo,struct dpow_info int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_block *bp,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,char *coinaddr) { int32_t haveutxo,completed; bits256 signedtxid; cJSON *addresses; char *rawtx,*sendtx; - if ( (haveutxo= dpow_haveutxo(myinfo,coin,txidp,voutp,coinaddr)) <= 10 && time(NULL) > myinfo->DPOW.lastsplit+300 ) + if ( (haveutxo= dpow_haveutxo(myinfo,coin,txidp,voutp,coinaddr)) <= 10 && time(NULL) > myinfo->DPOW.lastsplit+bp->duration ) { addresses = cJSON_CreateArray(); jaddistr(addresses,coinaddr); @@ -379,22 +379,49 @@ int32_t dpow_checkutxo(struct supernet_info *myinfo,struct dpow_block *bp,struct 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; struct iguana_info *src,*dest; char str[65],str2[65],srcaddr[64],destaddr[64]; bits256 zero,srchash; struct dpow_block *bp; struct dpow_entry *ep = 0; uint32_t starttime = (uint32_t)time(NULL); + void **ptrs = ptr; + struct supernet_info *myinfo; struct dpow_info *dp; struct dpow_checkpoint checkpoint; + int32_t i,n,numratified,myind = -1; cJSON *ratified,*json,*item; struct iguana_info *src,*dest; char *jsonstr,*handle,*hexstr,str[65],str2[65],srcaddr[64],destaddr[64]; bits256 zero,srchash; struct dpow_block *bp; struct dpow_entry *ep = 0; uint32_t duration,minsigs,starttime = (uint32_t)time(NULL); memset(&zero,0,sizeof(zero)); myinfo = ptrs[0]; dp = ptrs[1]; + minsigs = (uint32_t)ptrs[2]; + duration = (uint32_t)ptrs[3]; + jsonstr = ptrs[4]; dp->destupdated = 0; // prevent another state machine till next BTC block - 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); + memcpy(&checkpoint,&ptrs[5],sizeof(checkpoint)); + printf("statemachinestart %s->%s %s ht.%d minsigs.%d duration.%d\n",dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration); src = iguana_coinfind(dp->symbol); dest = iguana_coinfind(dp->dest); if ( (bp= dp->blocks[checkpoint.blockhash.height]) == 0 ) { bp = calloc(1,sizeof(*bp)); + bp->minsigs = minsigs; //DPOW_MINSIGS; + bp->duration = duration; //DPOW_DURATION; bp->srccoin = src; bp->destcoin = dest; bp->opret_symbol = dp->symbol; + if ( jsonstr != 0 && (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (ratified= jarray(&numratified,json,"ratified")) != 0 ) + { + for (i=0; iratified_pubkeys[i],33,hexstr); + safecopy(bp->handles[i],handle,sizeof(bp->handles[i])); + } else break; + } + if ( i == numratified ) + { + bp->numratified = numratified; + bp->ratified = jduplicate(ratified); + } + } + free_json(json); + } bp->bestk = -1; dp->blocks[checkpoint.blockhash.height] = bp; bp->beacon = rand256(0); @@ -448,7 +475,7 @@ void dpow_statemachinestart(void *ptr) for (i=0; iDPOW.minerkey33[i+1]; dpow_utxosync(myinfo,bp,0,myind,srchash); - while ( time(NULL) < starttime+300 && src != 0 && dest != 0 && bp->state != 0xffffffff ) + while ( time(NULL) < starttime+bp->duration && src != 0 && dest != 0 && bp->state != 0xffffffff ) { sleep(2); if ( dp->checkpoint.blockhash.height > checkpoint.blockhash.height ) @@ -461,6 +488,8 @@ void dpow_statemachinestart(void *ptr) //printf("dp->ht.%d ht.%d DEST.%08x %s\n",dp->checkpoint.blockhash.height,checkpoint.blockhash.height,deststate,bits256_str(str,srchash.hash)); bp->state = dpow_statemachineiterate(myinfo,dp,dest,bp,myind,1); } + if ( myinfo->DPOW.cancelratify != 0 && checkpoint.blockhash.height == 0 ) + break; } printf("state machine ht.%d completed state.%x %s.%s %s.%s\n",bp->height,bp->state,dp->dest,bits256_str(str,bp->desttxid),dp->symbol,bits256_str(str2,bp->srctxid)); free(ptr); diff --git a/iguana/dpow/dpow_tx.c b/iguana/dpow/dpow_tx.c index ec87d7bf1..24345b40a 100755 --- a/iguana/dpow/dpow_tx.c +++ b/iguana/dpow/dpow_tx.c @@ -69,14 +69,70 @@ struct dpow_block *dpow_heightfind(struct supernet_info *myinfo,int32_t height) return(myinfo->DPOW.blocks!=0?myinfo->DPOW.blocks[height]:0); } -bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t usesigs,int32_t src_or_dest) +int32_t dpow_voutratify(struct dpow_block *bp,uint8_t *serialized,int32_t m,uint8_t pubkeys[][33],int32_t numratified) { - uint32_t k,j,m,numsigs,locktime,numvouts,version,sequenceid = 0xffffffff; - uint64_t satoshis,satoshisB; bits256 zero; int32_t opretlen,siglen,len; uint8_t serialized[32768],opret[1024],data[4096]; struct dpow_entry *ep; struct dpow_coinentry *cp; + uint64_t satoshis; uint32_t locktime = 0; uint32_t numvouts; int32_t i,len = 0; + numvouts = numratified + 1; + len += iguana_rwvarint32(1,&serialized[len],&numvouts); + satoshis = DPOW_MINOUTPUT; + len += iguana_rwnum(1,&serialized[len],sizeof(satoshis),&satoshis); + serialized[len++] = 35; + serialized[len++] = 33; + decode_hex(&serialized[len],33,CRYPTO777_PUBSECPSTR), len += 33; + serialized[len++] = CHECKSIG; + for (i=0; ihashmsg,&bp->height,0,bp,src_or_dest); + else opretlen = dpow_rwopret(1,opret,&bp->hashmsg,&bp->height,bp->srccoin->symbol,bp,src_or_dest); + if ( opretlen < 0 ) + return(-1); + opretlen = dpow_opreturnscript(data,opret,opretlen); + if ( opretlen < 0xfd ) + serialized[len++] = opretlen; + else + { + serialized[len++] = 0xfd; + serialized[len++] = opretlen & 0xff; + serialized[len++] = (opretlen >> 8) & 0xff; + } + memcpy(&serialized[len],data,opretlen), len += opretlen; + len += iguana_rwnum(1,&serialized[len],sizeof(locktime),&locktime); + return(len); +} + +bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t usesigs,int32_t src_or_dest,uint8_t pubkeys[][33],int32_t numratified) +{ + uint32_t k,j,m,numsigs,version,sequenceid = 0xffffffff; bits256 zero; int32_t n,siglen,len; uint8_t serialized[32768]; struct dpow_entry *ep; struct dpow_coinentry *cp; signedtx[0] = 0; *numsigsp = 0; memset(zero.bytes,0,sizeof(zero)); - len = locktime = numsigs = 0; + len = numsigs = 0; version = 1; len += iguana_rwnum(1,&serialized[len],sizeof(version),&version); if ( isPoS != 0 ) @@ -112,34 +168,18 @@ bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow break; } } - numvouts = 2; - len += iguana_rwvarint32(1,&serialized[len],&numvouts); - satoshis = DPOW_UTXOSIZE * m * .76; - if ( (satoshisB= DPOW_UTXOSIZE * m - 10000) < satoshis ) - satoshis = satoshisB; - len += iguana_rwnum(1,&serialized[len],sizeof(satoshis),&satoshis); - serialized[len++] = 35; - serialized[len++] = 33; - decode_hex(&serialized[len],33,CRYPTO777_PUBSECPSTR), len += 33; - serialized[len++] = CHECKSIG; - satoshis = 0; - len += iguana_rwnum(1,&serialized[len],sizeof(satoshis),&satoshis); - if ( src_or_dest != 0 ) - opretlen = dpow_rwopret(1,opret,&bp->hashmsg,&bp->height,0,bp,src_or_dest); - else opretlen = dpow_rwopret(1,opret,&bp->hashmsg,&bp->height,bp->srccoin->symbol,bp,src_or_dest); - if ( opretlen < 0 ) - return(zero); - opretlen = dpow_opreturnscript(data,opret,opretlen); - if ( opretlen < 0xfd ) - serialized[len++] = opretlen; + if ( pubkeys != 0 && numratified > 0 ) + { + if ( (n= dpow_voutratify(bp,&serialized[len],m,pubkeys,numratified)) < 0 ) + return(zero); + len += n; + } else { - serialized[len++] = 0xfd; - serialized[len++] = opretlen & 0xff; - serialized[len++] = (opretlen >> 8) & 0xff; + if ( (n= dpow_voutstandard(bp,&serialized[len],m,src_or_dest)) < 0 ) + return(zero); + len += n; } - memcpy(&serialized[len],data,opretlen), len += opretlen; - len += iguana_rwnum(1,&serialized[len],sizeof(locktime),&locktime); init_hexbytes_noT(signedtx,serialized,len); //printf("notarytx.(%s) opretlen.%d\n",signedtx,opretlen); *numsigsp = numsigs; @@ -243,7 +283,7 @@ int32_t dpow_signedtxgen(struct supernet_info *myinfo,struct iguana_info *coin,s srchash.bytes[j] = myinfo->DPOW.minerkey33[j+1]; if ( (vins= dpow_vins(coin,bp,bestk,bestmask,1,src_or_dest)) != 0 ) { - txid = dpow_notarytx(rawtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest); + txid = dpow_notarytx(rawtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest,bp->numratified!=0?bp->ratified_pubkeys:0,bp->numratified); if ( bits256_nonz(txid) != 0 && rawtx[0] != 0 ) // send tx to share utxo set { /*memset(&tmp,0,sizeof(tmp)); @@ -269,7 +309,7 @@ void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_block *bp,uint32_t //printf("sigscheck myind.%d src_dest.%d state.%x\n",myind,src_or_dest,bp->state); if ( bp->state != 0xffffffff && coin != 0 ) { - signedtxid = dpow_notarytx(bp->signedtx,&numsigs,coin->chain->isPoS,bp,bp->bestk,bp->bestmask,1,src_or_dest); + signedtxid = dpow_notarytx(bp->signedtx,&numsigs,coin->chain->isPoS,bp,bp->bestk,bp->bestmask,1,src_or_dest,bp->numratified!=0?bp->ratified_pubkeys:0,bp->numratified); printf("src_or_dest.%d bestk.%d %llx %s numsigs.%d signedtx.(%s)\n",src_or_dest,bp->bestk,(long long)bp->bestmask,bits256_str(str,signedtxid),numsigs,bp->signedtx); bp->state = 1; if ( bits256_nonz(signedtxid) != 0 && numsigs == DPOW_M(bp) ) @@ -285,7 +325,6 @@ void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_block *bp,uint32_t if ( src_or_dest != 0 ) { bp->desttxid = txid; - printf("send out KMD sig\n"); dpow_signedtxgen(myinfo,bp->srccoin,bp,bp->bestk,bp->bestmask,myind,DPOW_SIGCHANNEL,0); } else bp->srctxid = txid; diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index a4900f818..abf6db19e 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -69,10 +69,13 @@ void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t he dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); if ( dp->destupdated != 0 && bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % DPOW_CHECKPOINTFREQ) == 0 ) { - ptrs = calloc(1,sizeof(void *)*2 + sizeof(struct dpow_checkpoint)); + ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); ptrs[0] = (void *)myinfo; ptrs[1] = (void *)dp; - memcpy(&ptrs[2],&checkpoint,sizeof(checkpoint)); + ptrs[2] = (void *)DPOW_MINSIGS; + ptrs[3] = (void *)DPOW_DURATION; + ptrs[4] = 0; + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) { } @@ -248,6 +251,32 @@ STRING_ARG(iguana,addnotary,ipaddr) return(clonestr("{\"result\":\"notary node added\"}")); } +ZERO_ARGS(dpow,cancelratify) +{ + myinfo->DPOW.cancelratify = 1; + return(clonestr("{\"result\":\"queued dpow cancel ratify\"}")); +} + +TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified) +{ + void **ptrs; bits256 zero; 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; + ptrs[1] = (void *)&myinfo->DPOW; + ptrs[2] = (void *)(long)minsigs; + ptrs[3] = (void *)DPOW_RATIFYDURATION; + ptrs[4] = (void *)jprint(ratified,0); + memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + myinfo->DPOW.cancelratify = 0; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) + { + } + return(clonestr("{\"result\":\"started ratification\"}")); +} #include "../includes/iguana_apiundefs.h" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 6dfd367ad..81f27fe89 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -14,6 +14,9 @@ ******************************************************************************/ TWO_STRINGS(iguana,dpow,symbol,pubkey); +TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified); +ZERO_ARGS(dpow,cancelratify); + TWO_STRINGS(zcash,passthru,function,hex); TWO_STRINGS(komodo,passthru,function,hex);