int32_t iguana_peergetrequest(struct iguana_info *coin,struct iguana_peer *addr,uint8_t *data,int32_t recvlen,int32_t getblock) { int32_t i,reqvers,len,n,flag = 0; bits256 hash2; if ( getblock != 0 ) addr->msgcounts.getblocks++; else addr->msgcounts.getheaders++; len = iguana_rwnum(0,&data[0],sizeof(uint32_t),&reqvers); len += iguana_rwvarint32(0,&data[len],(uint32_t *)&n); for (i=0; i<n&&len<=recvlen-sizeof(bits256)*2; i++) { len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes); if ( bits256_nonz(hash2) == 0 ) break; if ( flag == 0 ) { if ( getblock != 0 && iguana_peerblockrequest(coin,addr->blockspace,IGUANA_MAXPACKETSIZE,addr,hash2,0) > 0 ) flag = 1; else if ( getblock == 0 && iguana_peerhdrrequest(coin,addr->blockspace,IGUANA_MAXPACKETSIZE,addr,hash2) > 0 ) flag = 1; } } len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes); //for (i=0; i<69; i++) // printf("%02x ",data[i]); //printf("version.%d num blocks.%d recvlen.%d len.%d\n",reqvers,n,recvlen,len); return(len); }
int32_t iguana_rwblock(int32_t rwflag,bits256 *hash2p,uint8_t *serialized,struct iguana_msgblock *msg) { int32_t len = 0; char blockhash[65]; uint64_t x; len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->H.version),&msg->H.version); len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->H.prev_block),msg->H.prev_block.bytes); len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->H.merkle_root),msg->H.merkle_root.bytes); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->H.timestamp),&msg->H.timestamp); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->H.bits),&msg->H.bits); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->H.nonce),&msg->H.nonce); *hash2p = bits256_doublesha256(blockhash,serialized,len); //char str[65]; printf("len.%d: block version.%d timestamp.%u bits.%x nonce.%u prev.(%s) %llx blockhash.(%s) %llx\n",len,msg->H.version,msg->H.timestamp,msg->H.bits,msg->H.nonce,bits256_str(str,msg->H.prev_block),(long long)msg->H.merkle_root.txid,blockhash,(long long)hash2p->txid); if ( rwflag != 0 ) x = msg->txn_count; len += iguana_rwvarint(rwflag,&serialized[len],&x); if ( rwflag == 0 ) { char str[65]; bits256_str(str,*hash2p); if ( x < 65536 ) msg->txn_count = (uint16_t)x; else printf("txn_count overflow.%lld for %s\n",(long long)x,str); } // ? txns tx[] Block transactions, in format of "tx" command return(len); }
int32_t iguana_gethdrs(struct iguana_info *coin,uint8_t *serialized,char *cmd,char *hashstr) { uint32_t len,n; bits256 hash2; decode_hex(hash2.bytes,sizeof(hash2),hashstr); n = 0; len = iguana_rwnum(1,&serialized[sizeof(struct iguana_msghdr)],sizeof(uint32_t),&n); n++; len += iguana_rwvarint32(1,&serialized[sizeof(struct iguana_msghdr) + len],(uint32_t *)&n); len += iguana_rwbignum(1,&serialized[sizeof(struct iguana_msghdr) + len],sizeof(bits256),hash2.bytes); len += iguana_rwbignum(1,&serialized[sizeof(struct iguana_msghdr) + len],sizeof(bits256),(uint8_t *)bits256_zero.bytes); return(iguana_sethdr((void *)serialized,coin->chain->netmagic,cmd,&serialized[sizeof(struct iguana_msghdr)],len)); }
int32_t iguana_rwblockhash(int32_t rwflag,uint8_t *serialized,uint32_t *nVersionp,uint32_t *varintp,bits256 *hashes,bits256 *stophash) { int32_t i,len = 0; len += iguana_rwnum(rwflag,&serialized[len],sizeof(*nVersionp),nVersionp); len += iguana_rwvarint32(rwflag,&serialized[len],varintp); if ( *varintp < IGUANA_MAXLOCATORS-1 ) { for (i=0; i<*varintp; i++) len += iguana_rwbignum(rwflag,&serialized[len],sizeof(hashes[i]),hashes[i].bytes); len += iguana_rwbignum(rwflag,&serialized[len],sizeof(*stophash),stophash->bytes); //for (i=0; i<len; i++) // printf("%02x ",serialized[i]); //printf("rwblockhash len.%d\n",len); } else printf("iguana_rwblockhash: illegal varint.%d\n",*varintp); return(len); }
int32_t basilisk_messagekey(uint8_t *key,bits256 hash,cJSON *valsobj) { uint32_t channel,msgid; int32_t keylen = 0; channel = juint(valsobj,"channel"); msgid = juint(valsobj,"msgid"); keylen += iguana_rwbignum(1,&key[keylen],sizeof(hash),hash.bytes); keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); return(keylen); }
int32_t iguana_getdata(struct iguana_info *coin,uint8_t *serialized,int32_t type,char *hashstr) { uint32_t len,i,n=1; bits256 hash2; decode_hex(hash2.bytes,sizeof(hash2),hashstr); len = iguana_rwvarint32(1,&serialized[sizeof(struct iguana_msghdr)],(uint32_t *)&n); for (i=0; i<n; i++) { len += iguana_rwnum(1,&serialized[sizeof(struct iguana_msghdr) + len],sizeof(uint32_t),&type); len += iguana_rwbignum(1,&serialized[sizeof(struct iguana_msghdr) + len],sizeof(bits256),hash2.bytes); } return(iguana_sethdr((void *)serialized,coin->chain->netmagic,"getdata",&serialized[sizeof(struct iguana_msghdr)],len)); }
// two passes to check data size int32_t iguana_rwvin(int32_t rwflag,uint8_t *serialized,struct iguana_msgvin *msg) { int32_t len = 0; len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->prev_hash),msg->prev_hash.bytes); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout); //printf("vin.(%s) %d\n",bits256_str(msg->prev_hash),msg->prev_vout); len += iguana_rwvarint32(rwflag,&serialized[len],&msg->scriptlen); if ( rwflag == 0 ) msg->script = mycalloc('s',1,msg->scriptlen); len += iguana_rwmem(rwflag,&serialized[len],msg->scriptlen,msg->script); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence); //int i; for (i=0; i<msg->scriptlen; i++) // printf("%02x ",msg->script[i]); //printf(" inscriptlen.%d, prevhash.%llx prev_vout.%d | ",msg->scriptlen,(long long)msg->prev_hash.txid,msg->prev_vout); return(len); }
int32_t iguana_rwvin(int32_t rwflag,struct OS_memspace *mem,uint8_t *serialized,struct iguana_msgvin *msg) { int32_t len = 0; len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->prev_hash),msg->prev_hash.bytes); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout); len += iguana_rwvarint32(rwflag,&serialized[len],&msg->scriptlen); if ( rwflag == 0 ) msg->script = iguana_memalloc(mem,msg->scriptlen,1); len += iguana_rwmem(rwflag,&serialized[len],msg->scriptlen,msg->script); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence); //char str[65]; printf("MSGvin.(%s/v%d) script[%d]\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->scriptlen); //int i; for (i=0; i<msg->scriptlen; i++) // printf("%02x ",msg->script[i]); //printf(" inscriptlen.%d, prevhash.%llx prev_vout.%d | ",msg->scriptlen,(long long)msg->prev_hash.txid,msg->prev_vout); return(len); }
int32_t iguana_sethdr(struct iguana_msghdr *H,const uint8_t netmagic[4],char *command,uint8_t *data,int32_t datalen) { bits256 hash2,tmp; int32_t i; memset(H,0,sizeof(*H)); memcpy(H->netmagic,netmagic,4); strncpy(H->command,command,12); iguana_rwnum(1,H->serdatalen,sizeof(int32_t),&datalen); if ( data != 0 && datalen != 0 ) { hash2 = bits256_doublesha256(0,data,datalen); iguana_rwbignum(1,tmp.bytes,sizeof(tmp),hash2.bytes); for (i=0; i<4; i++) H->hash[i] = tmp.bytes[i]; } else H->hash[0] = 0x5d, H->hash[1] = 0xf6, H->hash[2] = 0xe0, H->hash[3] = 0xe2; return(datalen + sizeof(*H)); }
int32_t iguana_peerdatarequest(struct iguana_info *coin,struct iguana_peer *addr,uint8_t *data,int32_t recvlen) { int32_t i,type,len = 0; uint64_t x; bits256 hash2; len += iguana_rwvarint(0,data,&x); //for (i=0; i<10; i++) // printf("%02x ",data[i]); //printf("x.%d recvlen.%d\n",(int32_t)x,recvlen); if ( x < IGUANA_MAXINV ) { for (i=0; i<x; i++) { len += iguana_rwnum(0,&data[len],sizeof(uint32_t),&type); len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes); iguana_msgrequestQ(coin,addr,type,hash2); } } return(len); }
int32_t iguana_inv2packet(uint8_t *serialized,int32_t maxsize,int32_t type,bits256 *hashes,int32_t n) { int32_t i,len = sizeof(struct iguana_msghdr); uint64_t x = n; memset(serialized,0,len); len += iguana_rwvarint(1,&serialized[len],&x); //for (i=0; i<10; i++) // printf("%02x ",data[i]); //printf("x.%d recvlen.%d\n",(int32_t)x,recvlen); if ( x < IGUANA_MAXINV ) { for (i=0; i<x; i++) { len += iguana_rwnum(1,&serialized[len],sizeof(uint32_t),&type); len += iguana_rwbignum(1,&serialized[len],sizeof(bits256),hashes[i].bytes); } } if ( len > maxsize ) return(-1); return(len - sizeof(struct iguana_msghdr)); }
int32_t iguana_coinbase(int32_t isPoS,uint32_t txversion,uint8_t *serialized,uint32_t timestamp,bits256 prev_hash,uint8_t *coinbasescript,uint32_t coinbaselen,uint8_t *minerpayment,uint32_t minerpaymentlen,int64_t blockreward,bits256 *txidp) { int32_t len = 0,rwflag=1; uint32_t prev_vout,sequence,lock_time; char txidstr[65]; struct iguana_msgtx msg; memset(&msg,0,sizeof(msg)); msg.tx_out = (blockreward > 0) ? 1 : 0; msg.tx_in = 1; sequence = prev_vout = -1; lock_time = 0; msg.version = txversion; msg.timestamp = timestamp; len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg.version),&msg.version); if ( isPoS != 0 ) len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg.timestamp),&msg.timestamp); { len += iguana_rwvarint32(rwflag,&serialized[len],&msg.tx_in); // tx_in times len += iguana_rwbignum(rwflag,&serialized[len],sizeof(prev_hash),prev_hash.bytes); len += iguana_rwnum(rwflag,&serialized[len],sizeof(prev_vout),&prev_vout); len += iguana_rwvarint32(rwflag,&serialized[len],&coinbaselen); len += iguana_rwmem(rwflag,&serialized[len],coinbaselen,coinbasescript); len += iguana_rwnum(rwflag,&serialized[len],sizeof(sequence),&sequence); } { len += iguana_rwvarint32(rwflag,&serialized[len],&msg.tx_out); // tx_out times if ( msg.tx_out > 0 ) { len += iguana_rwnum(rwflag,&serialized[len],sizeof(blockreward),&blockreward); len += iguana_rwvarint32(rwflag,&serialized[len],&minerpaymentlen); len += iguana_rwmem(rwflag,&serialized[len],minerpaymentlen,minerpayment); } } len += iguana_rwnum(rwflag,&serialized[len],sizeof(lock_time),&lock_time); *txidp = bits256_doublesha256(txidstr,serialized,len); return(len); }
int32_t iguana_parser(struct iguana_info *coin,struct iguana_peer *addr,struct iguana_msghdr *H,uint8_t *data,int32_t datalen) { int32_t height,i,retval,srvmsg,bloom,intvectors,len= -100; uint64_t nonce,x; uint32_t type,firsttxidind,firstvout,firstvin; bits256 hash2; double PoW; bloom = intvectors = srvmsg = -1; if ( addr != 0 ) { addr->lastcontact = (uint32_t)time(NULL); strcpy(addr->lastcommand,H->command); } retval = 0; //printf("%s parse.(%s)\n",addr->ipaddr,H->command); if ( strcmp(H->command,"version") == 0 ) { struct iguana_msgversion recvmv; if ( addr != 0 ) { len = iguana_rwversion(0,data,&recvmv,addr->ipaddr); if ( len == datalen ) iguana_gotversion(coin,addr,&recvmv); //printf("deser.(%s) len.%d datalen.%d\n",recvmv.H.command,len,datalen); 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,"ping") == 0 ) { if ( datalen == 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++; } } } else if ( strcmp(H->command,"pong") == 0 ) { len = 0; if ( datalen == sizeof(uint64_t) ) { len = iguana_rwnum(0,data,sizeof(uint64_t),&nonce); iguana_gotpong(coin,addr,nonce); } else printf("unexpected pong datalen.%d\n",datalen); if ( len == datalen && addr != 0 ) addr->msgcounts.pong++; } 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 == datalen && addr != 0 ) { addr->lastgotaddr = (uint32_t)time(NULL); addr->msgcounts.addr++; } //printf("%s -> addr datalen.%d num.%d\n",addr->ipaddr,datalen,(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); height = -1; for (i=0; i<n; i++) { len += iguana_rwblock(0,&hash2,&data[len],&msg); if ( i == 0 ) height = iguana_setchainvars(coin,&firsttxidind,&firstvout,&firstvin,&PoW,hash2,msg.H.bits,msg.H.prev_block,msg.txn_count); iguana_convblock(&blocks[i],&msg,hash2,height,firsttxidind,firstvout,firstvin,PoW); if ( firsttxidind > 0 ) { height++; firsttxidind += blocks[i].txn_count; PoW += PoW_from_compact(blocks[i].bits,coin->chain->unitval); } } //printf("GOT HEADERS n.%d len.%d\n",n,len); iguana_gotheadersM(coin,addr,blocks,n); //myfree(blocks,sizeof(*blocks) * n); if ( len == datalen && addr != 0 ) addr->msgcounts.headers++; } else printf("got unexpected n.%d for headers\n",n); } else if ( strcmp(H->command,"tx") == 0 ) { struct iguana_msgtx *tx; tx = mycalloc('u',1,sizeof(*tx)); len = iguana_rwtx(0,data,tx,datalen,&tx->txid,-1,coin->chain->hastimestamp); if ( len == datalen && addr != 0 ) { iguana_gotunconfirmedM(coin,addr,tx,data,datalen); printf("tx datalen.%d\n",datalen); addr->msgcounts.tx++; } } else if ( strcmp(H->command,"block") == 0 ) { struct iguana_block *block; struct iguana_msgtx *tx; uint8_t extra[256]; block = mycalloc('b',1,sizeof(*block)); memset(extra,0,sizeof(extra)); tx = iguana_gentxarray(coin,&len,block,data,datalen,extra); if ( len == datalen ) { if ( addr != 0 ) { if ( len == datalen ) addr->msgcounts.block++; //addr->OV.reqrecv += datalen; //printf("%s gotblock.%d datalen.%d last.[%02x]\n",addr->ipaddr,block->height,datalen,data[len-1]); } iguana_gotblockM(coin,addr,block,tx,block->txn_count,data,datalen,extra); } else printf("parse error block txn_count.%d, len.%d vs datalen.%d\n",block->txn_count,len,datalen); //if ( tx != 0 ) // iguana_freetx(tx,block->txn_count); //myfree(block,sizeof(*block)); } else if ( strcmp(H->command,"reject") == 0 ) { for (i=0; i<datalen; i++) printf("%02x ",data[i]); printf("reject.(%s) datalen.%d\n",data+1,datalen); len = datalen; if ( len == datalen && addr != 0 ) addr->msgcounts.reject++; } else if ( strcmp(H->command,"alert") == 0 ) { for (i=0; i<datalen; i++) printf("%02x ",data[i]); printf("alert.(%s)\n",data+1); len = datalen; if ( len == datalen && 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 ) // for servers srvmsg = 'A', addr->msgcounts.getaddr++; else if ( strcmp(H->command,"mempool") == 0 ) // for servers 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 = datalen; // 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,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,sizeof(*blockhashes)); blockhashes[n++] = hash; //init_hexbytes_noT(hashstr,hash.bytes,sizeof(hash)); //queue_enqueue("blocksQ",&coin->blocksQ,queueitem(hashstr),1); //if ( i == x-2 ) // queue_enqueue("hdrsQ",&coin->hdrsQ,queueitem(hashstr),1); //printf("iv.%d %d of %d: block.%llx len.%d %s\n",intvectors,i,(int32_t)x,(long long)hash.txid,len,bits256_str(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 ) { //printf("n.%d != x.%d -> realloc blockhashes\n",n,(int32_t)x); blockhashes = myrealloc('f',blockhashes,(int32_t)(x*sizeof(*blockhashes)),n*sizeof(*blockhashes)); } // else printf("n.%d == x.%d\n",n,(int32_t)x); iguana_gotblockhashesM(coin,addr,blockhashes,n), blockhashes = 0; } if ( m > 0 ) { if ( m != x ) txids = myrealloc('t',txids,(int32_t)(x*sizeof(*txids)),m*sizeof(*txids)); iguana_gottxidsM(coin,addr,txids,m), txids = 0; } } if ( txids != 0 ) myfree(txids,sizeof(*txids) * x); if ( blockhashes != 0 ) myfree(blockhashes,sizeof(*blockhashes) * x); //printf("intvectors.%c datalen.%d\n",intvectors,datalen); } if ( len != datalen && len != datalen-1 ) { //printf("error.(%s) (%s): len.%d != datalen.%d\n",H->command,addr->ipaddr,len,datalen); //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,datalen); } else if ( len == datalen-1 ) { printf("extra byte.[%02x] command.%s len.%d datalen.%d\n",data[datalen-1],H->command,len,datalen); //retval = -1; } return(retval); }
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); }