char *gecko_blockconstruct(struct supernet_info *myinfo,struct iguana_info *virt,struct iguana_block *newblock,uint32_t *noncep,struct gecko_memtx **txptrs,int32_t txn_count,uint8_t *coinbase,int32_t coinbaselen,bits256 coinbasespend,double expiration,uint8_t *minerpubkey,int64_t blockreward) { struct iguana_info *btcd; uint8_t serialized[sizeof(*newblock)],space[16384]; int32_t i,n,len,totaltxlen=0; char *coinbasestr,str[65],str2[65],*blockstr=0; bits256 *txids=0,txspace[256],threshold,hash2; struct gecko_memtx *memtx; if ( (btcd= iguana_coinfind("BTCD")) == 0 ) { printf("basilisk needs BTCD\n"); return(0); } if ( txn_count+2 < sizeof(space)/sizeof(*space) ) { txids = txspace; memset(txids,0,sizeof(*txids) * (txn_count+2)); } else txids = calloc(txn_count+2,sizeof(*txids)); if ( txn_count > 0 ) { for (i=0; i<txn_count; i++) { if ( (memtx= txptrs[i]) != 0 ) { totaltxlen += memtx->datalen; txids[i + 1] = memtx->txid; printf("memtxid.%s\n",bits256_str(str,memtx->txid)); } } } if ( (coinbasestr= gecko_coinbasestr(myinfo,virt,&txids[0],newblock->RO.timestamp,minerpubkey,blockreward,coinbase,coinbaselen,coinbasespend)) != 0 ) { newblock->RO.merkle_root = iguana_merkle(txids,txn_count + 1); newblock->RO.txn_count = (txn_count + 1); if ( txn_count > 0 ) { printf("%s %s\n",bits256_str(str,txids[0]),bits256_str(str2,txids[1])); } if ( newblock->RO.bits >= GECKO_EASIESTDIFF ) newblock->RO.bits = GECKO_EASIESTDIFF; threshold = bits256_from_compact(newblock->RO.bits); if ( (newblock->RO.nonce= *noncep) == 0 ) { struct iguana_msgblock msg; memset(&msg,0,sizeof(msg)); msg.H.version = newblock->RO.version; msg.H.prev_block = newblock->RO.prev_block; msg.H.merkle_root = newblock->RO.merkle_root; msg.H.timestamp = newblock->RO.timestamp; msg.H.bits = newblock->RO.bits; for (i=0; i<GECKO_MAXMINERITERS; i++) { OS_randombytes((void *)noncep,sizeof(*noncep)); msg.H.nonce = *noncep; //n = iguana_serialize_block(virt->chain,&hash2,serialized,newblock); //char str[65]; printf("nonce.%08x %s\n",newblock->RO.nonce,bits256_str(str,newblock->RO.hash2)); len = iguana_rwblockhdr(1,virt->chain->zcash,serialized,&msg); hash2 = iguana_calcblockhash(virt->symbol,virt->chain->hashalgo,serialized,len); if ( bits256_cmp(threshold,hash2) > 0 ) { //printf("FOUND NONCE %d iterations\n",i+1); newblock->RO.hash2 = hash2; break; } if ( newblock->height != 0 && OS_milliseconds() > expiration ) { //printf("time limit exceeded %u %d iterations\n",virt->blocks.hwmchain.RO.timestamp,i+1); free(coinbasestr); if ( txids != txspace ) free(txids); return(0); } } } newblock->RO.nonce = *noncep; n = iguana_serialize_block(virt->chain,&newblock->RO.hash2,serialized,newblock); while ( 1 && time(NULL) <= newblock->RO.timestamp + GECKO_MAXFUTUREBLOCK ) { //printf("wait for block to be close enough to now: lag %ld\n",time(NULL) - newblock->RO.timestamp); sleep(1); } //if ( gecko_blocknonce_verify(virt,serialized,n,newblock->RO.bits,newblock->RO.timestamp,virt->blocks.hwmchain.RO.timestamp) >= 0 ) if ( bits256_cmp(threshold,newblock->RO.hash2) > 0 ) { blockstr = calloc(1,strlen(coinbasestr) + (totaltxlen+n)*2 + 1); init_hexbytes_noT(blockstr,serialized,n); printf("block.(%s) coinbase.(%s) lens.%ld\n",blockstr,coinbasestr,(strlen(blockstr)+strlen(coinbasestr))/2); strcat(blockstr,coinbasestr); len = (int32_t)strlen(blockstr); for (i=0; i<txn_count; i++) { if ( (memtx= txptrs[i]) != 0 ) { init_hexbytes_noT(&blockstr[len],gecko_txdata(memtx),memtx->datalen); len += memtx->datalen << 1; printf(" txi.%d (%s)\n",i,&blockstr[len]); } } } else printf("nonce failure\n"); free(coinbasestr); } if ( txids != txspace ) free(txids); return(blockstr); }
int32_t iguana_peerblockrequest(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *blockspace,int32_t max,struct iguana_peer *addr,bits256 hash2,int32_t validatesigs) { #if defined(_M_X64) /* * because we have no choice but to access the memory address * we need 64bit to correctly hold 64bit memory address, thus changing * to uint64_t instead of long in win x64 * @author - [email protected] */ struct iguana_txid *tx, T; bits256 checktxid; int32_t i, len, total, bundlei = -2; struct iguana_block *block; struct iguana_msgzblock zmsgB; bits256 *tree, checkhash2, merkle_root; struct iguana_bundle *bp = 0; uint64_t tmp; char str[65]; struct iguana_ramchaindata *rdata; #else struct iguana_txid *tx,T; bits256 checktxid; int32_t i,len,total,bundlei=-2; struct iguana_block *block; struct iguana_msgzblock zmsgB; bits256 *tree,checkhash2,merkle_root; struct iguana_bundle *bp=0; long tmp; char str[65]; struct iguana_ramchaindata *rdata; #endif if ( (bp= iguana_bundlefind(coin,&bp,&bundlei,hash2)) != 0 && bundlei >= 0 && bundlei < bp->n ) { if ( (rdata= bp->ramchain.H.data) == 0 )//&& bp == coin->current ) { //printf("iguana_peerblockrequest no ramchain data [%d] use RTcache\n",bp->hdrsi); //rdata = coin->RTramchain.H.data; return(-1); } if ( (block= bp->blocks[bundlei]) != 0 && rdata != 0 ) { iguana_blockunconv(coin->chain->zcash,coin->chain->auxpow,&zmsgB,(void *)block,0); zmsgB.txn_count = block->RO.txn_count; total = iguana_rwblock(myinfo,coin->symbol,coin->chain->zcash,coin->chain->auxpow,coin->chain->hashalgo,1,&checkhash2,&blockspace[sizeof(struct iguana_msghdr) + 0],&zmsgB,max); if ( bits256_cmp(checkhash2,block->RO.hash2) != 0 ) { //static int counter; //if ( counter++ < 100 ) printf("iguana_peerblockrequest: blockhash mismatch ht.%d\n",bp->bundleheight+bundlei); return(-1); } for (i=0; i<block->RO.txn_count; i++) { if ( (tx= iguana_blocktx(coin,&T,block,i)) != 0 ) { //printf("ht.%d [%d:%d] txi.%d i.%d o.%d %s\n",block->height,block->hdrsi,block->bundlei,i,tx->numvins,tx->numvouts,bits256_str(str,tx->txid)); if ( (len= iguana_ramtxbytes(coin,&blockspace[sizeof(struct iguana_msghdr) + total],max - total,&checktxid,tx,block->height,0,0,validatesigs)) > 0 )//&& bits256_cmp(checktxid,T.txid) == 0 ) total += len; else { static uint32_t counter; char str[65],str2[65]; if ( counter++ < 100 ) { for (i=0; i<len; i++) printf("%02x",blockspace[sizeof(struct iguana_msghdr)+i]); printf(" len.%d error getting txi.%d [%d:%d] cmp.%s %s\n",len,i,bp->hdrsi,bundlei,bits256_str(str,checktxid),bits256_str(str2,T.txid)); } break; } } else { printf("%s null tx error getting txi.%d [%d:%d]\n",coin->symbol,i,bp->hdrsi,bundlei); break; } } if ( i == block->RO.txn_count ) { #if defined(_M_X64) /* * because we have no choice but to access the memory address * we need 64bit to correctly hold 64bit memory address, thus changing * to uint64_t instead of long in win x64 * @author - [email protected] */ tmp = (uint64_t)&blockspace[sizeof(struct iguana_msghdr) + total + sizeof(bits256)]; #else tmp = (long)&blockspace[sizeof(struct iguana_msghdr) + total + sizeof(bits256)]; #endif tmp &= ~(sizeof(bits256) - 1); tree = (void *)tmp; for (i=0; i<block->RO.txn_count; i++) { if ( (tx= iguana_blocktx(coin,&T,block,i)) != 0 ) tree[i] = T.txid; else break; } if ( i == block->RO.txn_count ) { merkle_root = iguana_merkle(tree,block->RO.txn_count); if ( bits256_cmp(merkle_root,block->RO.merkle_root) == 0 ) { if ( addr != 0 && addr->lastsent != block->height ) { addr->lastsent = block->height; printf("Sendlen.%d block.%d %s to %s\n",total,block->height,bits256_str(str,block->RO.hash2),addr->ipaddr); if ( 0 ) { struct iguana_txblock txdata; int32_t checklen; static struct OS_memspace RAWMEM; if ( RAWMEM.ptr == 0 ) iguana_meminit(&RAWMEM,addr->ipaddr,0,IGUANA_MAXPACKETSIZE * 2,0); else iguana_memreset(&RAWMEM); memset(&txdata,0,sizeof(txdata)); int32_t i; for (i=0; i<total; i++) { if ( i == 81 ) printf(" "); printf("%02x",blockspace[i + sizeof(struct iguana_msghdr)]); } printf(" blocksize.%d\n",total); for (i=0; i<16; i++) printf("%02x",blockspace[i + sizeof(struct iguana_msghdr)+81]); printf(" txhdr\n"); if ( (checklen= iguana_gentxarray(myinfo,coin,&RAWMEM,&txdata,&checklen,&blockspace[sizeof(struct iguana_msghdr)],total)) != total && checklen != total-1 ) printf("Error reconstructing txarray checklen.%d total.%d\n",checklen,total); } return(iguana_queue_send(addr,0,blockspace,"block",total)); } else { //printf("validated.[%d:%d] len.%d\n",bp->hdrsi,bundlei,total); return(total); } } else printf("iguana_peerblockrequest: %s error %s merkle cmp tx.[%d] for ht.%d\n",coin->symbol,bits256_str(str,block->RO.hash2),i,bp->bundleheight+bundlei); } else printf("iguana_peerblockrequest: error merkle verify tx.[%d] for ht.%d\n",i,bp->bundleheight+bundlei); } else { static uint32_t counter; if ( counter++ < 10 ) printf("%s iguana_peerblockrequest: error getting tx.[%d] for ht.%d block.%p main.%d ht.%d\n",coin->symbol,i,bp->bundleheight+bundlei,block,block!=0?block->mainchain:-1,block!=0?block->height:-1); } } else { if ( coin->virtualchain != 0 ) ; /*if ( block != 0 ) printf("iguana_peerblockrequest: block.%p ht.%d mainchain.%d [%d:%d] from %s bp.%p rdata.%p\n",block,block->height,block->mainchain,bp->hdrsi,bundlei,addr!=0?addr->ipaddr:"local",bp,bp!=0?rdata:0); else printf("iguana_peerblockrequest: block.%p [%d:%d]\n",block,bp->hdrsi,bundlei);*/ } } //else printf("iguana_peerblockrequest: cant find %s\n",bits256_str(str,hash2)); return(-1); }