int32_t iguana_msgparser(struct iguana_info *coin,struct iguana_peer *addr,struct OS_memspace *rawmem,struct OS_memspace *txmem,struct OS_memspace *hashmem,struct iguana_msghdr *H,uint8_t *data,int32_t recvlen) { uint8_t serialized[512]; char *retstr; int32_t i,retval,delay,srvmsg,bloom,intvectors,len= -100; uint64_t nonce,x; uint32_t type; bits256 hash2; bloom = intvectors = srvmsg = -1; if ( addr != 0 ) { addr->lastcontact = (uint32_t)time(NULL); strcpy(addr->lastcommand,H->command); } retval = 0; //printf("iguana_msgparser %s parse.(%s)\n",addr->ipaddr,H->command); if ( strncmp(H->command,"SuperNET",strlen("SuperNET")) == 0 ) { addr->supernet = 1; addr->msgcounts.verack++; len = recvlen; if ( (retstr= SuperNET_p2p(coin,addr,&delay,addr->ipaddr,data,recvlen,H->command[strlen("SuperNET")]=='b')) != 0 ) { iguana_send_supernet(coin,addr,retstr,delay); free(retstr); } //printf("GOT.(%s) [%s] len.%d from %s -> (%s)\n",H->command,data,recvlen,addr->ipaddr,retstr==0?"null":retstr); } else if ( strcmp(H->command,"version") == 0 ) { struct iguana_msgversion recvmv; if ( addr != 0 ) { len = iguana_rwversion(0,data,&recvmv,addr->ipaddr,recvlen); if ( len <= recvlen ) iguana_gotversion(coin,addr,&recvmv); //printf("deser.(%s) len.%d recvlen.%d\n",recvmv.H.command,len,recvlen); addr->msgcounts.version++; } } else if ( strcmp(H->command,"verack") == 0 ) { if ( addr != 0 ) { iguana_gotverack(coin,addr); addr->msgcounts.verack++; } len = 0; } else if ( strcmp(H->command,"ConnectTo") == 0 ) { iguana_queue_send(coin,addr,0,serialized,"getaddr",0,0,0); len = 6; } else if ( strcmp(H->command,"ping") == 0 ) { if ( recvlen == sizeof(uint64_t) && addr != 0 ) { len = iguana_rwnum(0,data,sizeof(uint64_t),&nonce); if ( addr != 0 ) { //printf("%u got nonce.%llx from %s\n",(uint32_t)time(NULL),(long long)nonce,addr->ipaddr); iguana_gotping(coin,addr,nonce,data); addr->msgcounts.ping++; } iguana_queue_send(coin,addr,0,serialized,"getaddr",0,0,0); } } else if ( strcmp(H->command,"pong") == 0 ) { len = 0; if ( recvlen == sizeof(uint64_t) ) { len = iguana_rwnum(0,data,sizeof(uint64_t),&nonce); iguana_gotpong(coin,addr,nonce); } else printf("unexpected pong recvlen.%d\n",recvlen); if ( len == recvlen && addr != 0 ) addr->msgcounts.pong++; iguana_queue_send(coin,addr,0,serialized,"getaddr",0,0,0); } else if ( strcmp(H->command,"addr") == 0 ) { struct iguana_msgaddress A; len = iguana_rwvarint(0,data,&x); for (i=0; i<x; i++) { memset(&A,0,sizeof(A)); if ( addr != 0 ) len += iguana_rwaddr(0,&data[len],&A,(int32_t)addr->protover); iguana_gotaddr(coin,addr,&A); } if ( len == recvlen && addr != 0 ) { addr->lastgotaddr = (uint32_t)time(NULL); addr->msgcounts.addr++; } //printf("%s -> addr recvlen.%d num.%d\n",addr->ipaddr,recvlen,(int32_t)x); } else if ( strcmp(H->command,"headers") == 0 ) { struct iguana_msgblock msg; struct iguana_block *blocks; uint32_t n; len = iguana_rwvarint32(0,data,&n); if ( n <= IGUANA_MAXINV ) { blocks = mycalloc('i',1,sizeof(*blocks) * n); for (i=0; i<n; i++) { len += iguana_rwblock(0,&hash2,&data[len],&msg); iguana_blockconv(&blocks[i],&msg,hash2,-1); } iguana_gotheadersM(coin,addr,blocks,n); //myfree(blocks,sizeof(*blocks) * n); if ( len == recvlen && addr != 0 ) addr->msgcounts.headers++; } else printf("got unexpected n.%d for headers\n",n); //printf("GOT HEADERS n.%d len.%d\n",n,len); } else if ( strcmp(H->command,"tx") == 0 ) { struct iguana_msgtx *tx; iguana_memreset(rawmem); tx = iguana_memalloc(rawmem,sizeof(*tx),1);//mycalloc('u',1,sizeof(*tx)); len = iguana_rwtx(0,rawmem,data,tx,recvlen,&tx->txid,coin->chain->hastimestamp,strcmp(coin->symbol,"VPN")==0); iguana_gotunconfirmedM(coin,addr,tx,data,recvlen); printf("tx recvlen.%d vs len.%d\n",recvlen,len); addr->msgcounts.tx++; } else if ( strcmp(H->command,"block") == 0 ) { struct iguana_txblock txdata; if ( addr != 0 ) addr->msgcounts.block++; iguana_memreset(rawmem), iguana_memreset(txmem);//, iguana_memreset(hashmem); memset(&txdata,0,sizeof(txdata)); if ( (len= iguana_gentxarray(coin,rawmem,&txdata,&len,data,recvlen)) == recvlen ) iguana_gotblockM(coin,addr,&txdata,rawmem->ptr,H,data,recvlen); else printf("parse error block txn_count.%d, len.%d vs recvlen.%d\n",txdata.block.RO.txn_count,len,recvlen); } else if ( strcmp(H->command,"reject") == 0 ) { for (i=0; i<recvlen; i++) printf("%02x ",data[i]); printf("reject.(%s) recvlen.%d\n",data+1,recvlen); len = recvlen; if ( len == recvlen && addr != 0 ) addr->msgcounts.reject++; } else if ( strcmp(H->command,"alert") == 0 ) { for (i=0; i<recvlen; i++) printf("%02x ",data[i]); printf("alert.(%s)\n",data+1); len = recvlen; if ( len == recvlen && addr != 0 ) addr->msgcounts.alert++; } else if ( addr != 0 ) { if ( strcmp(H->command,"inv") == 0 ) intvectors = 'I', addr->msgcounts.inv++; else if ( strcmp(H->command,"notfound") == 0 ) // for servers intvectors = 'N', addr->msgcounts.notfound++; else if ( strcmp(H->command,"getdata") == 0 ) // for servers { intvectors = srvmsg = 'D', addr->msgcounts.getdata++; } else if ( strcmp(H->command,"getblocks") == 0 ) // for servers { srvmsg = 'B', addr->msgcounts.getblocks++; } else if ( strcmp(H->command,"getheaders") == 0 ) // for servers { srvmsg = 'H', addr->msgcounts.getheaders++; } else if ( strcmp(H->command,"getaddr") == 0 ) { srvmsg = 'A', addr->msgcounts.getaddr++; } else if ( strcmp(H->command,"mempool") == 0 ) srvmsg = 'M', addr->msgcounts.mempool++; else if ( strcmp(H->command,"filterload") == 0 ) // for bloom bloom = 'L', addr->msgcounts.filterload++; else if ( strcmp(H->command,"filteradd") == 0 ) // for bloom bloom = 'A', addr->msgcounts.filteradd++; else if ( strcmp(H->command,"filterclear") == 0 ) // for bloom bloom = 'C', addr->msgcounts.filterclear++; else if ( strcmp(H->command,"merkleblock") == 0 ) // for bloom bloom = 'M', addr->msgcounts.merkleblock++; } if ( bloom >= 0 || srvmsg >= 0 ) len = recvlen; // just mark as valid if ( intvectors >= 0 ) { bits256 *txids=0,*blockhashes=0,hash; int32_t n,m; len = n = m = 0; len += iguana_rwvarint(0,&data[len],&x); for (i=0; i<x; i++) { len += iguana_rwnum(0,&data[len],sizeof(uint32_t),&type); len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash.bytes); if ( type == MSG_TX ) { if ( txids == 0 ) txids = mycalloc('t',(int32_t)x+1,sizeof(*txids)); txids[m++] = hash; if ( (rand() % 1000) == 0 && i == x-1 ) printf("%s iv.%c %d of %d: tx.%llx len.%d\n",addr->ipaddr,intvectors,i,(int32_t)x,(long long)hash.txid,len); } else if ( type == MSG_BLOCK ) { if ( blockhashes == 0 ) { blockhashes = mycalloc('f',(int32_t)x+1,sizeof(*blockhashes)); n = 1; } blockhashes[n++] = hash; } else if ( type == MSG_FILTERED_BLOCK ) printf("iv.%d %d of %d: merkle.%llx\n",intvectors,i,(int32_t)x,(long long)hash.txid); else printf("what type is %d\n",type); } if ( intvectors == 'I' ) { if ( n > 0 ) { if ( n != x+1 ) { printf("n.%d != x.%d -> realloc blockhashes\n",n,(int32_t)x+1); blockhashes = myrealloc('f',blockhashes,(int32_t)((x+1)*sizeof(*blockhashes)),n*sizeof(*blockhashes)); } // else printf("n.%d == x.%d\n",n,(int32_t)x); if ( 1 ) iguana_gotblockhashesM(coin,addr,blockhashes,n), blockhashes = 0; else iguana_send_hashes(coin,"getblocks",addr,blockhashes[0],&blockhashes[1],n); } if ( m > 0 ) { if ( m != x ) txids = myrealloc('t',txids,(int32_t)((x+1)*sizeof(*txids)),(m+1)*sizeof(*txids)); iguana_gottxidsM(coin,addr,txids,m), txids = 0; } } if ( txids != 0 ) myfree(txids,sizeof(*txids) * (x+1)); if ( blockhashes != 0 ) myfree(blockhashes,sizeof(*blockhashes) * (x+1)); //printf("intvectors.%c recvlen.%d\n",intvectors,recvlen); } if ( len != recvlen && len != recvlen-1 && len != recvlen-2 ) { //printf("error.(%s) (%s): len.%d != recvlen.%d\n",H->command,addr->ipaddr,len,recvlen); //for (i=0; i<len; i++) // printf("%02x",data[i]); if ( strcmp(H->command,"addr") != 0 ) printf("%s.%s len mismatch %d != %d\n",addr!=0?addr->ipaddr:"local",H->command,len,recvlen); } else if ( len != recvlen ) { printf("%s extra byte.[%02x] command.%s len.%d recvlen.%d\n",addr->ipaddr,data[recvlen-1],H->command,len,recvlen); //retval = -1; } return(retval); }
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); }