You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
647 lines
30 KiB
647 lines
30 KiB
/******************************************************************************
|
|
* 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. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
struct dpow_entry *dpow_notaryfind(struct supernet_info *myinfo,struct dpow_block *bp,int32_t *senderindp,uint8_t *senderpub)
|
|
{
|
|
int32_t i;
|
|
*senderindp = -1;
|
|
for (i=0; i<bp->numnotaries; i++)
|
|
{
|
|
if ( memcmp(bp->notaries[i].pubkey,senderpub,33) == 0 )
|
|
{
|
|
//printf("matches notary.%d\n",i);
|
|
*senderindp = i;
|
|
return(&bp->notaries[i]);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void dpow_utxo2entry(struct dpow_block *bp,struct dpow_entry *ep,struct dpow_utxoentry *up)
|
|
{
|
|
int32_t i;
|
|
for (i=0; i<bp->numnotaries; i++)
|
|
bp->notaries[i].othermask |= up->othermasks[i];
|
|
ep->commit = up->commit;
|
|
ep->height = up->height;
|
|
ep->recvmask = up->recvmask;
|
|
ep->bestk = up->bestk;
|
|
ep->src.prev_hash = up->srchash;
|
|
ep->dest.prev_hash = up->desthash;
|
|
ep->src.prev_vout = up->srcvout;
|
|
ep->dest.prev_vout = up->destvout;
|
|
}
|
|
|
|
void dpow_entry2utxo(struct dpow_utxoentry *up,struct dpow_block *bp,struct dpow_entry *ep)
|
|
{
|
|
int32_t i;
|
|
up->commit = bp->commit;
|
|
up->hashmsg = bp->hashmsg;
|
|
up->height = bp->height;
|
|
up->recvmask = bp->recvmask;
|
|
up->bestk = bp->bestk;
|
|
for (i=0; i<bp->numnotaries; i++)
|
|
up->othermasks[i] = bp->notaries[i].recvmask;
|
|
for (i=0; i<33; i++)
|
|
up->pubkey[i] = ep->pubkey[i];
|
|
up->commit = ep->commit;
|
|
up->height = ep->height;
|
|
up->recvmask = ep->recvmask;
|
|
up->bestk = ep->bestk;
|
|
up->srchash = ep->src.prev_hash;
|
|
up->desthash = ep->dest.prev_hash;
|
|
up->srcvout = ep->src.prev_vout;
|
|
up->destvout = ep->dest.prev_vout;
|
|
}
|
|
|
|
void dpow_utxosync(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint64_t recvmask,int32_t myind,bits256 srchash)
|
|
{
|
|
uint32_t i,j,r; int32_t len; struct dpow_utxoentry U; uint8_t utxodata[sizeof(U)+2];
|
|
if ( (bp->recvmask ^ recvmask) != 0 )
|
|
{
|
|
if ( ((1LL << myind) & recvmask) == 0 )
|
|
{
|
|
i = myind;
|
|
//printf("utxosync bp->%llx != %llx, myind.%d\n",(long long)bp->recvmask,(long long)recvmask,myind);
|
|
}
|
|
else
|
|
{
|
|
r = (rand() % bp->numnotaries);
|
|
for (j=0; j<DPOW_M(bp); j++)
|
|
{
|
|
i = DPOW_MODIND(bp,j+r);
|
|
if ( ((1LL << i) & bp->recvmask) != 0 && ((1LL << i) & recvmask) == 0 )
|
|
break;
|
|
}
|
|
//printf("utxosync bp->%llx != %llx, random pick.%d\n",(long long)bp->recvmask,(long long)recvmask,i);
|
|
}
|
|
memset(&U,0,sizeof(U));
|
|
dpow_entry2utxo(&U,bp,&bp->notaries[i]);
|
|
//char str[65],str2[65];
|
|
//printf("send.(%s %s)\n",bits256_str(str,bp->notaries[i].dest.prev_hash),bits256_str(str2,bp->notaries[i].src.prev_hash));
|
|
if ( (len= dpow_rwutxobuf(1,utxodata,&U,bp)) > 0 )
|
|
dpow_send(myinfo,dp,bp,srchash,bp->hashmsg,DPOW_UTXOCHANNEL,bp->height,utxodata,len);
|
|
}
|
|
}
|
|
|
|
void dpow_sync(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint64_t refmask,int32_t myind,bits256 srchash,uint32_t channel,int32_t src_or_dest)
|
|
{
|
|
int8_t lastk; uint64_t mask;
|
|
mask = dpow_maskmin(refmask,bp,&lastk);
|
|
//dpow_utxosync(myinfo,bp,mask,myind,srchash);
|
|
if ( bp->notaries[myind].masks[lastk] == 0 )
|
|
dpow_signedtxgen(myinfo,dp,(src_or_dest != 0) ? bp->destcoin : bp->srccoin,bp,lastk,mask,myind,src_or_dest != 0 ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL,src_or_dest);
|
|
}
|
|
|
|
int32_t dpow_datahandler(struct supernet_info *myinfo,struct dpow_info *dp,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen)
|
|
{
|
|
bits256 txid,commit,srchash,hashmsg; struct dpow_block *bp = 0; uint32_t flag = 0; int32_t src_or_dest,senderind,i,iter,rlen,myind = -1; char str[65],str2[65]; struct dpow_sigentry dsig; struct dpow_entry *ep; struct dpow_coinentry *cp; struct dpow_utxoentry U; struct iguana_info *coin;
|
|
if ( (bp= dpow_heightfind(myinfo,dp,height)) == 0 )
|
|
{
|
|
if ( 0 && (rand() % 100) == 0 && height > 0 )
|
|
printf("couldnt find height.%d | if you just started notary dapp this is normal\n",height);
|
|
return(-1);
|
|
}
|
|
dpow_notaryfind(myinfo,bp,&myind,dp->minerkey33);
|
|
if ( myind < 0 )
|
|
{
|
|
printf("couldnt find myind height.%d | this means your pubkey for this node is not registered and needs to be ratified by majority vote of all notaries\n",height);
|
|
return(-1);
|
|
}
|
|
for (i=0; i<32; i++)
|
|
srchash.bytes[i] = dp->minerkey33[i+1];
|
|
if ( channel == DPOW_ENTRIESCHANNEL )
|
|
{
|
|
struct dpow_entry notaries[DPOW_MAXRELAYS]; uint8_t n; int8_t bestk; struct dpow_coinentry *ptr,*refptr;
|
|
rlen = 0;
|
|
bestk = data[rlen++];
|
|
n = data[rlen++];
|
|
rlen += iguana_rwbignum(0,&data[rlen],sizeof(hashmsg),hashmsg.bytes);
|
|
//printf("got ENTRIES bestk.%d numnotaries.%d\n",bestk,n);
|
|
if ( bits256_cmp(hashmsg,bp->hashmsg) == 0 )
|
|
{
|
|
memset(notaries,0,sizeof(notaries));
|
|
for (i=0; i<64; i++)
|
|
notaries[i].bestk = -1;
|
|
rlen += dpow_rwcoinentrys(0,&data[rlen],notaries,n,bestk);
|
|
//printf("matched hashmsg rlen.%d vs datalen.%d\n",rlen,datalen);
|
|
for (i=0; i<n; i++)
|
|
{
|
|
for (iter=0; iter<2; iter++)
|
|
{
|
|
ptr = iter != 0 ? ¬aries[i].dest : ¬aries[i].src;
|
|
refptr = iter != 0 ? &bp->notaries[i].dest : &bp->notaries[i].src;
|
|
if ( bits256_nonz(ptr->prev_hash) != 0 )
|
|
{
|
|
if ( bits256_nonz(refptr->prev_hash) == 0 )
|
|
{
|
|
printf(">>>>>>>>> %s got utxo.[%d] indirectly <<<<<<<<<<<\n",iter!=0?"dest":"src",i);
|
|
refptr->prev_hash = ptr->prev_hash;
|
|
refptr->prev_vout = ptr->prev_vout;
|
|
if ( iter == 1 && bits256_nonz(notaries[i].src.prev_hash) != 0 )
|
|
bp->recvmask |= (1LL << i);
|
|
}
|
|
}
|
|
if ( (bestk= notaries[i].bestk) >= 0 )
|
|
{
|
|
if ( ptr->siglens[bestk] > 0 && refptr->siglens[bestk] == 0 )
|
|
{
|
|
printf(">>>>>>>>>> got %s siglen.%d for [%d] indirectly <<<<<<<<<<\n",iter!=0?"dest":"src",ptr->siglens[bestk],i);
|
|
memcpy(refptr->sigs[bestk],ptr->sigs[bestk],ptr->siglens[bestk]);
|
|
refptr->siglens[bestk] = ptr->siglens[bestk];
|
|
if ( iter != 0 )
|
|
bp->destsigsmasks[bestk] |= (1LL << i);
|
|
else bp->srcsigsmasks[bestk] |= (1LL << i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( channel == DPOW_UTXOCHANNEL )
|
|
{
|
|
src_or_dest = 1;
|
|
coin = (src_or_dest != 0) ? bp->destcoin : bp->srccoin;
|
|
memset(&U,0,sizeof(U));
|
|
if ( dpow_rwutxobuf(0,data,&U,bp) < 0 )
|
|
{
|
|
printf("error from rwutxobuf\n");
|
|
return(0);
|
|
}
|
|
if ( bits256_cmp(U.hashmsg,bp->hashmsg) != 0 )
|
|
{
|
|
//printf("unexpected mismatch hashmsg.%s vs %s\n",bits256_str(str,U.hashmsg),bits256_str(str2,bp->hashmsg));
|
|
return(0);
|
|
}
|
|
if ( (ep= dpow_notaryfind(myinfo,bp,&senderind,U.pubkey)) != 0 )
|
|
{
|
|
dpow_utxo2entry(bp,ep,&U);
|
|
if ( ((1LL << senderind) & bp->recvmask) == 0 )
|
|
{
|
|
dpow_utxosync(myinfo,dp,bp,0,myind,srchash);
|
|
bp->recvmask |= (1LL << senderind);
|
|
}
|
|
dpow_sync(myinfo,dp,bp,ep->recvmask,myind,srchash,channel,src_or_dest);
|
|
flag = 1;
|
|
}
|
|
if ( 0 && flag == 0 && bp != 0 )
|
|
printf("ep.%p sender.%d UTXO.%d hashmsg.(%s) txid.(%s) v%d %llx\n",ep,senderind,height,bits256_str(str,U.hashmsg),bits256_str(str2,src_or_dest!=0?U.desthash:U.srchash),src_or_dest!=0?U.destvout:U.srcvout,(long long)bp->recvmask);
|
|
}
|
|
else if ( channel == DPOW_SIGCHANNEL || channel == DPOW_SIGBTCCHANNEL )
|
|
{
|
|
//printf("got sig.%x (%d %d) <<<<<<<<<< from.%d (%d %llx)\n",channel,channel == DPOW_SIGCHANNEL,channel == DPOW_SIGBTCCHANNEL,dsig.senderind,dsig.lastk,(long long)dsig.mask);
|
|
if ( dpow_rwsigentry(0,data,&dsig) < 0 )
|
|
{
|
|
printf("rwsigentry error\n");
|
|
return(0);
|
|
}
|
|
if ( channel == DPOW_SIGBTCCHANNEL )
|
|
{
|
|
src_or_dest = 1;
|
|
coin = bp->destcoin;
|
|
cp = &bp->notaries[dsig.senderind].dest;
|
|
//printf("gotsig %s channel.%x from %d bestk.%d %llx\n",coin->symbol,channel,dsig.senderind,dsig.lastk,(long long)dsig.mask);
|
|
}
|
|
else
|
|
{
|
|
src_or_dest = 0;
|
|
coin = bp->srccoin;
|
|
cp = &bp->notaries[dsig.senderind].src;
|
|
}
|
|
if ( dsig.senderind >= 0 && dsig.senderind < DPOW_MAXRELAYS )
|
|
{
|
|
if ( dsig.lastk < bp->numnotaries && dsig.senderind < bp->numnotaries && (ep= dpow_notaryfind(myinfo,bp,&senderind,dsig.senderpub)) != 0 )
|
|
{
|
|
vcalc_sha256(0,commit.bytes,dsig.beacon.bytes,sizeof(dsig.beacon));
|
|
if ( memcmp(dsig.senderpub,bp->notaries[dsig.senderind].pubkey,33) == 0 )
|
|
{
|
|
//if ( ep->masks[dsig.lastk] == 0 )
|
|
{
|
|
ep->masks[src_or_dest][dsig.lastk] = dsig.mask;
|
|
cp->siglens[dsig.lastk] = dsig.siglen;
|
|
memcpy(cp->sigs[dsig.lastk],dsig.sig,dsig.siglen);
|
|
ep->beacon = dsig.beacon;
|
|
if ( src_or_dest != 0 )
|
|
{
|
|
bp->destsigsmasks[dsig.lastk] |= (1LL << dsig.senderind);
|
|
if ( bp->bestk >= 0 && bp->bestk == dsig.lastk && (bp->bestmask & bp->destsigsmasks[dsig.lastk]) == bp->bestmask )
|
|
{
|
|
dpow_sigscheck(myinfo,dp,bp,DPOW_SIGBTCCHANNEL,myind,1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bp->srcsigsmasks[dsig.lastk] |= (1LL << dsig.senderind);
|
|
if ( bp->bestk >= 0 && bp->bestk == dsig.lastk && (bp->bestmask & bp->srcsigsmasks[dsig.lastk]) == bp->bestmask )
|
|
{
|
|
dpow_sigscheck(myinfo,dp,bp,DPOW_SIGCHANNEL,myind,0);
|
|
}
|
|
}
|
|
//printf(" ht.%d (%d %llx) <<<<<<<< %s from.%d got lastk.%d %llx/%llx siglen.%d >>>>>>>>>\n",bp->height,bp->bestk,(long long)bp->bestmask,coin->symbol,dsig.senderind,dsig.lastk,(long long)dsig.mask,(long long)bp->destsigsmasks[dsig.lastk],dsig.siglen);
|
|
dpow_sync(myinfo,dp,bp,dsig.mask,myind,srchash,channel,src_or_dest);
|
|
flag = 1;
|
|
}
|
|
} else printf("%s pubkey mismatch for senderind.%d %llx vs %llx\n",coin->symbol,dsig.senderind,*(long long *)dsig.senderpub,*(long long *)bp->notaries[dsig.senderind].pubkey);
|
|
} else printf("%s illegal lastk.%d or senderind.%d or senderpub.%llx\n",coin->symbol,dsig.lastk,dsig.senderind,*(long long *)dsig.senderpub);
|
|
} else printf("couldnt find senderind.%d height.%d channel.%x\n",dsig.senderind,height,channel);
|
|
//if ( 0 && bp != 0 )
|
|
// printf("%s SIG.%d sender.%d lastk.%d mask.%llx siglen.%d recv.%llx\n",coin->symbol,height,dsig.senderind,dsig.lastk,(long long)dsig.mask,dsig.siglen,(long long)bp->recvmask);
|
|
}
|
|
else if ( channel == DPOW_TXIDCHANNEL || channel == DPOW_BTCTXIDCHANNEL )
|
|
{
|
|
src_or_dest = (channel == DPOW_BTCTXIDCHANNEL);
|
|
coin = (src_or_dest != 0) ? bp->destcoin : bp->srccoin;
|
|
printf("handle txid channel.%x\n",channel);
|
|
//printf("bp.%p datalen.%d\n",bp,datalen);
|
|
for (i=0; i<32; i++)
|
|
srchash.bytes[i] = data[i];
|
|
txid = bits256_doublesha256(0,&data[32],datalen-32);
|
|
init_hexbytes_noT(bp->signedtx,&data[32],datalen-32);
|
|
printf("signedtx.(%s)\n",bp->signedtx);
|
|
if ( bits256_cmp(txid,srchash) == 0 )
|
|
{
|
|
printf("verify (%s) it is properly signed! set ht.%d signedtxid to %s\n",coin->symbol,height,bits256_str(str,txid));
|
|
if ( src_or_dest != 0 )
|
|
{
|
|
bp->desttxid = txid;
|
|
bp->state = 1000;
|
|
dp->destupdated = 0;
|
|
dpow_signedtxgen(myinfo,dp,bp->srccoin,bp,bp->bestk,bp->bestmask,myind,DPOW_SIGCHANNEL,0);
|
|
//dpow_sigscheck(myinfo,dp,bp,DPOW_SIGCHANNEL,myind,0);
|
|
}
|
|
else
|
|
{
|
|
bp->srctxid = txid;
|
|
printf("set state COMPLETED\n");
|
|
bp->state = 0xffffffff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
init_hexbytes_noT(bp->signedtx,data,datalen);
|
|
printf("txidchannel txid %s mismatch %s (%s)\n",bits256_str(str,txid),bits256_str(str2,srchash),bp->signedtx);
|
|
bp->signedtx[0] = 0;
|
|
}
|
|
} else printf("unhandled channel.%x\n",channel);
|
|
return(0);
|
|
}
|
|
|
|
int32_t dpow_update(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,uint32_t txidchannel,bits256 srchash,int32_t myind)
|
|
{
|
|
struct dpow_entry *ep; int32_t i,k,len,src_or_dest,sendutxo = 0; uint8_t data[sizeof(struct dpow_entry)+2]; struct dpow_utxoentry U;
|
|
ep = &bp->notaries[myind];
|
|
if ( bp->state < 1000 )
|
|
{
|
|
src_or_dest = 1;
|
|
bp->bestmask = dpow_maskmin(bp->recvmask,bp,&bp->bestk);
|
|
if ( bp->bestk >= 0 )
|
|
{
|
|
sendutxo = 0;
|
|
for (i=0; i<bp->numnotaries; i++)
|
|
{
|
|
k = DPOW_MODIND(bp,i);
|
|
if ( k == myind )
|
|
continue;
|
|
if ( ((1LL << k) & bp->recvmask) != 0 && (bp->notaries[k].recvmask & (1LL << myind)) == 0 )
|
|
{
|
|
//printf("other notary.%d doesnt have our.%d utxo yet\n",k,myind);
|
|
sendutxo = 1;
|
|
break;
|
|
}
|
|
}
|
|
if ( ep->masks[src_or_dest][bp->bestk] == 0 )
|
|
dpow_signedtxgen(myinfo,dp,(src_or_dest != 0) ? bp->destcoin : bp->srccoin,bp,bp->bestk,bp->bestmask,myind,DPOW_SIGBTCCHANNEL,src_or_dest);
|
|
if ( bp->bestk >= 0 && (rand() % 10) == 0 )
|
|
dpow_sigsend(myinfo,dp,bp,myind,bp->bestk,bp->bestmask,srchash,DPOW_SIGBTCCHANNEL);
|
|
} else sendutxo = 1;
|
|
if ( sendutxo != 0 )
|
|
{
|
|
memset(&U,0,sizeof(U));
|
|
dpow_entry2utxo(&U,bp,&bp->notaries[myind]);
|
|
if ( (len= dpow_rwutxobuf(1,data,&U,bp)) > 0 )
|
|
dpow_send(myinfo,dp,bp,srchash,bp->hashmsg,DPOW_UTXOCHANNEL,bp->height,data,len);
|
|
}
|
|
if ( bp->bestk >= 0 && ep->masks[src_or_dest][bp->bestk] == 0 )
|
|
dpow_signedtxgen(myinfo,dp,(src_or_dest != 0) ? bp->destcoin : bp->srccoin,bp,bp->bestk,bp->bestmask,myind,DPOW_SIGBTCCHANNEL,src_or_dest);
|
|
if ( bp->bestk >= 0 && (rand() % 10) == 0 )
|
|
dpow_sigsend(myinfo,dp,bp,myind,bp->bestk,bp->bestmask,srchash,DPOW_SIGBTCCHANNEL);
|
|
}
|
|
else if ( bp->state != 0xffffffff )
|
|
{
|
|
src_or_dest = 0;
|
|
if ( bp->bestk >= 0 && ep->masks[src_or_dest][bp->bestk] == 0 )
|
|
dpow_signedtxgen(myinfo,dp,(src_or_dest != 0) ? bp->destcoin : bp->srccoin,bp,bp->bestk,bp->bestmask,myind,DPOW_SIGCHANNEL,src_or_dest);
|
|
if ( bp->bestk >= 0 && (rand() % 10) == 0 )
|
|
dpow_sigsend(myinfo,dp,bp,myind,bp->bestk,bp->bestmask,srchash,DPOW_SIGCHANNEL);
|
|
}
|
|
if ( (rand() % 10) == 0 )
|
|
{
|
|
if ( bp->isratify != 0 )
|
|
{
|
|
uint64_t sigsmask,srcmask;
|
|
if ( bp->bestk < 0 )
|
|
sigsmask = srcmask = 0;
|
|
else sigsmask = bp->destsigsmasks[bp->bestk], srcmask = bp->srcsigsmasks[bp->bestk];
|
|
printf("[%d] %s isratify.%d ht.%d FSM.%08x masks.%llx best.(%d %llx) sigsmask.%llx %llx src.%llx\n",myind,src_or_dest != 0 ? bp->destcoin->symbol : bp->srccoin->symbol,bp->isratify,bp->height,bp->state,(long long)bp->recvmask,bp->bestk,(long long)bp->bestmask,(long long)sigsmask,(long long)(sigsmask & bp->bestmask),(long long)srcmask);
|
|
}
|
|
if ( bp->isratify != 0 || (rand() % 10) == 0 )
|
|
{
|
|
bp->bestmask = dpow_maskmin(bp->recvmask,bp,&bp->bestk);
|
|
dpow_sendcoinentrys(myinfo,dp,bp);
|
|
if ( bp->bestk >= 0 )
|
|
dpow_signedtxgen(myinfo,dp,(bp->state < 1000) ? bp->destcoin : bp->srccoin,bp,bp->bestk,bp->bestmask,myind,bp->state < 1000 ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL,bp->state < 1000);
|
|
printf("ht.%d numnotaries.%d BEST.%llx from RECV.%llx bestk.%d sigsmask.%llx\n",bp->height,bp->numnotaries,(long long)bp->bestmask,(long long)bp->recvmask,bp->bestk,bp->bestk>=0?(long long)bp->destsigsmasks[bp->bestk]:0);
|
|
if ( bp->height < DPOW_FIRSTRATIFY )
|
|
dp->blocks[bp->height] = bp;
|
|
}
|
|
}
|
|
if ( bp->state < 1000 && bp->bestk >= 0 && (bp->destsigsmasks[bp->bestk] & bp->bestmask) == bp->bestmask )
|
|
{
|
|
dpow_sigscheck(myinfo,dp,bp,DPOW_SIGBTCCHANNEL,myind,1);
|
|
}
|
|
else if ( bp->state != 0xffffffff && bp->bestk >= 0 && (bp->srcsigsmasks[bp->bestk] & bp->bestmask) == bp->bestmask )
|
|
{
|
|
dpow_sigscheck(myinfo,dp,bp,DPOW_SIGCHANNEL,myind,0);
|
|
}
|
|
return(bp->state);
|
|
}
|
|
|
|
uint32_t dpow_statemachineiterate(struct supernet_info *myinfo,struct dpow_info *dp,struct iguana_info *coin,struct dpow_block *bp,int32_t myind,int32_t src_or_dest)
|
|
{
|
|
int32_t j,incr; char *opret_symbol,coinaddr[64]; uint32_t channel,sigchannel,txidchannel; bits256 srchash,zero;
|
|
if ( 0 && bp->numnotaries > 8 )
|
|
incr = sqrt(bp->numnotaries) + 1;
|
|
else incr = 1;
|
|
memset(zero.bytes,0,sizeof(zero));
|
|
channel = DPOW_UTXOCHANNEL;
|
|
if ( bits256_nonz(bp->desttxid) == 0 )
|
|
{
|
|
sigchannel = DPOW_SIGBTCCHANNEL;
|
|
txidchannel = DPOW_BTCTXIDCHANNEL;
|
|
opret_symbol = "";
|
|
}
|
|
else
|
|
{
|
|
sigchannel = DPOW_SIGCHANNEL;
|
|
txidchannel = DPOW_TXIDCHANNEL;
|
|
opret_symbol = dp->symbol;
|
|
}
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,dp->minerkey33,33);
|
|
if ( bits256_nonz(bp->hashmsg) == 0 && bp->height >= DPOW_FIRSTRATIFY )
|
|
return(0);
|
|
for (j=0; j<sizeof(srchash); j++)
|
|
srchash.bytes[j] = dp->minerkey33[j+1];
|
|
bp->bestk = dpow_bestk(bp,&bp->bestmask);
|
|
if ( bp->state < 7 )
|
|
{
|
|
dpow_utxosync(myinfo,dp,bp,0,myind,srchash);
|
|
bp->state++;
|
|
}
|
|
else
|
|
{
|
|
dpow_update(myinfo,dp,bp,txidchannel,srchash,myind);
|
|
if ( bits256_nonz(bp->srctxid) != 0 )
|
|
bp->state = 0xffffffff;
|
|
}
|
|
return(bp->state);
|
|
}
|
|
|
|
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)
|
|
{
|
|
int32_t haveutxo,completed; bits256 signedtxid; cJSON *addresses; char *rawtx,*sendtx;
|
|
if ( (haveutxo= dpow_haveutxo(myinfo,coin,txidp,voutp,coinaddr)) <= 10 && time(NULL) > dp->lastsplit+bp->duration )
|
|
{
|
|
addresses = cJSON_CreateArray();
|
|
jaddistr(addresses,coinaddr);
|
|
if ( (rawtx= iguana_utxoduplicates(myinfo,coin,dp->minerkey33,DPOW_UTXOSIZE,strcmp(coin->symbol,"BTC") == 0 ? 50 : 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);
|
|
dp->lastsplit = (uint32_t)time(NULL);
|
|
}
|
|
if ( bits256_nonz(*txidp) == 0 )
|
|
return(-1);
|
|
return(haveutxo);
|
|
}
|
|
|
|
void dpow_statemachinestart(void *ptr)
|
|
{
|
|
void **ptrs = ptr;
|
|
struct supernet_info *myinfo; struct dpow_info *dp; struct dpow_checkpoint checkpoint;
|
|
int32_t i,destprevvout0,srcprevvout0,numratified=0,kmdheight,myind = -1; uint8_t pubkeys[64][33]; cJSON *ratified=0,*item; struct iguana_info *src,*dest; char *jsonstr,*handle,*hexstr,str[65],str2[65],srcaddr[64],destaddr[64]; bits256 zero,srchash,destprevtxid0,srcprevtxid0; struct dpow_block *bp; struct dpow_entry *ep = 0; uint32_t duration,minsigs,starttime;
|
|
memset(&zero,0,sizeof(zero));
|
|
srcprevtxid0 = destprevtxid0 = zero;
|
|
srcprevvout0 = destprevvout0 = -1;
|
|
myinfo = ptrs[0];
|
|
dp = ptrs[1];
|
|
minsigs = (uint32_t)(long)ptrs[2];
|
|
duration = (uint32_t)(long)ptrs[3];
|
|
jsonstr = ptrs[4];
|
|
kmdheight = -1;
|
|
memcpy(&checkpoint,&ptrs[5],sizeof(checkpoint));
|
|
printf("statemachinestart %s->%s %s ht.%d minsigs.%d duration.%d start.%u\n",dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp);
|
|
src = iguana_coinfind(dp->symbol);
|
|
dest = iguana_coinfind(dp->dest);
|
|
if ( strcmp(src->symbol,"KMD") == 0 )
|
|
kmdheight = checkpoint.blockhash.height;
|
|
else if ( strcmp(dest->symbol,"KMD") == 0 )
|
|
kmdheight = dest->longestchain;
|
|
if ( (bp= dp->blocks[checkpoint.blockhash.height]) == 0 )
|
|
{
|
|
bp = calloc(1,sizeof(*bp));
|
|
bp->minsigs = minsigs;
|
|
if ( (bp->duration= duration) == DPOW_RATIFYDURATION )
|
|
bp->isratify = 1;
|
|
bp->srccoin = src;
|
|
bp->destcoin = dest;
|
|
bp->opret_symbol = dp->symbol;
|
|
if ( jsonstr != 0 && (ratified= cJSON_Parse(jsonstr)) != 0 )
|
|
{
|
|
if ( (numratified= cJSON_GetArraySize(ratified)) > 0 )
|
|
{
|
|
for (i=0; i<numratified; i++)
|
|
{
|
|
item = jitem(ratified,i);
|
|
hexstr = handle = 0;
|
|
if ( (hexstr= jstr(item,"pubkey")) != 0 && is_hexstr(hexstr,0) == 66 && (handle= jstr(item,"handle")) != 0 )
|
|
{
|
|
decode_hex(bp->ratified_pubkeys[i],33,hexstr);
|
|
safecopy(bp->handles[i],handle,sizeof(bp->handles[i]));
|
|
if ( i == 0 )
|
|
{
|
|
destprevtxid0 = jbits256(item,"destprevtxid0");
|
|
destprevvout0 = jint(item,"destprevvout0");
|
|
srcprevtxid0 = jbits256(item,"srcprevtxid0");
|
|
srcprevvout0 = jint(item,"srcprevvout0");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("break loop hexstr.%p handle.%p\n",hexstr,handle);
|
|
break;
|
|
}
|
|
}
|
|
if ( i == numratified )
|
|
{
|
|
bp->numratified = numratified;
|
|
bp->ratified = ratified;
|
|
printf("numratified.%d %s\n",numratified,jprint(ratified,0));
|
|
}
|
|
else
|
|
{
|
|
printf("i.%d numratified.%d\n",i,numratified);
|
|
free_json(ratified);
|
|
}
|
|
}
|
|
}
|
|
bp->bestk = -1;
|
|
dp->blocks[checkpoint.blockhash.height] = bp;
|
|
bp->beacon = rand256(0);
|
|
vcalc_sha256(0,bp->commit.bytes,bp->beacon.bytes,sizeof(bp->beacon));
|
|
/*if ( checkpoint.blockhash.height >= DPOW_FIRSTRATIFY && dp->blocks[checkpoint.blockhash.height - DPOW_FIRSTRATIFY] != 0 )
|
|
{
|
|
printf("purge %s.%d\n",dp->dest,checkpoint.blockhash.height - DPOW_FIRSTRATIFY);
|
|
free(dp->blocks[checkpoint.blockhash.height - DPOW_FIRSTRATIFY]);
|
|
dp->blocks[checkpoint.blockhash.height - DPOW_FIRSTRATIFY] = 0;
|
|
}*/
|
|
}
|
|
bitcoin_address(srcaddr,src->chain->pubtype,dp->minerkey33,33);
|
|
bitcoin_address(destaddr,dest->chain->pubtype,dp->minerkey33,33);
|
|
if ( kmdheight >= 0 )
|
|
{
|
|
bp->numnotaries = komodo_notaries(pubkeys,kmdheight);
|
|
for (i=0; i<bp->numnotaries; i++)
|
|
{
|
|
//for (j=0; j<33; j++)
|
|
// printf("%02x",pubkeys[i][j]);
|
|
//printf(" <= pubkey[%d]\n",i);
|
|
memcpy(bp->notaries[i].pubkey,pubkeys[i],33);
|
|
if ( memcmp(bp->notaries[i].pubkey,dp->minerkey33,33) == 0 )
|
|
{
|
|
myind = i;
|
|
ep = &bp->notaries[myind];
|
|
}
|
|
}
|
|
if ( myind < 0 || ep == 0 )
|
|
{
|
|
printf("minerkey33-> ");
|
|
for (i=0; i<33; i++)
|
|
printf("%02x",dp->minerkey33[i]);
|
|
printf(" statemachinestart this node %s %s is not official notary numnotaries.%d\n",srcaddr,destaddr,bp->numnotaries);
|
|
free(ptr);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("statemachinestart no kmdheight.%d\n",kmdheight);
|
|
free(ptr);
|
|
return;
|
|
}
|
|
printf(" myind.%d myaddr.(%s %s)\n",myind,srcaddr,destaddr);
|
|
if ( myind == 0 && bits256_nonz(destprevtxid0) != 0 && bits256_nonz(srcprevtxid0) != 0 && destprevvout0 >= 0 && srcprevvout0 >= 0 )
|
|
{
|
|
ep->dest.prev_hash = destprevtxid0;
|
|
ep->dest.prev_vout = destprevvout0;
|
|
ep->src.prev_hash = srcprevtxid0;
|
|
ep->src.prev_vout = srcprevvout0;
|
|
printf("Use override utxo %s/v%d %s/v%d\n",bits256_str(str,destprevtxid0),destprevvout0,bits256_str(str2,srcprevtxid0),srcprevvout0);
|
|
}
|
|
else
|
|
{
|
|
if ( dpow_checkutxo(myinfo,dp,bp,bp->destcoin,&ep->dest.prev_hash,&ep->dest.prev_vout,destaddr) < 0 )
|
|
{
|
|
printf("dont have %s %s utxo, please send funds\n",dp->dest,destaddr);
|
|
free(ptr);
|
|
return;
|
|
}
|
|
if ( dpow_checkutxo(myinfo,dp,bp,bp->srccoin,&ep->src.prev_hash,&ep->src.prev_vout,srcaddr) < 0 )
|
|
{
|
|
printf("dont have %s %s utxo, please send funds\n",dp->symbol,srcaddr);
|
|
free(ptr);
|
|
return;
|
|
}
|
|
}
|
|
bp->recvmask |= (1LL << myind);
|
|
bp->notaries[myind].othermask |= (1LL << myind);
|
|
dp->checkpoint = checkpoint;
|
|
bp->height = checkpoint.blockhash.height;
|
|
bp->timestamp = checkpoint.timestamp;
|
|
bp->hashmsg = checkpoint.blockhash.hash;
|
|
while ( bp->isratify == 0 && dp->destupdated == 0 )
|
|
{
|
|
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);
|
|
return;
|
|
}
|
|
sleep(1);
|
|
}
|
|
if ( (starttime= checkpoint.timestamp) == 0 )
|
|
starttime = (uint32_t)time(NULL);
|
|
printf("isratify.%d DPOW.%s statemachine checkpoint.%d %s start.%u\n",bp->isratify,src->symbol,checkpoint.blockhash.height,bits256_str(str,checkpoint.blockhash.hash),checkpoint.timestamp);
|
|
for (i=0; i<sizeof(srchash); i++)
|
|
srchash.bytes[i] = dp->minerkey33[i+1];
|
|
dpow_utxosync(myinfo,dp,bp,0,myind,srchash);
|
|
while ( time(NULL) < starttime+bp->duration && src != 0 && dest != 0 && bp->state != 0xffffffff )
|
|
{
|
|
sleep(2);
|
|
if ( dp->checkpoint.blockhash.height > checkpoint.blockhash.height )
|
|
{
|
|
if ( bp->isratify == 0 )
|
|
{
|
|
printf("abort ht.%d due to new checkpoint.%d\n",checkpoint.blockhash.height,dp->checkpoint.blockhash.height);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
bp->bestk = -1;
|
|
bp->bestmask = bp->recvmask = 0;
|
|
bp->height = ((dp->checkpoint.blockhash.height / 10) % (DPOW_FIRSTRATIFY/10)) * 10;
|
|
printf("new rotation ht.%d\n",bp->height);
|
|
dp->blocks[checkpoint.blockhash.height] = 0;
|
|
checkpoint.blockhash.height = dp->checkpoint.blockhash.height;
|
|
dp->blocks[checkpoint.blockhash.height] = bp;
|
|
for (i=0; i<64; i++)
|
|
{
|
|
bp->notaries[i].recvmask = 0;
|
|
bp->notaries[i].bestk = -1;
|
|
}
|
|
memset(bp->destsigsmasks,0,sizeof(bp->destsigsmasks));
|
|
memset(bp->notaries[myind].masks,0,sizeof(bp->notaries[myind].masks));
|
|
}
|
|
}
|
|
if ( bp->state != 0xffffffff )
|
|
{
|
|
//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 ( 0 && dp->cancelratify != 0 && bp->isratify != 0 )
|
|
{
|
|
printf("abort pending ratify\n");
|
|
break;
|
|
}
|
|
}
|
|
printf("state machine ht.%d completed state.%x %s.%s %s.%s recvmask.%llx\n",bp->height,bp->state,dp->dest,bits256_str(str,bp->desttxid),dp->symbol,bits256_str(str2,bp->srctxid),(long long)bp->recvmask);
|
|
dp->lastrecvmask = bp->recvmask;
|
|
free(ptr);
|
|
}
|
|
|
|
|