Core::CBlock* Miner::DeserializeBlock(std::vector<unsigned char> DATA) { Core::CBlock* BLOCK = new Core::CBlock(); BLOCK->SetVersion(bytes2uint(std::vector<unsigned char>(DATA.begin(), DATA.begin() + 4))); uint1024 prevBlock = BLOCK->GetPrevBlock(); prevBlock.SetBytes(std::vector<unsigned char>(DATA.begin() + 4, DATA.begin() + 132)); BLOCK->SetPrevBlock(prevBlock); uint512 merkleRoot = BLOCK->GetMerkleRoot(); merkleRoot.SetBytes(std::vector<unsigned char>(DATA.begin() + 132, DATA.end() - 20)); BLOCK->SetMerkleRoot(merkleRoot); BLOCK->SetChannel(bytes2uint(std::vector<unsigned char>(DATA.end() - 20, DATA.end() - 16))); BLOCK->SetHeight(bytes2uint(std::vector<unsigned char>(DATA.end() - 16, DATA.end() - 12))); BLOCK->SetBits(bytes2uint(std::vector<unsigned char>(DATA.end() - 12, DATA.end() - 8))); BLOCK->SetNonce(bytes2uint64(std::vector<unsigned char>(DATA.end() - 8, DATA.end()))); return BLOCK; }
/** Main Connection Thread. Handles all the networking to allow Mining threads the most performance. **/ void ServerConnection::ServerThread() { /** Don't begin until all mining threads are Created. **/ while(THREADS.size() != nThreads) Sleep(1); /** Initialize the Server Connection. **/ CLIENT = new LLP::Miner(IP, PORT); /** Initialize a Timer for the Hash Meter. **/ METER_TIMER.Start(); HEIGHT_TIMER.Start(); loop { try { /** Run this thread at 100 Cycles per Second. **/ Sleep(10); /** Attempt with best efforts to keep the Connection Alive. **/ if(!CLIENT->Connected() || CLIENT->Errors() || CLIENT->Timeout(nTimeout)) { ResetThreads(); if(!CLIENT->Connect()) continue; else { CLIENT->SetChannel(1); CLIENT->GetHeight(); } } /** Check the Block Height every Second. **/ if(HEIGHT_TIMER.ElapsedMilliseconds() > 1000) { HEIGHT_TIMER.Reset(); CLIENT->GetHeight(); } /** Show the Meter every 15 Seconds. **/ if(METER_TIMER.Elapsed() > 15) { unsigned int SecondsElapsed = (unsigned int)time(0) - nStartTimer; unsigned int nElapsed = METER_TIMER.Elapsed(); double PPS = (double) nPrimes / nElapsed; double CPS = (double) nChains / nElapsed; double CSD = (double) (nBlocks * 60.0) / (SecondsElapsed / 60.0); nPrimes = 0; nChains = 0; printf("[METERS] %f PPS | %f CPS | %u Blocks | %f NXS per Hour | Height = %u | Difficulty %f | %02d:%02d:%02d\n", PPS, CPS, nBlocks, CSD, nBestHeight, nDifficulty / 10000000.0, (SecondsElapsed/3600)%60, (SecondsElapsed/60)%60, (SecondsElapsed)%60); METER_TIMER.Reset(); ResetThreads(); } /** Check if there is work to do for each Miner Thread. **/ for(int nIndex = 0; nIndex < THREADS.size(); nIndex++) { /** Attempt to get a new block from the Server if Thread needs One. **/ if(THREADS[nIndex]->fNewBlock) { CLIENT->GetBlock(); THREADS[nIndex]->fBlockWaiting = true; THREADS[nIndex]->fNewBlock = false; } } CLIENT->ReadPacket(); if(!CLIENT->PacketComplete()) continue; /** Handle the New Packet, and Interpret its Data. **/ LLP::Packet PACKET = CLIENT->NewPacket(); CLIENT->ResetPacket(); /** Output if a Share is Accepted. **/ if(PACKET.HEADER == CLIENT->GOOD) { nBlocks++; printf("[MASTER] Nexus : Block ACCEPTED\n"); ResetThreads(); } /** Output if a Share is Rejected. **/ else if(PACKET.HEADER == CLIENT->FAIL) { printf("[MASTER] Nexus : Block REJECTED\n"); ResetThreads(); } /** Reset the Threads if a New Block came in. **/ else if(PACKET.HEADER == CLIENT->BLOCK_HEIGHT) { unsigned int nHeight = bytes2uint(PACKET.DATA); if(nHeight > nBestHeight) { nBestHeight = nHeight; printf("[MASTER] Nexus : New Block %u.\n", nBestHeight); ResetThreads(); } } /** Set the Block for the Thread if there is a New Block Packet. **/ else if(PACKET.HEADER == CLIENT->BLOCK_DATA) { /** Search for a Thread waiting for a New Block to Supply its need. **/ for(int nIndex = 0; nIndex < THREADS.size(); nIndex++) { if(THREADS[nIndex]->fBlockWaiting) { THREADS[nIndex]->MUTEX.lock(); THREADS[nIndex]->cBlock.nVersion = bytes2uint(std::vector<unsigned char>(PACKET.DATA.begin(), PACKET.DATA.begin() + 4)); THREADS[nIndex]->cBlock.hashPrevBlock.SetBytes (std::vector<unsigned char>(PACKET.DATA.begin() + 4, PACKET.DATA.begin() + 132)); THREADS[nIndex]->cBlock.hashMerkleRoot.SetBytes(std::vector<unsigned char>(PACKET.DATA.begin() + 132, PACKET.DATA.end() - 20)); THREADS[nIndex]->cBlock.nChannel = bytes2uint(std::vector<unsigned char>(PACKET.DATA.end() - 20, PACKET.DATA.end() - 16)); THREADS[nIndex]->cBlock.nHeight = bytes2uint(std::vector<unsigned char>(PACKET.DATA.end() - 16, PACKET.DATA.end() - 12)); THREADS[nIndex]->cBlock.nBits = bytes2uint(std::vector<unsigned char>(PACKET.DATA.end() - 12, PACKET.DATA.end() - 8)); THREADS[nIndex]->cBlock.nNonce = bytes2uint64(std::vector<unsigned char>(PACKET.DATA.end() - 8, PACKET.DATA.end())); THREADS[nIndex]->MUTEX.unlock(); if(THREADS[nIndex]->cBlock.nHeight < nBestHeight) { printf("[MASTER] Received Obsolete Block %u... Requesting New Block.\n", THREADS[nIndex]->cBlock.nHeight); CLIENT->GetBlock(); break; } /** Set the Difficulty from most recent Block Received. **/ nDifficulty = THREADS[nIndex]->cBlock.nBits; printf("[MASTER] Block %s Height = %u Received on Thread %u\n", THREADS[nIndex]->cBlock.hashMerkleRoot.ToString().substr(0, 20).c_str(), THREADS[nIndex]->cBlock.nHeight, nIndex); THREADS[nIndex]->fBlockWaiting = false; break; } } } } catch(std::exception& e) { printf("%s\n", e.what()); CLIENT = new LLP::Miner(IP, PORT); } } }