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); }
ZERO_ARGS(bitcoinrpc,getdifficulty) { char buf[512]; if ( coin != 0 ) { sprintf(buf,"{\"result\":\"success\",\"proof-of-work\":\"%.8f\",\"search-interval\": 0}",PoW_from_compact(coin->blocks.hwmchain.RO.bits,coin->chain->unitval)); return(clonestr(buf)); } else return(clonestr("{\"error\":\"getdifficulty needs coin\"}")); }
cJSON *iguana_blockjson(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_block *block,int32_t txidsflag) { char str[65],hexstr[1024]; int32_t i,len,size; struct iguana_txid *tx,T; struct iguana_msgzblock zmsg; struct iguana_msgblock *msg = (void *)&zmsg; struct iguana_zblock *zblock; bits256 hash2,nexthash2; uint8_t serialized[1024]; cJSON *array,*json = cJSON_CreateObject(); jaddstr(json,"result","success"); jaddstr(json,"hash",bits256_str(str,block->RO.hash2)); jaddnum(json,"height",block->height); //jaddnum(json,"ipbits",block->fpipbits); jaddstr(json,"merkleroot",bits256_str(str,block->RO.merkle_root)); jaddstr(json,"previousblockhash",bits256_str(str,block->RO.prev_block)); if ( block->height > 0 ) { nexthash2 = iguana_blockhash(coin,block->height+1); if ( bits256_nonz(nexthash2) != 0 ) jaddstr(json,"nextblockhash",bits256_str(str,nexthash2)); } jaddnum(json,"timestamp",block->RO.timestamp); jaddstr(json,"utc",utc_str(str,block->RO.timestamp)); jaddnum(json,"nonce",block->RO.nonce); jaddnum(json,"version",block->RO.version); jaddnum(json,"numvouts",block->RO.numvouts); jaddnum(json,"numvins",block->RO.numvins); jaddnum(json,"recvlen",block->RO.recvlen); jaddnum(json,"hdrsi",block->hdrsi); jaddnum(json,"difficulty",PoW_from_compact(block->RO.bits,coin->chain->unitval)); jaddnum(json,"bundlei",block->bundlei); jaddnum(json,"mainchain",block->mainchain); jaddnum(json,"valid",block->valid); jaddnum(json,"txn_count",block->RO.txn_count); jaddnum(json,"nBits",block->RO.bits); serialized[0] = ((uint8_t *)&block->RO.bits)[3]; serialized[1] = ((uint8_t *)&block->RO.bits)[2]; serialized[2] = ((uint8_t *)&block->RO.bits)[1]; serialized[3] = ((uint8_t *)&block->RO.bits)[0]; init_hexbytes_noT(hexstr,serialized,sizeof(uint32_t)); jaddstr(json,"nBitshex",hexstr); if ( block->RO.allocsize == sizeof(struct iguana_zblock) ) { zblock = (void *)block; memset(&zmsg,0,sizeof(zmsg)); zmsg.zH.version = zblock->RO.version; zmsg.zH.merkle_root = zblock->RO.merkle_root; zmsg.zH.timestamp = zblock->RO.timestamp; zmsg.zH.bits = zblock->RO.bits; zmsg.zH.bignonce = zblock->zRO.bignonce; if ( iguana_rwvarint32(1,zmsg.zH.var_numelements,&zblock->zRO.numelements) != sizeof(zmsg.zH.var_numelements) ) printf("unexpected varint size for zmsg.zH.numelements <- %d\n",zblock->zRO.numelements); for (i=0; i<ZCASH_SOLUTION_ELEMENTS; i++) zmsg.zH.solution[i] = zblock->zRO.solution[i]; zmsg.txn_count = 0;//block->RO.txn_count; len = iguana_rwblock(myinfo,coin->symbol,coin->chain->zcash,coin->chain->auxpow,coin->chain->hashalgo,1,&hash2,serialized,&zmsg,IGUANA_MAXPACKETSIZE*2); } else { memset(msg,0,sizeof(&msg)); msg->H.version = block->RO.version; msg->H.prev_block = block->RO.prev_block; msg->H.merkle_root = block->RO.merkle_root; msg->H.timestamp = block->RO.timestamp; msg->H.bits = block->RO.bits; msg->H.nonce = block->RO.nonce; msg->txn_count = 0;//block->RO.txn_count; len = iguana_rwblock(myinfo,coin->symbol,coin->chain->zcash,coin->chain->auxpow,coin->chain->hashalgo,1,&hash2,serialized,&zmsg,IGUANA_MAXPACKETSIZE*2); } init_hexbytes_noT(hexstr,serialized,len); jaddstr(json,"blockheader",hexstr); if ( txidsflag != 0 ) { array = cJSON_CreateArray(); for (i=0; i<block->RO.txn_count; i++) { if ( (tx= iguana_blocktx(coin,&T,block,i)) != 0 ) jaddistr(array,bits256_str(str,tx->txid)); } jadd(json,"tx",array); //printf("add txids[%d]\n",block->txn_count); } if ( (size= iguana_peerblockrequest(myinfo,coin,coin->blockspace,coin->blockspacesize,0,block->RO.hash2,0)) < 0 ) jaddstr(json,"error","couldnt generate raw bytes for block"); else jaddnum(json,"size",size); return(json); }