uint32_t get_work(uint32_t *midstate, uint32_t *data) { getwork gw; uint32_t mtime; int h,num=sizeof(hosts)/sizeof(hosts_t); static unsigned char host=0; gwmut.lock(); for(h=0;h<num;h++,host++){ host=host%num; GetworkThread* gwt=(GetworkThread*)hosts[host].gwt; if(!gwt->getworks.empty()){ mtime=gwt->getworks.back().mtime; memcpy(data,gwt->getworks.back().data,sizeof(gw.data)); memcpy(midstate,gwt->getworks.back().midstate,sizeof(gw.midstate)); //add host signature to data if(((char*)data)[0]!=0){ printf("ERROR: got incompatible data header char: %d\n",(int)(((char*)data)[0])); gwt->getworks.pop_back(); gwmut.unlock(); return 0;} memcpy(data,&host,1); gwt->getworks.pop_back(); gwmut.unlock(); hosts[host].got++; return mtime;}} gwmut.unlock(); threads_sleep(100); //sleep here rather than in C part return 0; }
void put_work(uint32_t *data,uint32_t* hash) { //FILE* fd; int k; unsigned char host; for(k=0;k<7;k++){ // Reverse byte order ! byte_reverse((uint8_t*)(&hash[k]));} memcpy(&host,data,1); for(k=7;k>0;k--){ if(hash[k]<hosts[host].target[k]){ // hash meets difficulty PutworkThread* pwt; putwork pw; memset(data,0,1); pwt=(PutworkThread*)hosts[host].pwt; memcpy(pw.data,data,sizeof(uint32_t)*32); pwmut.lock(); pwt->putworks.push_back(pw); pwmut.unlock(); hosts[host].done++; //fd=fopen(".putwork.log", "a"); //fprintf(fd,"%lu %08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x %d good\n",time(NULL),hash[0],hash[1],hash[2],hash[3],hash[4],hash[5],hash[6],hash[7],k); //fclose(fd); //printf("SENDING: %08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x\n",hash[0],hash[1],hash[2],hash[3],hash[4],hash[5],hash[6],hash[7]); return;} if(hash[k]>hosts[host].target[k]){ //fd=fopen(".putwork.log", "a"); //fprintf(fd,"%lu %08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x %d easy\n",time(NULL),hash[0],hash[1],hash[2],hash[3],hash[4],hash[5],hash[6],hash[7],k); //fclose(fd); return;}} }
void PutworkThread::Run() // just send data, don't check anything (again) { for(;;){ uint32_t data[32]; char ustr[258]; unsigned int k; //FILE* fd; pwmut.lock(); if(putworks.empty()){ pwmut.unlock(); if(testCancel()){ break;} threads_sleep(100); continue;} memcpy(data,putworks.front().data, sizeof(data)); putworks.erase(putworks.begin()); pwmut.unlock(); for(k=0;k<32;k++) { byte_reverse((uint8_t*)(&data[k])); sprintf(&ustr[k*8],"%08x",data[k]);} ustr[256] = 0; //fd=fopen(".putwork.log", "a"); //fprintf(fd,"%u %s\n",time(NULL),ustr); //fclose(fd); Json::Value query; query["jsonrpc"] = "2.0"; query["id"] = 1; query["method"] = "getwork"; query["params"][0] = std::string(ustr); Json::Value answ = make_rpc_req(query, false, host); // only one save // here we should check if the answer is ok hosts[host].sent++; //log(); } }
void PutworkThread::log() { unsigned int i,j; char filename[32]; FILE* fp; sprintf(filename,".putwork-%d.log",host); fp=fopen(filename, "w"); gwmut.lock(); fprintf(fp,"%d\n",putworks.size()); for(i=0;i<putworks.size();i++){ for(j=16;j<20;j++){ fprintf(fp,"%08x", putworks[i].data[j]);} fprintf(fp,"\n");} gwmut.unlock(); fclose(fp); }
/* -------------------------------- getwork -----------------------------------*/ void GetworkThread::log() { unsigned int i,j; char filename[32]; FILE* fp; sprintf(filename,".getwork-%d.log",host); fp=fopen(filename, "w"); gwmut.lock(); for(i=0;i<getworks.size();i++){ fprintf(fp,"%u ",getworks[i].mtime); for(j=0;j<8;j++){ fprintf(fp,"%08x", getworks[i].midstate[j]);} fprintf(fp,"\n");} gwmut.unlock(); fclose(fp); }
void GetworkThread::Run() { while(!testCancel()) { uint32_t midstate[8]={0,0,0,0,0,0,0,0}, data[32]; unsigned int i; getwork gw; uint32_t mtime = time(NULL); Json::Value query, answ; PutworkThread* pwt=(PutworkThread*)hosts[host].pwt; gwmut.lock(); if(!getworks.empty()){ if(getworks.back().mtime==mtime) { gwmut.unlock(); threads_sleep(100); continue;} for(i=0;i<getworks.size();i++){ if(getworks[i].mtime>mtime-MAXWORKAGE){ break;}} if(i>0){ getworks.erase(getworks.begin(),getworks.begin()+i);}} gwmut.unlock(); if(pwt==NULL){ threads_sleep(100); continue;} if(pwt->putworks.size()>MAXPUTWORK){ gwmut.lock(); getworks.clear(); // removes all jobs due to slow queue gwmut.unlock(); printf("GETWORK: queue full for host[%d]: %s \n",host,hosts[host].url); threads_sleep(1000); continue;} query["jsonrpc"] = "2.0"; query["id"] = 1; query["method"] = "getwork"; answ = make_rpc_req(query, false, host); if (answ.type() != Json::objectValue){ threads_sleep(500); continue; } if (!parse_ulong(data, answ["data"].asCString(), 32, 0, 1)){ threads_sleep(500); continue; } if (!parse_ulong(midstate, answ["midstate"].asCString(), 8, 0, 1)) { const unsigned sha_initial_state[8]={0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19}; SHA256_Full(midstate, data, sha_initial_state); } gwmut.lock(); if(!getworks.empty()){ if (memcmp( ((btc_block_t*)data)->hashPrevBlock, ((btc_block_t*)getworks.front().data)->hashPrevBlock, 32)) { getworks.clear(); // removes all jobs in last block gwmut.unlock(); pwmut.lock(); if (!parse_ulong(hosts[host].target, answ["target"].asCString(), 8, 0, 1)) { bits2bn(hosts[host].target, ((btc_block_t*)data)->nBits ); } pwmut.unlock(); gwmut.lock(); } } else{ if(hosts[host].target[7]==0xFFFFFFFF){ gwmut.unlock(); pwmut.lock(); if (!parse_ulong(hosts[host].target, answ["target"].asCString(), 8, 0, 1)) { bits2bn(hosts[host].target, ((btc_block_t*)data)->nBits ); } pwmut.unlock(); gwmut.lock(); } } gw.mtime=mtime; memcpy(gw.data,data,sizeof(data)); memcpy(gw.midstate,midstate,sizeof(midstate)); getworks.push_back(gw); gwmut.unlock(); //log(); } }
void GetworkThread::Run() { while(!testCancel()) { uint32_t midstate[8]={0,0,0,0,0,0,0,0}, data[32]; unsigned int i; getwork gw; uint32_t mtime = time(NULL); static uint32_t ltime=0; // last download Json::Value query, answ; PutworkThread* pwt=(PutworkThread*)hosts[host].pwt; if(ltime==mtime){ // limit requests to 1 per second threads_sleep(100); continue;} gwmut.lock(); if(!getworks.empty()){ int h; for(h=0;h<MAXHOSTS;h++){ // check all getwork threads if any has current job GetworkThread* gwt=(GetworkThread*)hosts[h].gwt; if(gwt==NULL || gwt->getworks.empty()){ continue;} if(gwt->getworks.back().mtime==mtime) { break;}} // this should be a GOTO, I have to start using this if(h<MAXHOSTS){ gwmut.unlock(); threads_sleep(100); continue;} /*if(getworks.back().mtime==mtime) { gwmut.unlock(); threads_sleep(100); continue;}*/ for(i=0;i<getworks.size();i++){ if(getworks[i].mtime>mtime-MAXWORKAGE){ break;}} if(i>0){ getworks.erase(getworks.begin(),getworks.begin()+i);}} gwmut.unlock(); if(pwt==NULL){ threads_sleep(100); continue;} if(pwt->putworks.size()>MAXPUTWORK){ gwmut.lock(); getworks.clear(); // removes all jobs due to slow queue gwmut.unlock(); printf("GETWORK: queue full for host[%d]: %s \n",host,hosts[host].url); threads_sleep(1000); continue;} query["jsonrpc"] = "2.0"; query["id"] = 1; query["method"] = "getwork"; answ = make_rpc_req(query, false, host,2); if (answ.type() != Json::objectValue){ threads_sleep(500); continue; } if (answ["data"].type() != Json::stringValue || !parse_ulong(data, answ["data"].asCString(), 32, 0, 1)){ threads_sleep(500); continue; } if (answ["midstate"].type() != Json::stringValue || !parse_ulong(midstate, answ["midstate"].asCString(), 8, 0, 1)) { const unsigned sha_initial_state[8]={0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19}; SHA256_Full(midstate, data, sha_initial_state); } gwmut.lock(); if(!getworks.empty()){ if (memcmp( ((btc_block_t*)data)->hashPrevBlock, ((btc_block_t*)getworks.front().data)->hashPrevBlock, 32)) { // removes all jobs in last block //try clearing all queues int h; for(h=0;h<MAXHOSTS;h++){ GetworkThread* gwt=(GetworkThread*)hosts[h].gwt; if(gwt==NULL){ continue;} gwt->getworks.clear();} // clear our again just in case :-) getworks.clear(); gwmut.unlock(); pwmut.lock(); if (answ["target"].type() != Json::stringValue || !parse_ulong(hosts[host].target, answ["target"].asCString(), 8, 0, 1)) { bits2bn(hosts[host].target, ((btc_block_t*)data)->nBits ); } pwmut.unlock(); gwmut.lock(); } } else{ if(hosts[host].target[7]==0xFFFFFFFF){ gwmut.unlock(); pwmut.lock(); if (answ["target"].type() != Json::stringValue || !parse_ulong(hosts[host].target, answ["target"].asCString(), 8, 0, 1)) { bits2bn(hosts[host].target, ((btc_block_t*)data)->nBits ); } pwmut.unlock(); gwmut.lock(); } } gw.mtime=mtime; memcpy(gw.data,data,sizeof(data)); memcpy(gw.midstate,midstate,sizeof(midstate)); getworks.push_back(gw); gwmut.unlock(); ltime=mtime; //log(); } }