jl777
8 years ago
7 changed files with 1365 additions and 1297 deletions
@ -0,0 +1,365 @@ |
|||||
|
/******************************************************************************
|
||||
|
* 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
|
||||
|
void dpow_datahandler(struct supernet_info *myinfo,struct dpow_block *bp,uint32_t channel,uint32_t height,uint8_t *data,int32_t datalen) |
||||
|
{ |
||||
|
bits256 hashmsg,txid,commit,srchash; uint32_t flag = 0; uint64_t mask; int8_t lastk; int32_t senderind,i,j,r,vout,len,myind = -1; char str[65],str2[65]; uint8_t utxodata[1024]; struct dpow_sigentry dsig; struct dpow_entry *ep,E; |
||||
|
if ( channel == DPOW_UTXOCHANNEL || channel == DPOW_UTXOBTCCHANNEL ) |
||||
|
{ |
||||
|
memset(&E,0,sizeof(E)); |
||||
|
if ( dpow_rwutxobuf(0,data,&hashmsg,&E) < 0 ) |
||||
|
return; |
||||
|
if ( bp != 0 || (bp= dpow_heightfind(myinfo,height,channel == DPOW_UTXOBTCCHANNEL)) != 0 ) |
||||
|
{ |
||||
|
dpow_notaryfind(myinfo,bp,&myind,myinfo->DPOW.minerkey33); |
||||
|
if ( myind < 0 ) |
||||
|
return; |
||||
|
if ( bits256_cmp(hashmsg,bp->hashmsg) != 0 ) |
||||
|
{ |
||||
|
printf("unexpected mismatch hashmsg.%s vs %s\n",bits256_str(str,hashmsg),bits256_str(str2,bp->hashmsg)); |
||||
|
return; |
||||
|
} |
||||
|
if ( (ep= dpow_notaryfind(myinfo,bp,&senderind,E.pubkey)) != 0 ) |
||||
|
{ |
||||
|
if ( bits256_nonz(ep->prev_hash) == 0 ) |
||||
|
{ |
||||
|
*ep = E; |
||||
|
bp->recvmask |= (1LL << senderind); |
||||
|
if ( (bp->recvmask ^ E.recvmask) != 0 ) |
||||
|
{ |
||||
|
if ( ((1LL << myind) & E.recvmask) == 0 ) |
||||
|
i = myind; |
||||
|
else |
||||
|
{ |
||||
|
r = (rand() % bp->numnotaries); |
||||
|
for (j=0; j<DPOW_M(bp); j++) |
||||
|
{ |
||||
|
i = ((bp->height % bp->numnotaries) + j + r) % bp->numnotaries; |
||||
|
if ( ((1LL << i) & bp->recvmask) != 0 && ((1LL << i) & bp->recvmask) == 0 ) |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
printf("sender.%d %llx doesnt have ours %llx\n",senderind,(long long)E.recvmask,(long long)(1LL << i)); |
||||
|
if ( (len= dpow_rwutxobuf(1,utxodata,&bp->hashmsg,&bp->notaries[i])) > 0 ) |
||||
|
dpow_send(myinfo,bp,srchash,bp->hashmsg,channel,bp->height,utxodata,len,bp->utxocrcs); |
||||
|
} |
||||
|
mask = dpow_maskmin(ep->recvmask,bp,&lastk); |
||||
|
if ( (mask & bp->recvmask) == mask ) |
||||
|
dpow_signedtxgen(myinfo,bp->coin,bp,ep->bestk,mask,myind,bp->opret_symbol,bits256_nonz(bp->btctxid) == 0 ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL); |
||||
|
flag = 1; |
||||
|
printf("<<<<<<<<<< %s from.%ld got ht.%d %s/v%d\n",bp->coin->symbol,((long)ep - (long)bp->notaries)/sizeof(*ep),height,bits256_str(str,E.prev_hash),E.prev_vout); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if ( 0 && flag == 0 && bp != 0 ) |
||||
|
printf("UTXO.%d hashmsg.(%s) txid.(%s) v%d\n",height,bits256_str(str,hashmsg),bits256_str(str2,E.prev_hash),vout); |
||||
|
} |
||||
|
else if ( channel == DPOW_SIGCHANNEL || channel == DPOW_SIGBTCCHANNEL ) |
||||
|
{ |
||||
|
if ( dpow_rwsigentry(0,data,&dsig) < 0 ) |
||||
|
return; |
||||
|
if ( dsig.senderind >= 0 && dsig.senderind < DPOW_MAXRELAYS && (bp != 0 || (bp= dpow_heightfind(myinfo,height,channel == DPOW_SIGBTCCHANNEL)) != 0) ) |
||||
|
{ |
||||
|
dpow_notaryfind(myinfo,bp,&myind,myinfo->DPOW.minerkey33); |
||||
|
if ( myind < 0 ) |
||||
|
return; |
||||
|
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 ) //bits256_cmp(ep->commit,commit) == 0 &&
|
||||
|
{ |
||||
|
if ( ep->masks[dsig.lastk] == 0 ) |
||||
|
{ |
||||
|
ep->masks[dsig.lastk] = dsig.mask; |
||||
|
ep->siglens[dsig.lastk] = dsig.siglen; |
||||
|
memcpy(ep->sigs[dsig.lastk],dsig.sig,dsig.siglen); |
||||
|
ep->beacon = dsig.beacon; |
||||
|
//for (j=0; j<dsig.siglen; j++)
|
||||
|
// printf("%02x",dsig.sig[j]);
|
||||
|
printf(" <<<<<<<< %s from.%d got lastk.%d %llx siglen.%d >>>>>>>>>\n",bp->coin->symbol,dsig.senderind,dsig.lastk,(long long)dsig.mask,dsig.siglen); |
||||
|
mask = dpow_maskmin(ep->recvmask,bp,&lastk); |
||||
|
if ( (mask & bp->recvmask) == mask ) |
||||
|
dpow_signedtxgen(myinfo,bp->coin,bp,dsig.lastk,mask,myind,bp->opret_symbol,bits256_nonz(bp->btctxid) == 0 ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL); |
||||
|
if ( ((1LL << myind) & dsig.mask) == 0 ) |
||||
|
{ |
||||
|
printf("B sender.%d %llx doesnt have ours %llx\n",dsig.senderind,(long long)dsig.mask,(long long)(1LL << myind)); |
||||
|
if ( (len= dpow_rwutxobuf(1,utxodata,&bp->hashmsg,&bp->notaries[myind])) > 0 ) |
||||
|
dpow_send(myinfo,bp,srchash,bp->hashmsg,channel,bp->height,utxodata,len,bp->utxocrcs); |
||||
|
} |
||||
|
flag = 1; |
||||
|
} |
||||
|
} else printf("%s pubkey mismatch for senderind.%d %llx vs %llx\n",bp->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",bp->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(" SIG.%d sender.%d lastk.%d mask.%llx siglen.%d recv.%llx\n",height,dsig.senderind,dsig.lastk,(long long)dsig.mask,dsig.siglen,(long long)bp->recvmask); |
||||
|
} |
||||
|
else if ( channel == DPOW_TXIDCHANNEL || channel == DPOW_BTCTXIDCHANNEL ) |
||||
|
{ |
||||
|
if ( bp != 0 || (bp= dpow_heightfind(myinfo,height,channel == DPOW_BTCTXIDCHANNEL)) != 0 ) |
||||
|
{ |
||||
|
if ( bp->state != 0xffffffff ) |
||||
|
{ |
||||
|
for (i=0; i<32; i++) |
||||
|
srchash.bytes[i] = data[i]; |
||||
|
/*if ( srchash.ulongs[0] == 0 )
|
||||
|
{ |
||||
|
init_hexbytes_noT(bp->rawtx,&data[32],datalen-32); |
||||
|
//printf("got bestk.%d %llx rawtx.(%s) set utxo\n",srchash.bytes[31],(long long)srchash.ulongs[1],bp->rawtx);
|
||||
|
dpow_rawtxsign(myinfo,bp->coin,bp,bp->rawtx,0,srchash.bytes[31],srchash.ulongs[1],myind,bits256_nonz(bp->btctxid) == 0 ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL); |
||||
|
} |
||||
|
else*/ |
||||
|
{ |
||||
|
txid = bits256_doublesha256(0,&data[32],datalen-32); |
||||
|
init_hexbytes_noT(bp->signedtx,&data[32],datalen-32); |
||||
|
if ( bits256_cmp(txid,srchash) == 0 ) |
||||
|
{ |
||||
|
printf("verify (%s) it is properly signed! set ht.%d signedtxid to %s\n",bp->coin->symbol,height,bits256_str(str,txid)); |
||||
|
bp->signedtxid = txid; |
||||
|
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("txidchannel cant find bp for %d\n",height); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_update(struct supernet_info *myinfo,struct dpow_block *bp,uint32_t channel,uint32_t sigchannel,uint32_t txidchannel,bits256 srchash,int32_t myind) |
||||
|
{ |
||||
|
struct dpow_entry *ep; |
||||
|
ep = &bp->notaries[myind]; |
||||
|
//dpow_channelget(myinfo,bp,channel);
|
||||
|
if ( (bp->bestk= dpow_bestk(bp,&bp->bestmask)) >= 0 ) |
||||
|
{ |
||||
|
if ( ep->masks[bp->bestk] == 0 ) |
||||
|
dpow_signedtxgen(myinfo,bp->coin,bp,bp->bestk,bp->bestmask,myind,bp->opret_symbol,sigchannel); |
||||
|
else dpow_sigsend(myinfo,bp,myind,bp->bestk,bp->bestmask,srchash,sigchannel); |
||||
|
|
||||
|
} |
||||
|
//dpow_channelget(myinfo,bp,txidchannel);
|
||||
|
if ( bp->state != 0xffffffff ) |
||||
|
{ |
||||
|
//dpow_channelget(myinfo,bp,sigchannel);
|
||||
|
if ( ep->masks[bp->bestk] == 0 ) |
||||
|
dpow_signedtxgen(myinfo,bp->coin,bp,bp->bestk,bp->bestmask,myind,bp->opret_symbol,sigchannel); |
||||
|
else dpow_sigsend(myinfo,bp,myind,bp->bestk,bp->bestmask,srchash,sigchannel); |
||||
|
} |
||||
|
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) |
||||
|
{ |
||||
|
// todo: add RBF support
|
||||
|
int32_t j,match,sigmatch,len,vout,incr,haveutxo = 0; cJSON *addresses; char *sendtx,*rawtx,*opret_symbol,coinaddr[64]; uint32_t channel,sigchannel,txidchannel; bits256 txid,srchash,zero; uint8_t data[4096]; int8_t lastk; uint64_t sigsmask; |
||||
|
if ( bp->numnotaries > 8 ) |
||||
|
incr = sqrt(bp->numnotaries) + 1; |
||||
|
else incr = 1; |
||||
|
memset(zero.bytes,0,sizeof(zero)); |
||||
|
if ( bits256_nonz(bp->btctxid) == 0 ) |
||||
|
{ |
||||
|
channel = DPOW_UTXOBTCCHANNEL; |
||||
|
sigchannel = DPOW_SIGBTCCHANNEL; |
||||
|
txidchannel = DPOW_BTCTXIDCHANNEL; |
||||
|
opret_symbol = ""; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
channel = DPOW_UTXOCHANNEL; |
||||
|
sigchannel = DPOW_SIGCHANNEL; |
||||
|
txidchannel = DPOW_TXIDCHANNEL; |
||||
|
opret_symbol = dp->symbol; |
||||
|
} |
||||
|
bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->DPOW.minerkey33,33); |
||||
|
if ( bits256_nonz(bp->hashmsg) == 0 ) |
||||
|
return(0xffffffff); |
||||
|
for (j=0; j<sizeof(srchash); j++) |
||||
|
srchash.bytes[j] = myinfo->DPOW.minerkey33[j+1]; |
||||
|
if ( bits256_nonz(bp->signedtxid) != 0 ) |
||||
|
bp->state = 0xffffffff; |
||||
|
sigsmask = match = sigmatch = 0; |
||||
|
if ( (bp->bestk= dpow_bestk(bp,&bp->bestmask)) >= 0 ) |
||||
|
{ |
||||
|
for (j=0; j<bp->numnotaries; j++) |
||||
|
{ |
||||
|
if ( bp->notaries[j].masks[bp->bestk] == bp->bestmask ) |
||||
|
{ |
||||
|
match++; |
||||
|
if ( bp->notaries[j].siglens[bp->bestk] > 0 ) |
||||
|
{ |
||||
|
sigmatch++; |
||||
|
sigsmask |= (1LL << j); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if ( (rand() % 10) == 0 ) |
||||
|
printf("%s ht.%d FSM.%d %s BTC.%d masks.%llx best.(%d %llx) match.(%d sigs.%d) sigsmask.%llx\n",coin->symbol,bp->height,bp->state,coinaddr,bits256_nonz(bp->btctxid)==0,(long long)bp->recvmask,bp->bestk,(long long)bp->bestmask,match,sigmatch,(long long)sigsmask); |
||||
|
if ( sigmatch == DPOW_M(bp) ) |
||||
|
{ |
||||
|
printf("sigmatch.%d\n",sigmatch); |
||||
|
dpow_sigscheck(myinfo,bp,sigchannel,myind); |
||||
|
} |
||||
|
switch ( bp->state ) |
||||
|
{ |
||||
|
case 0: |
||||
|
if ( (haveutxo= dpow_haveutxo(myinfo,coin,&txid,&vout,coinaddr)) != 0 && bits256_nonz(txid) != 0 ) |
||||
|
{ |
||||
|
bp->notaries[myind].prev_hash = txid; |
||||
|
bp->notaries[myind].prev_vout = vout; |
||||
|
bp->state = 1; |
||||
|
} |
||||
|
if ( haveutxo < 10 && time(NULL) > dp->lastsplit+600 ) |
||||
|
{ |
||||
|
addresses = cJSON_CreateArray(); |
||||
|
jaddistr(addresses,coinaddr); |
||||
|
if ( (rawtx= iguana_utxoduplicates(myinfo,coin,myinfo->DPOW.minerkey33,DPOW_UTXOSIZE,10,&bp->completed,&bp->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); |
||||
|
} |
||||
|
break; |
||||
|
case 1: |
||||
|
dpow_lastk_mask(bp,&lastk); |
||||
|
if ( (len= dpow_rwutxobuf(1,data,&bp->hashmsg,&bp->notaries[myind])) > 0 ) |
||||
|
dpow_send(myinfo,bp,srchash,bp->hashmsg,channel,bp->height,data,len,bp->utxocrcs); |
||||
|
bp->recvmask |= (1LL << myind); |
||||
|
bp->state = 2; |
||||
|
break; |
||||
|
default: |
||||
|
dpow_update(myinfo,bp,channel,sigchannel,txidchannel,srchash,myind); |
||||
|
break; |
||||
|
} |
||||
|
if ( bits256_nonz(bp->signedtxid) != 0 ) |
||||
|
{ |
||||
|
bp->state = 0xffffffff; |
||||
|
} |
||||
|
return(bp->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; struct iguana_info *src,*dest; char str[65],coinaddr[64]; bits256 zero; struct dpow_block *srcbp,*destbp,*bp; uint32_t starttime = (uint32_t)time(NULL); |
||||
|
memset(&zero,0,sizeof(zero)); |
||||
|
myinfo = ptrs[0]; |
||||
|
dp = ptrs[1]; |
||||
|
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); |
||||
|
src = iguana_coinfind(dp->symbol); |
||||
|
dest = iguana_coinfind(dp->dest); |
||||
|
if ( (destbp= dp->destblocks[checkpoint.blockhash.height]) == 0 ) |
||||
|
{ |
||||
|
destbp = calloc(1,sizeof(*destbp)); |
||||
|
destbp->coin = iguana_coinfind(dp->dest); |
||||
|
destbp->opret_symbol = dp->symbol; |
||||
|
destbp->bestk = -1; |
||||
|
dp->destblocks[checkpoint.blockhash.height] = destbp; |
||||
|
destbp->beacon = rand256(0); |
||||
|
vcalc_sha256(0,destbp->commit.bytes,destbp->beacon.bytes,sizeof(destbp->beacon)); |
||||
|
if ( (bp= dp->destblocks[checkpoint.blockhash.height - 100]) != 0 ) |
||||
|
{ |
||||
|
printf("purge %s.%d\n",dp->dest,checkpoint.blockhash.height - 100); |
||||
|
dp->destblocks[checkpoint.blockhash.height - 100] = 0; |
||||
|
free(bp); |
||||
|
} |
||||
|
} |
||||
|
if ( (srcbp= dp->srcblocks[checkpoint.blockhash.height]) == 0 ) |
||||
|
{ |
||||
|
srcbp = calloc(1,sizeof(*srcbp)); |
||||
|
srcbp->coin = iguana_coinfind(dp->symbol); |
||||
|
srcbp->opret_symbol = dp->symbol; |
||||
|
srcbp->bestk = -1; |
||||
|
dp->srcblocks[checkpoint.blockhash.height] = srcbp; |
||||
|
srcbp->beacon = destbp->beacon; |
||||
|
srcbp->commit = destbp->commit; |
||||
|
printf("create srcbp[%d]\n",checkpoint.blockhash.height); |
||||
|
if ( (bp= dp->srcblocks[checkpoint.blockhash.height - 1000]) != 0 ) |
||||
|
{ |
||||
|
printf("purge %s.%d\n",dp->symbol,checkpoint.blockhash.height - 1000); |
||||
|
dp->srcblocks[checkpoint.blockhash.height - 1000] = 0; |
||||
|
free(bp); |
||||
|
} |
||||
|
} |
||||
|
n = (int32_t)(sizeof(Notaries)/sizeof(*Notaries)); |
||||
|
srcbp->numnotaries = destbp->numnotaries = n; |
||||
|
for (i=0; i<n; i++) |
||||
|
{ |
||||
|
decode_hex(srcbp->notaries[i].pubkey,33,Notaries[i][1]); |
||||
|
decode_hex(destbp->notaries[i].pubkey,33,Notaries[i][1]); |
||||
|
if ( memcmp(destbp->notaries[i].pubkey,myinfo->DPOW.minerkey33,33) == 0 ) |
||||
|
myind = i; |
||||
|
} |
||||
|
bitcoin_address(coinaddr,src->chain->pubtype,myinfo->DPOW.minerkey33,33); |
||||
|
printf(" myaddr.%s\n",coinaddr); |
||||
|
if ( myind < 0 ) |
||||
|
{ |
||||
|
printf("statemachinestart this node %s is not official notary\n",coinaddr); |
||||
|
free(ptr); |
||||
|
return; |
||||
|
} |
||||
|
dp->checkpoint = checkpoint; |
||||
|
srcbp->height = destbp->height = checkpoint.blockhash.height; |
||||
|
srcbp->timestamp = destbp->timestamp = checkpoint.timestamp; |
||||
|
srcbp->hashmsg = destbp->hashmsg = checkpoint.blockhash.hash; |
||||
|
printf("DPOW statemachine checkpoint.%d %s\n",checkpoint.blockhash.height,bits256_str(str,checkpoint.blockhash.hash)); |
||||
|
while ( time(NULL) < starttime+300 && src != 0 && dest != 0 && (srcbp->state != 0xffffffff || destbp->state != 0xffffffff) ) |
||||
|
{ |
||||
|
sleep(1); |
||||
|
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 ( destbp->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));
|
||||
|
destbp->state = dpow_statemachineiterate(myinfo,dp,dest,destbp,myind); |
||||
|
if ( destbp->state == 0xffffffff ) |
||||
|
{ |
||||
|
srcbp->btctxid = destbp->signedtxid; |
||||
|
printf("SET BTCTXID.(%s)\n",bits256_str(str,srcbp->btctxid)); |
||||
|
} |
||||
|
} |
||||
|
if ( destbp->state == 0xffffffff && bits256_nonz(srcbp->btctxid) != 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); |
||||
|
break; |
||||
|
} |
||||
|
if ( srcbp->state != 0xffffffff ) |
||||
|
{ |
||||
|
//printf("dp->ht.%d ht.%d SRC.%08x %s\n",dp->checkpoint.blockhash.height,checkpoint.blockhash.height,srcbp->state,bits256_str(str,srcbp->btctxid));
|
||||
|
srcbp->state = dpow_statemachineiterate(myinfo,dp,src,srcbp,myind); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
free(ptr); |
||||
|
} |
@ -0,0 +1,271 @@ |
|||||
|
/******************************************************************************
|
||||
|
* 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
|
||||
|
#if ISNOTARYNODE |
||||
|
|
||||
|
struct dpow_nanomsghdr |
||||
|
{ |
||||
|
bits256 srchash,desthash; |
||||
|
uint32_t channel,height,size,datalen,crc32; |
||||
|
uint8_t packet[]; |
||||
|
}; |
||||
|
|
||||
|
char *nanomsg_tcpname(char *str,char *ipaddr) |
||||
|
{ |
||||
|
sprintf(str,"tcp://%s:7775",ipaddr); |
||||
|
return(str); |
||||
|
} |
||||
|
|
||||
|
void dpow_nanomsginit(struct supernet_info *myinfo,char *ipaddr) |
||||
|
{ |
||||
|
char str[512]; int32_t timeout,retval; |
||||
|
if ( myinfo->ipaddr[0] == 0 ) |
||||
|
{ |
||||
|
printf("need to set ipaddr before nanomsg\n"); |
||||
|
return; |
||||
|
} |
||||
|
if ( myinfo->DPOW.sock < 0 && (myinfo->DPOW.sock= nn_socket(AF_SP,NN_BUS)) >= 0 ) |
||||
|
{ |
||||
|
if ( nn_bind(myinfo->DPOW.sock,nanomsg_tcpname(str,myinfo->ipaddr)) < 0 ) |
||||
|
{ |
||||
|
printf("error binding to (%s)\n",nanomsg_tcpname(str,myinfo->ipaddr)); |
||||
|
nn_close(myinfo->DPOW.sock); |
||||
|
myinfo->DPOW.sock = -1; |
||||
|
} |
||||
|
timeout = 100; |
||||
|
nn_setsockopt(myinfo->DPOW.sock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); |
||||
|
} |
||||
|
if ( myinfo->DPOW.sock >= 0 && strcmp(ipaddr,myinfo->ipaddr) != 0 ) |
||||
|
{ |
||||
|
retval = nn_connect(myinfo->DPOW.sock,nanomsg_tcpname(str,ipaddr)); |
||||
|
printf("addnotary (%s) retval.%d\n",ipaddr,retval); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_crc32find(struct supernet_info *myinfo,uint32_t crc32) |
||||
|
{ |
||||
|
int32_t i,firstz = -1; |
||||
|
for (i=0; i<sizeof(myinfo->DPOW.crcs)/sizeof(*myinfo->DPOW.crcs); i++) |
||||
|
{ |
||||
|
if ( myinfo->DPOW.crcs[i] == crc32 ) |
||||
|
{ |
||||
|
printf("NANODUPLICATE.%08x\n",crc32); |
||||
|
return(-1); |
||||
|
} |
||||
|
else if ( myinfo->DPOW.crcs[i] == 0 ) |
||||
|
firstz = i; |
||||
|
} |
||||
|
if ( firstz < 0 ) |
||||
|
firstz = (rand() % (sizeof(myinfo->DPOW.crcs)/sizeof(*myinfo->DPOW.crcs))); |
||||
|
return(firstz); |
||||
|
} |
||||
|
|
||||
|
void dpow_send(struct supernet_info *myinfo,struct dpow_block *bp,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t crcs[2]) |
||||
|
{ |
||||
|
struct dpow_nanomsghdr *np; int32_t size,firstz,sentbytes = 0; uint32_t crc32; |
||||
|
crc32 = calc_crc32(0,data,datalen); |
||||
|
if ( (firstz= dpow_crc32find(myinfo,crc32)) >= 0 ) |
||||
|
{ |
||||
|
myinfo->DPOW.crcs[firstz] = crc32; |
||||
|
size = (int32_t)(sizeof(*np) + datalen); |
||||
|
np = malloc(size); |
||||
|
np->size = size; |
||||
|
np->datalen = datalen; |
||||
|
np->crc32 = crc32; |
||||
|
np->srchash = srchash; |
||||
|
np->desthash = desthash; |
||||
|
np->channel = channel; |
||||
|
np->height = msgbits; |
||||
|
memcpy(np->packet,data,datalen); |
||||
|
sentbytes = nn_send(myinfo->DPOW.sock,np,size,0); |
||||
|
free(np); |
||||
|
printf("NANOSEND ht.%d channel.%08x (%d) crc32.%08x\n",np->height,np->channel,size,np->crc32); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void dpow_nanomsg_update(struct supernet_info *myinfo) |
||||
|
{ |
||||
|
int32_t size,firstz = -1; uint32_t crc32; struct dpow_nanomsghdr *np; |
||||
|
while ( (size= nn_recv(myinfo->DPOW.sock,&np,NN_MSG,0)) >= 0 ) |
||||
|
{ |
||||
|
if ( size >= 0 ) |
||||
|
{ |
||||
|
crc32 = calc_crc32(0,np->packet,np->datalen); |
||||
|
if ( crc32 == np->crc32 && np->datalen == (size - sizeof(*np)) ) |
||||
|
{ |
||||
|
if ( (firstz= dpow_crc32find(myinfo,crc32)) >= 0 ) |
||||
|
{ |
||||
|
myinfo->DPOW.crcs[firstz] = crc32; |
||||
|
printf("NANORECV ht.%d channel.%08x (%d) crc32.%08x:%08x datalen.%d:%d\n",np->height,np->channel,size,np->crc32,crc32,np->datalen,(int32_t)(size - sizeof(*np))); |
||||
|
dpow_datahandler(myinfo,0,np->channel,np->height,np->packet,size - np->size); |
||||
|
} |
||||
|
} |
||||
|
if ( np != 0 ) |
||||
|
nn_freemsg(np); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
#else |
||||
|
|
||||
|
void dpow_nanomsginit(struct supernet_info *myinfo,char *ipaddr) { } |
||||
|
|
||||
|
uint32_t dpow_send(struct supernet_info *myinfo,struct dpow_block *bp,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t crcs[2]) |
||||
|
{ |
||||
|
return(0); |
||||
|
} |
||||
|
|
||||
|
void dpow_nanomsg_update(struct supernet_info *myinfo) { } |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
int32_t dpow_opreturnscript(uint8_t *script,uint8_t *opret,int32_t opretlen) |
||||
|
{ |
||||
|
int32_t offset = 0; |
||||
|
script[offset++] = 0x6a; |
||||
|
if ( opretlen >= 0x4c ) |
||||
|
{ |
||||
|
if ( opretlen > 0xff ) |
||||
|
{ |
||||
|
script[offset++] = 0x4d; |
||||
|
script[offset++] = opretlen & 0xff; |
||||
|
script[offset++] = (opretlen >> 8) & 0xff; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
script[offset++] = 0x4c; |
||||
|
script[offset++] = opretlen; |
||||
|
} |
||||
|
} else script[offset++] = opretlen; |
||||
|
memcpy(&script[offset],opret,opretlen); |
||||
|
return(opretlen + offset); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_rwopret(int32_t rwflag,uint8_t *opret,bits256 *hashmsg,int32_t *heightmsgp,bits256 *btctxid,char *src) |
||||
|
{ |
||||
|
int32_t i,opretlen = 0; |
||||
|
opretlen += iguana_rwbignum(rwflag,&opret[opretlen],sizeof(*hashmsg),hashmsg->bytes); |
||||
|
opretlen += iguana_rwnum(rwflag,&opret[opretlen],sizeof(*heightmsgp),(uint32_t *)heightmsgp); |
||||
|
if ( bits256_nonz(*btctxid) != 0 ) |
||||
|
{ |
||||
|
opretlen += iguana_rwbignum(rwflag,&opret[opretlen],sizeof(*btctxid),btctxid->bytes); |
||||
|
if ( rwflag != 0 ) |
||||
|
{ |
||||
|
for (i=0; src[i]!=0; i++) |
||||
|
opret[opretlen++] = src[i]; |
||||
|
opret[opretlen++] = 0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
for (i=0; opret[opretlen]!=0; i++) |
||||
|
src[i] = opret[opretlen++]; |
||||
|
src[i] = 0; |
||||
|
opretlen++; |
||||
|
} |
||||
|
} |
||||
|
return(opretlen); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_rwutxobuf(int32_t rwflag,uint8_t *data,bits256 *hashmsg,struct dpow_entry *ep) |
||||
|
{ |
||||
|
int32_t i,len = 0; |
||||
|
if ( rwflag != 0 ) |
||||
|
{ |
||||
|
data[0] = DPOW_VERSION & 0xff; |
||||
|
data[1] = (DPOW_VERSION >> 8) & 0xff; |
||||
|
} |
||||
|
else if ( (data[0]+((int32_t)data[1]<<8)) != DPOW_VERSION ) |
||||
|
return(-1); |
||||
|
len = 2; |
||||
|
len += iguana_rwbignum(rwflag,&data[len],sizeof(*hashmsg),hashmsg->bytes); |
||||
|
len += iguana_rwbignum(rwflag,&data[len],sizeof(ep->prev_hash),ep->prev_hash.bytes); |
||||
|
if ( bits256_nonz(ep->prev_hash) == 0 ) |
||||
|
return(-1); |
||||
|
len += iguana_rwbignum(rwflag,&data[len],sizeof(ep->commit),ep->commit.bytes); |
||||
|
if ( rwflag != 0 ) |
||||
|
{ |
||||
|
data[len++] = ep->prev_vout; |
||||
|
for (i=0; i<33; i++) |
||||
|
data[len++] = ep->pubkey[i]; |
||||
|
data[len++] = ep->bestk; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
ep->prev_vout = data[len++]; |
||||
|
for (i=0; i<33; i++) |
||||
|
ep->pubkey[i] = data[len++]; |
||||
|
ep->bestk = data[len++]; |
||||
|
} |
||||
|
len += iguana_rwbignum(rwflag,&data[len],sizeof(ep->recvmask),(uint8_t *)&ep->recvmask); |
||||
|
return(len); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_rwsigentry(int32_t rwflag,uint8_t *data,struct dpow_sigentry *dsig) |
||||
|
{ |
||||
|
int32_t i,len = 0; |
||||
|
if ( rwflag != 0 ) |
||||
|
{ |
||||
|
data[len++] = DPOW_VERSION & 0xff; |
||||
|
data[len++] = (DPOW_VERSION >> 8) & 0xff; |
||||
|
data[len++] = dsig->senderind; |
||||
|
data[len++] = dsig->lastk; |
||||
|
len += iguana_rwnum(rwflag,&data[len],sizeof(dsig->mask),(uint8_t *)&dsig->mask); |
||||
|
data[len++] = dsig->siglen; |
||||
|
memcpy(&data[len],dsig->sig,dsig->siglen), len += dsig->siglen; |
||||
|
for (i=0; i<sizeof(dsig->beacon); i++) |
||||
|
data[len++] = dsig->beacon.bytes[i]; |
||||
|
for (i=0; i<33; i++) |
||||
|
data[len++] = dsig->senderpub[i]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if ( (data[0]+((int32_t)data[1]<<8)) != DPOW_VERSION ) |
||||
|
return(-1); |
||||
|
len = 2; |
||||
|
memset(dsig,0,sizeof(*dsig)); |
||||
|
dsig->senderind = data[len++]; |
||||
|
if ( dsig->senderind < 0 || dsig->senderind >= DPOW_MAXRELAYS ) |
||||
|
return(-1); |
||||
|
dsig->lastk = data[len++]; |
||||
|
len += iguana_rwnum(rwflag,&data[len],sizeof(dsig->mask),(uint8_t *)&dsig->mask); |
||||
|
dsig->siglen = data[len++]; |
||||
|
memcpy(dsig->sig,&data[len],dsig->siglen), len += dsig->siglen; |
||||
|
for (i=0; i<sizeof(dsig->beacon); i++) |
||||
|
dsig->beacon.bytes[i] = data[len++]; |
||||
|
for (i=0; i<33; i++) |
||||
|
dsig->senderpub[i] = data[len++]; |
||||
|
} |
||||
|
return(len); |
||||
|
} |
||||
|
|
||||
|
void dpow_sigsend(struct supernet_info *myinfo,struct dpow_block *bp,int32_t myind,int8_t bestk,uint64_t bestmask,bits256 srchash,uint32_t sigchannel) |
||||
|
{ |
||||
|
struct dpow_sigentry dsig; int32_t i,len; uint8_t data[4096]; struct dpow_entry *ep; |
||||
|
ep = &bp->notaries[myind]; |
||||
|
//printf("myind.%d bestk.%d %llx\n",myind,bestk,(long long)bestmask);
|
||||
|
memset(&dsig,0,sizeof(dsig)); |
||||
|
for (i=0; i<33; i++) |
||||
|
dsig.senderpub[i] = myinfo->DPOW.minerkey33[i]; |
||||
|
dsig.lastk = bestk; |
||||
|
dsig.mask = bestmask; |
||||
|
dsig.senderind = myind; |
||||
|
dsig.beacon = bp->beacon; |
||||
|
dsig.siglen = ep->siglens[bestk]; |
||||
|
memcpy(dsig.sig,ep->sigs[bestk],ep->siglens[bestk]); |
||||
|
memcpy(dsig.senderpub,myinfo->DPOW.minerkey33,33); |
||||
|
len = dpow_rwsigentry(1,data,&dsig); |
||||
|
dpow_send(myinfo,bp,srchash,bp->hashmsg,sigchannel,bp->height,data,len,bp->sigcrcs); |
||||
|
} |
@ -0,0 +1,312 @@ |
|||||
|
/******************************************************************************
|
||||
|
* 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
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("%s getbestblockhash.(%s)\n",coin->symbol,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("%s getblock.(%s)\n",coin->symbol,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); |
||||
|
} |
||||
|
|
||||
|
char *dpow_decoderawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx) |
||||
|
{ |
||||
|
char *retstr,*paramstr; cJSON *array; |
||||
|
if ( coin->FULLNODE < 0 ) |
||||
|
{ |
||||
|
array = cJSON_CreateArray(); |
||||
|
jaddistr(array,rawtx); |
||||
|
paramstr = jprint(array,1); |
||||
|
retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"decoderawtransaction",paramstr); |
||||
|
//printf("%s decoderawtransaction.(%s) <- (%s)\n",coin->symbol,retstr,paramstr);
|
||||
|
free(paramstr); |
||||
|
} |
||||
|
else if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 ) |
||||
|
{ |
||||
|
retstr = bitcoinrpc_decoderawtransaction(myinfo,coin,0,0,rawtx,1); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return(0); |
||||
|
} |
||||
|
return(retstr); |
||||
|
} |
||||
|
|
||||
|
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 = dpow_decoderawtransaction(myinfo,coin,rawtx); |
||||
|
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,"0, 99999999, [\"%s\"]",coinaddr); |
||||
|
if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",buf)) != 0 ) |
||||
|
{ |
||||
|
json = cJSON_Parse(retstr); |
||||
|
//printf("%s (%s) listunspent.(%s)\n",coin->symbol,buf,retstr);
|
||||
|
free(retstr); |
||||
|
} else printf("%s null retstr from (%s)n",coin->symbol,buf); |
||||
|
} |
||||
|
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("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,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<n; i++) |
||||
|
{ |
||||
|
wifstr = ""; |
||||
|
item = jitem(vins,i); |
||||
|
if ( (str= jstr(item,"scriptPubkey")) != 0 && is_hexstr(str,0) > 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,*array; char *paramstr,*retstr; |
||||
|
if ( coin->FULLNODE < 0 ) |
||||
|
{ |
||||
|
array = cJSON_CreateArray(); |
||||
|
jaddistr(array,signedtx); |
||||
|
paramstr = jprint(array,1); |
||||
|
retstr = bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"sendrawtransaction",paramstr); |
||||
|
printf(">>>>>>>>>>> %s sendrawtransaction.(%s) -> %s\n",coin->symbol,paramstr,retstr); |
||||
|
free(paramstr); |
||||
|
return(retstr); |
||||
|
} |
||||
|
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_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; |
||||
|
*blockhashp = 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; i<n&&i<maxtx; i++) |
||||
|
txs[i] = jbits256i(array,i); |
||||
|
//printf("dpow_getchaintip %s ht.%d time.%u numtx.%d\n",coin->symbol,height,*blocktimep,n);
|
||||
|
*numtxp = n; |
||||
|
} |
||||
|
} else height = -1; |
||||
|
free_json(json); |
||||
|
} |
||||
|
} |
||||
|
return(height); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_vini_ismine(struct supernet_info *myinfo,cJSON *item) |
||||
|
{ |
||||
|
cJSON *sobj; char *hexstr; int32_t len; uint8_t data[35]; |
||||
|
if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 ) |
||||
|
{ |
||||
|
len = (int32_t)strlen(hexstr) >> 1; |
||||
|
if ( len <= sizeof(data) ) |
||||
|
{ |
||||
|
decode_hex(data,len,hexstr); |
||||
|
if ( len == 35 && data[34] == CHECKSIG && data[0] == 33 && memcmp(data+1,myinfo->DPOW.minerkey33,33) == 0 ) |
||||
|
return(0); |
||||
|
} |
||||
|
} |
||||
|
return(-1); |
||||
|
} |
||||
|
|
||||
|
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,*address; 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; i<n; i++) |
||||
|
{ |
||||
|
item = jitem(unspents,i); |
||||
|
satoshis = SATOSHIDEN * jdouble(item,"amount"); |
||||
|
if ( satoshis == DPOW_UTXOSIZE && (address= jstr(item,"address")) != 0 && strcmp(address,coinaddr) == 0 ) |
||||
|
{ |
||||
|
if ( (str= jstr(item,"scriptPubKey")) != 0 && is_hexstr(str,0) == sizeof(script)*2 ) |
||||
|
{ |
||||
|
txid = jbits256(item,"txid"); |
||||
|
vout = jint(item,"vout"); |
||||
|
if ( bits256_nonz(txid) != 0 && vout >= 0 ) |
||||
|
{ |
||||
|
if ( *voutp < 0 ) |
||||
|
{ |
||||
|
*voutp = vout; |
||||
|
*txidp = txid; |
||||
|
} |
||||
|
haveutxo++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if ( haveutxo == 0 ) |
||||
|
printf("no utxo: need to fund address.(%s) or wait for splitfund to confirm\n",coinaddr); |
||||
|
} else printf("null utxo array size\n"); |
||||
|
free_json(unspents); |
||||
|
} else printf("null return from dpow_listunspent\n"); |
||||
|
if ( haveutxo > 0 ) |
||||
|
printf("%s haveutxo.%d\n",coin->symbol,haveutxo); |
||||
|
return(haveutxo); |
||||
|
} |
@ -0,0 +1,368 @@ |
|||||
|
/******************************************************************************
|
||||
|
* 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. * |
||||
|
* * |
||||
|
******************************************************************************/ |
||||
|
|
||||
|
uint64_t dpow_lastk_mask(struct dpow_block *bp,int8_t *lastkp) |
||||
|
{ |
||||
|
int32_t j,m,k; uint64_t mask = 0; |
||||
|
*lastkp = -1; |
||||
|
for (j=m=0; j<bp->numnotaries; j++) |
||||
|
{ |
||||
|
k = ((bp->height % bp->numnotaries) + j) % bp->numnotaries; |
||||
|
if ( bits256_nonz(bp->notaries[k].prev_hash) != 0 ) |
||||
|
{ |
||||
|
bp->recvmask |= (1LL << k); |
||||
|
mask |= (1LL << k); |
||||
|
if ( ++m >= DPOW_M(bp) ) |
||||
|
{ |
||||
|
*lastkp = k; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return(mask); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_bestk(struct dpow_block *bp,uint64_t *maskp) |
||||
|
{ |
||||
|
int8_t lastk; uint64_t mask; |
||||
|
*maskp = 0; |
||||
|
mask = dpow_lastk_mask(bp,&lastk); |
||||
|
if ( lastk < 0 ) |
||||
|
return(-1); |
||||
|
*maskp = mask; |
||||
|
return(lastk); |
||||
|
} |
||||
|
|
||||
|
uint64_t dpow_maskmin(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp) |
||||
|
{ |
||||
|
int32_t j,m,k; uint64_t mask = 0; |
||||
|
for (j=m=0; j<bp->numnotaries; j++) |
||||
|
{ |
||||
|
k = ((bp->height % bp->numnotaries) + j) % bp->numnotaries; |
||||
|
if ( bits256_nonz(bp->notaries[k].prev_hash) != 0 ) |
||||
|
{ |
||||
|
mask |= (1LL << k); |
||||
|
if ( ++m >= DPOW_M(bp) ) |
||||
|
{ |
||||
|
*lastkp = k; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return(mask); |
||||
|
} |
||||
|
|
||||
|
struct dpow_block *dpow_heightfind(struct supernet_info *myinfo,int32_t height,int32_t destflag) |
||||
|
{ |
||||
|
if ( destflag != 0 ) |
||||
|
return(myinfo->DPOW.destblocks!=0?myinfo->DPOW.destblocks[height]:0); |
||||
|
else return(myinfo->DPOW.srcblocks!=0?myinfo->DPOW.srcblocks[height]:0); |
||||
|
} |
||||
|
|
||||
|
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 ) |
||||
|
{ |
||||
|
*senderindp = i; |
||||
|
return(&bp->notaries[i]); |
||||
|
} |
||||
|
} |
||||
|
return(0); |
||||
|
} |
||||
|
|
||||
|
bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,char *src) |
||||
|
{ |
||||
|
uint32_t i,j,m,numsigs,locktime,numvouts,version,opretlen,siglen,len,sequenceid = 0xffffffff; |
||||
|
uint64_t satoshis,satoshisB; uint8_t serialized[32768],opret[1024],data[4096]; |
||||
|
len = locktime = numsigs = 0; |
||||
|
version = 1; |
||||
|
len += iguana_rwnum(1,&serialized[len],sizeof(version),&version); |
||||
|
if ( isPoS != 0 ) |
||||
|
len += iguana_rwnum(1,&serialized[len],sizeof(bp->timestamp),&bp->timestamp); |
||||
|
m = DPOW_M(bp); |
||||
|
len += iguana_rwvarint32(1,&serialized[len],(uint32_t *)&m); |
||||
|
for (j=m=0; j<bp->numnotaries; j++) |
||||
|
{ |
||||
|
i = ((bp->height % bp->numnotaries) + j) % bp->numnotaries; |
||||
|
if ( ((1LL << i) & bestmask) != 0 ) |
||||
|
{ |
||||
|
if ( bits256_nonz(bp->notaries[i].prev_hash) == 0 ) |
||||
|
return(bp->notaries[i].prev_hash); |
||||
|
len += iguana_rwbignum(1,&serialized[len],sizeof(bp->notaries[i].prev_hash),bp->notaries[i].prev_hash.bytes); |
||||
|
len += iguana_rwnum(1,&serialized[len],sizeof(bp->notaries[i].prev_vout),&bp->notaries[i].prev_vout); |
||||
|
siglen = bp->notaries[i].siglens[bestk]; |
||||
|
len += iguana_rwvarint32(1,&serialized[len],&siglen); |
||||
|
if ( siglen > 0 && siglen <= sizeof(bp->notaries[i].sigs[bestk]) ) |
||||
|
{ |
||||
|
memcpy(&serialized[len],bp->notaries[i].sigs[bestk],siglen); |
||||
|
len += siglen; |
||||
|
numsigs++; |
||||
|
} |
||||
|
len += iguana_rwnum(1,&serialized[len],sizeof(sequenceid),&sequenceid); |
||||
|
//printf("height.%d mod.%d VINI.%d <- i.%d j.%d\n",height,height % numnotaries,m,i,j);
|
||||
|
m++; |
||||
|
if ( m == DPOW_M(bp) && i == bestk ) |
||||
|
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); |
||||
|
opretlen = dpow_rwopret(1,opret,&bp->hashmsg,&bp->height,&bp->btctxid,src); |
||||
|
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); |
||||
|
init_hexbytes_noT(signedtx,serialized,len); |
||||
|
//printf("notarytx.(%s) opretlen.%d\n",signedtx,opretlen);
|
||||
|
*numsigsp = numsigs; |
||||
|
return(bits256_doublesha256(0,serialized,len)); |
||||
|
} |
||||
|
|
||||
|
cJSON *dpow_createtx(struct iguana_info *coin,cJSON **vinsp,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t usesigs) |
||||
|
{ |
||||
|
int32_t i,j,m=0,siglen; char scriptstr[256]; cJSON *txobj=0,*vins=0,*item; uint64_t satoshis; uint8_t script[35],*sig; |
||||
|
if ( (txobj= bitcoin_txcreate(coin->chain->isPoS,0,1,0)) != 0 ) |
||||
|
{ |
||||
|
jaddnum(txobj,"suppress",1); |
||||
|
jaddnum(txobj,"timestamp",bp->timestamp); |
||||
|
vins = cJSON_CreateArray(); |
||||
|
for (j=0; j<bp->numnotaries; j++) |
||||
|
{ |
||||
|
i = ((bp->height % bp->numnotaries) + j) % bp->numnotaries; |
||||
|
if ( ((1LL << i) & bestmask) != 0 ) |
||||
|
{ |
||||
|
if ( bits256_nonz(bp->notaries[i].prev_hash) != 0 ) |
||||
|
{ |
||||
|
item = cJSON_CreateObject(); |
||||
|
jaddbits256(item,"txid",bp->notaries[i].prev_hash); |
||||
|
jaddnum(item,"vout",bp->notaries[i].prev_vout); |
||||
|
script[0] = 33; |
||||
|
memcpy(script+1,bp->notaries[i].pubkey,33); |
||||
|
script[34] = CHECKSIG; |
||||
|
init_hexbytes_noT(scriptstr,script,35); |
||||
|
jaddstr(item,"scriptPubKey",scriptstr); |
||||
|
sig = 0, siglen = 0; |
||||
|
if ( usesigs != 0 && bp->notaries[i].siglens[bestk] > 0 ) |
||||
|
{ |
||||
|
init_hexbytes_noT(scriptstr,bp->notaries[i].sigs[bestk],bp->notaries[i].siglens[bestk]); |
||||
|
jaddstr(item,"scriptSig",scriptstr); |
||||
|
//printf("sig%d.(%s)\n",i,scriptstr);
|
||||
|
sig = bp->notaries[i].sigs[bestk]; |
||||
|
siglen = bp->notaries[i].siglens[bestk]; |
||||
|
} |
||||
|
jaddi(vins,item); |
||||
|
bitcoin_txinput(coin,txobj,bp->notaries[i].prev_hash,bp->notaries[i].prev_vout,0xffffffff,script,sizeof(script),0,0,0,0,sig,siglen); |
||||
|
//printf("height.%d mod.%d VINI.%d <- i.%d j.%d\n",height,height % numnotaries,m,i,j);
|
||||
|
m++; |
||||
|
if ( m == DPOW_M(bp) && i == bestk ) |
||||
|
break; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
free_json(vins), vins = 0; |
||||
|
free_json(txobj); |
||||
|
return(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
satoshis = DPOW_UTXOSIZE * m * .76; |
||||
|
script[0] = 33; |
||||
|
decode_hex(script+1,33,CRYPTO777_PUBSECPSTR); |
||||
|
script[34] = CHECKSIG; |
||||
|
txobj = bitcoin_txoutput(txobj,script,sizeof(script),satoshis); |
||||
|
} |
||||
|
*vinsp = vins; |
||||
|
if ( 0 && usesigs != 0 ) |
||||
|
printf("%s createtx.(%s)\n",coin->symbol,jprint(txobj,0)); |
||||
|
return(txobj); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void dpow_rawtxsign(struct supernet_info *myinfo,struct iguana_info *coin,struct dpow_block *bp,char *rawtx,cJSON *vins,int8_t bestk,uint64_t bestmask,int32_t myind,uint32_t sigchannel) |
||||
|
{ |
||||
|
int32_t j,m=0,flag=0,retval=-1; char *jsonstr,*signedtx,*rawtx2,*sigstr; cJSON *signobj,*sobj,*txobj2,*item,*vin; bits256 srchash; struct dpow_entry *ep = &bp->notaries[myind]; |
||||
|
/*if ( vins == 0 && bitweight(bestmask) == DPOW_M(bp) )
|
||||
|
{ |
||||
|
if ( (rawtx2= dpow_decoderawtransaction(myinfo,coin,rawtx)) != 0 ) |
||||
|
{ |
||||
|
if ( (txobj= cJSON_Parse(rawtx2)) != 0 ) |
||||
|
{ |
||||
|
vins = jduplicate(jobj(txobj,"vin")); |
||||
|
free_json(txobj); |
||||
|
//printf("generated vins.(%s)\n",jprint(vins,0));
|
||||
|
} |
||||
|
free(rawtx2); |
||||
|
} |
||||
|
if ( vins != 0 ) |
||||
|
{ |
||||
|
flag = 1; |
||||
|
n = cJSON_GetArraySize(vins); |
||||
|
k = (bp->height % bp->numnotaries) % bp->numnotaries; |
||||
|
for (i=0; i<n; i++) |
||||
|
{ |
||||
|
while ( ((1LL << k) & bestmask) == 0 ) |
||||
|
if ( ++k >= bp->numnotaries ) |
||||
|
k = 0; |
||||
|
item = jitem(vins,i); |
||||
|
//printf("(%s) i.%d of %d, (%d) k.%d bestmask.%llx\n",jprint(item,0),i,n,(bp->height % bp->numnotaries) % bp->numnotaries,k,(long long)bestmask);
|
||||
|
if ( bits256_nonz(bp->notaries[k].prev_hash) == 0 ) |
||||
|
{ |
||||
|
bp->notaries[k].prev_hash = jbits256(item,"txid"); |
||||
|
if ( bits256_nonz(bp->notaries[k].prev_hash) != 0 ) |
||||
|
{ |
||||
|
bp->notaries[k].prev_vout = jint(item,"vout"); |
||||
|
bp->recvmask |= (1LL << k); |
||||
|
printf(">>>>>>>> rawtx utxo.%d %s/v%d %llx\n",k,bits256_str(str,bp->notaries[k].prev_hash),bp->notaries[k].prev_vout,(long long)bp->recvmask); |
||||
|
} |
||||
|
} |
||||
|
if ( i < n-1 ) |
||||
|
k++; |
||||
|
} |
||||
|
if ( k != bestk ) |
||||
|
printf("extracted uxto k.%d != bestk.%d %llx\n",k,bestk,(long long)bestmask); |
||||
|
} |
||||
|
}*/ |
||||
|
m = 0; |
||||
|
if ( (jsonstr= dpow_signrawtransaction(myinfo,coin,rawtx,vins)) != 0 ) |
||||
|
{ |
||||
|
printf("bestk.%d mask.%llx dpowsign.(%s)\n",bestk,(long long)bestmask,jsonstr); |
||||
|
if ( (signobj= cJSON_Parse(jsonstr)) != 0 ) |
||||
|
{ |
||||
|
if ( ((signedtx= jstr(signobj,"hex")) != 0 || (signedtx= jstr(signobj,"result")) != 0) && (rawtx2= dpow_decoderawtransaction(myinfo,coin,signedtx)) != 0 ) |
||||
|
{ |
||||
|
if ( (txobj2= cJSON_Parse(rawtx2)) != 0 ) |
||||
|
{ |
||||
|
if ( (vin= jarray(&m,txobj2,"vin")) != 0 ) |
||||
|
{ |
||||
|
for (j=0; j<m; j++) |
||||
|
{ |
||||
|
item = jitem(vin,j); |
||||
|
if ( (sobj= jobj(item,"scriptSig")) != 0 && (sigstr= jstr(sobj,"hex")) != 0 && strlen(sigstr) > 32 ) |
||||
|
{ |
||||
|
printf("height.%d mod.%d VINI.%d myind.%d MINE.(%s) j.%d\n",bp->height,bp->height%bp->numnotaries,j,myind,jprint(item,0),j); |
||||
|
ep->siglens[bestk] = (int32_t)strlen(sigstr) >> 1; |
||||
|
decode_hex(ep->sigs[bestk],ep->siglens[bestk],sigstr); |
||||
|
ep->masks[bestk] = bestmask; |
||||
|
ep->siglens[bestk] = ep->siglens[bestk]; |
||||
|
ep->beacon = bp->beacon; |
||||
|
dpow_sigsend(myinfo,bp,myind,bestk,bestmask,srchash,sigchannel); |
||||
|
retval = 0; |
||||
|
break; |
||||
|
} // else printf("notmine.(%s)\n",jprint(item,0));
|
||||
|
} |
||||
|
} else printf("no vin[] (%s)\n",jprint(txobj2,0)); |
||||
|
free_json(txobj2); |
||||
|
} else printf("cant parse.(%s)\n",rawtx2); |
||||
|
free(rawtx2); |
||||
|
} //else printf("error decoding (%s) %s\n",signedtx==0?"":signedtx,jsonstr);
|
||||
|
free_json(signobj); |
||||
|
} else printf("error parsing.(%s)\n",jsonstr); |
||||
|
free(jsonstr); |
||||
|
} |
||||
|
if ( flag != 0 && vins != 0 ) |
||||
|
free_json(vins); |
||||
|
} |
||||
|
|
||||
|
int32_t dpow_signedtxgen(struct supernet_info *myinfo,struct iguana_info *coin,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t myind,char *opret_symbol,uint32_t sigchannel) |
||||
|
{ |
||||
|
int32_t j,incr,numsigs,retval=-1; char rawtx[32768]; cJSON *txobj,*vins; bits256 txid,srchash,zero; struct dpow_entry *ep; |
||||
|
if ( bp->numnotaries < 8 ) |
||||
|
incr = 1; |
||||
|
else incr = sqrt(bp->numnotaries) + 1; |
||||
|
bestmask = dpow_maskmin(bestmask,bp,&bestk); |
||||
|
ep = &bp->notaries[myind]; |
||||
|
memset(&zero,0,sizeof(zero)); |
||||
|
if ( bestk < 0 ) |
||||
|
return(-1); |
||||
|
for (j=0; j<sizeof(srchash); j++) |
||||
|
srchash.bytes[j] = myinfo->DPOW.minerkey33[j+1]; |
||||
|
if ( (txobj= dpow_createtx(coin,&vins,bp,bestk,bestmask,1)) != 0 ) |
||||
|
{ |
||||
|
txid = dpow_notarytx(rawtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,opret_symbol); |
||||
|
if ( bits256_nonz(txid) != 0 && rawtx[0] != 0 ) // send tx to share utxo set
|
||||
|
{ |
||||
|
/*memset(&tmp,0,sizeof(tmp));
|
||||
|
tmp.ulongs[1] = bestmask; |
||||
|
tmp.bytes[31] = bestk; |
||||
|
len = (int32_t)strlen(rawtx) >> 1; |
||||
|
decode_hex(txdata+32,len,rawtx); |
||||
|
for (j=0; j<sizeof(srchash); j++) |
||||
|
txdata[j] = tmp.bytes[j]; |
||||
|
dpow_send(myinfo,bp,zero,bp->hashmsg,(bits256_nonz(bp->btctxid) == 0) ? DPOW_BTCTXIDCHANNEL : DPOW_TXIDCHANNEL,bp->height,txdata,len+32,bp->txidcrcs);*/ |
||||
|
dpow_rawtxsign(myinfo,coin,bp,rawtx,vins,bestk,bestmask,myind,sigchannel); |
||||
|
} |
||||
|
free_json(txobj); |
||||
|
//fprintf(stderr,"free vins\n");
|
||||
|
//free_json(vins);
|
||||
|
} |
||||
|
return(retval); |
||||
|
} |
||||
|
|
||||
|
void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_block *bp,uint32_t channel,int32_t myind) |
||||
|
{ |
||||
|
bits256 txid,srchash,zero; int32_t j,len,numsigs; char *retstr=0,str[65],str2[65]; uint8_t txdata[32768]; |
||||
|
memset(zero.bytes,0,sizeof(zero)); |
||||
|
if ( bp->state != 0xffffffff && bp->coin != 0 ) |
||||
|
{ |
||||
|
bp->signedtxid = dpow_notarytx(bp->signedtx,&numsigs,bp->coin->chain->isPoS,bp,bp->bestk,bp->bestmask,bp->opret_symbol); |
||||
|
printf("%s numsigs.%d signedtx.(%s)\n",bits256_str(str,bp->signedtxid),numsigs,bp->signedtx); |
||||
|
bp->state = 1; |
||||
|
if ( bits256_nonz(bp->signedtxid) != 0 && numsigs == DPOW_M(bp) ) |
||||
|
{ |
||||
|
if ( (retstr= dpow_sendrawtransaction(myinfo,bp->coin,bp->signedtx)) != 0 ) |
||||
|
{ |
||||
|
printf("sendrawtransaction.(%s)\n",retstr); |
||||
|
if ( is_hexstr(retstr,0) == sizeof(txid)*2 ) |
||||
|
{ |
||||
|
decode_hex(txid.bytes,sizeof(txid),retstr); |
||||
|
if ( bits256_cmp(txid,bp->signedtxid) == 0 ) |
||||
|
{ |
||||
|
len = (int32_t)strlen(bp->signedtx) >> 1; |
||||
|
decode_hex(txdata+32,len,bp->signedtx); |
||||
|
for (j=0; j<sizeof(srchash); j++) |
||||
|
txdata[j] = txid.bytes[j]; |
||||
|
dpow_send(myinfo,bp,txid,bp->hashmsg,(channel == DPOW_SIGBTCCHANNEL) ? DPOW_BTCTXIDCHANNEL : DPOW_TXIDCHANNEL,bp->height,txdata,len+32,bp->txidcrcs); |
||||
|
printf("complete statemachine.%s ht.%d\n",bp->coin->symbol,bp->height); |
||||
|
bp->state = 0xffffffff; |
||||
|
} else printf("sendtxid mismatch got %s instead of %s\n",bits256_str(str,txid),bits256_str(str2,bp->signedtxid)); |
||||
|
} |
||||
|
free(retstr); |
||||
|
retstr = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
File diff suppressed because it is too large
Loading…
Reference in new issue