//Main int main(int argc, char *argv[]) { //Get args if (argc < 2) { fprintf(stderr, "Usage: %s <snapshot_file>\n", argv[0]); return 1; } snap_path = argv[1]; //Allocate memory fprintf(stderr, "Allocating arena with size %.2f MBytes ...\n", (float)m / CHAR_BIT / MEGA); Bloom = malloc( (m + ( CHAR_BIT - 1)) / CHAR_BIT ); // Ceil byte length: bytes = bits + 7 / 8 //Load or create snapshot file if (!access(snap_path, F_OK)) { fputs("Loading snapshot...\n", stderr); if (LoadSnap(Bloom, snap_path)) { fputs("Unable to load snapshot!\n", stderr); return -1; } fputs("Snapshot loaded.\n", stderr); } else { fputs("Initializing new file storage...\n", stderr); size_t shouldwrite = (m + (CHAR_BIT - 1)) / CHAR_BIT; memset(Bloom, 0, shouldwrite); if (SaveSnap(Bloom, snap_path)) { fputs("Unable to save initial snapshot!\n", stderr); return -1; } fputs("Initial snapshot written.\n", stderr); } void OnReq(struct evhttp_request *req, void *arg) { struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req); if (!OutBuf) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); return; } struct evkeyvalq *Headers = evhttp_request_get_output_headers(req); if (!Headers) { evhttp_send_reply(req, HTTP_INTERNAL, "Internal Error", OutBuf); return; } const struct evhttp_uri *HTTPURI = evhttp_request_get_evhttp_uri(req); if (!HTTPURI) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); return; } const char *path = evhttp_uri_get_path(HTTPURI); if (!path) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); } const char *query_string = evhttp_uri_get_query(HTTPURI); if (!query_string) { evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf); return; } struct evkeyvalq params; evhttp_parse_query_str(query_string, ¶ms); const char *element = evhttp_find_header(¶ms, "e"); if (!element) { evhttp_clear_headers(¶ms); evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf); return; } int i; const char* (*Operation)(bloom_cell *, size_t []) = NULL; for (i=0; i< sizeof HandlerTable/ sizeof HandlerTable[0] ; i++) if (strncmp(HandlerTable[i][0], path, STR_MAX) == 0) { Operation = HandlerTable[i][1]; break; } if (!Operation) { evhttp_clear_headers(¶ms); evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", OutBuf); return; } const char *response = Operation(Bloom, Hashes(element)); evhttp_add_header(Headers, MIME_TYPE); evbuffer_add_printf(OutBuf, response); evhttp_send_reply(req, HTTP_OK, "OK", OutBuf); evhttp_clear_headers(¶ms); }; if (!(base = event_base_new())) crash("Couldn't create an event_base: exiting\n", -1); if (!(http = evhttp_new(base))) crash("Couldn't create evhttp. Exiting.\n", -1); evhttp_set_gencb(http, OnReq, NULL); if (!(handle = evhttp_bind_socket_with_handle(http, BIND_ADDRESS, BIND_PORT))) crash("couldn't bind to port 8888. Exiting.\n", -1); if (signal(SIGINT, term_handler) == SIG_ERR) crash("Unable to set SIGINT handler!", -1); if (signal(SIGTERM, term_handler) == SIG_ERR) crash("Unable to set SIGTERM handler!", -1); if (signal(SIGCHLD, child_collector) == SIG_ERR) crash("Unable to set SIGCHLD handler!", -1); //This signal handled by event loop in order to avoid malloc deadlock if ((dump_event = evsignal_new(base, SIGUSR1, dump_handler, NULL)) == NULL) crash("Unable to create SIGUSR1 handler!", -1); else if (event_add(dump_event, NULL) == -1) crash("Unable to add SIGUSR1 handler!", -1); if (event_base_dispatch(base) == -1) crash("Failed to run message loop.\n", -1); fputs("Exiting...\n", stderr); SaveSnap(Bloom, snap_path); evhttp_del_accept_socket(http, handle); evhttp_free(http); event_free(dump_event); event_base_free(base); free(Bloom); return 0; }
/** 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(1000); /** Initialize the Server Connection. **/ CLIENT = new LLP::Miner(IP, PORT); /** Initialize a Timer for the Hash Meter. **/ TIMER.Start(); unsigned int nTimerWait = 2; unsigned int nBestHeight = 0; loop { try { /** Run this thread at 1 Cycle per Second. **/ Sleep(50); /** Attempt with best efforts to keep the Connection Alive. **/ if (!CLIENT->Connected() || CLIENT->Errors()) { ResetThreads(); if (!CLIENT->Connect()) continue; else CLIENT->SetChannel(2); } /** Check the Block Height. **/ unsigned int nHeight = CLIENT->GetHeight(5); if (nHeight == 0) { printf("[MASTER] Failed to Update Height\n"); CLIENT->Disconnect(); continue; } /** If there is a new block, Flag the Threads to Stop Mining. **/ if (nHeight != nBestHeight) { nBestHeight = nHeight; printf("[MASTER] Coinshield Network: New Block %u\n", nHeight); ResetThreads(); } /** Rudimentary Meter **/ if (TIMER.Elapsed() > nTimerWait) { double Elapsed = (double)TIMER.ElapsedMilliseconds(); unsigned long long nHashes = Hashes(); //double khash = ((double)nHashes)/Elapsed; unsigned long long khash = nHashes / TIMER.ElapsedMilliseconds(); unsigned int nDifficulty = THREADS[0]->GetBlock()->GetBits(); nDifficulty = nDifficulty & 0xffffff; CBigNum target; target.SetCompact(nDifficulty); //double diff = (double)(0xFFFF * pow(2, 208)) / (double)nDifficulty; printf("[METERS] %llu kHash/s | Height = %u | Diff= %.08f\n", khash, nBestHeight, 1.0 / (double)nDifficulty); TIMER.Reset(); if (nTimerWait == 2) nTimerWait = 20; } /** Check if there is work to do for each Miner Thread. **/ for (unsigned int nIndex = 0; nIndex < THREADS.size(); nIndex++) { /** Attempt to get a new block from the Server if Thread needs One. **/ if (THREADS[nIndex]->GetIsNewBlock()) { /** Retrieve new block from Server. **/ /** Delete the Block Pointer if it Exists. **/ CBlock* pBlock = THREADS[nIndex]->GetBlock(); if (pBlock != NULL) { delete(pBlock); } /** Retrieve new block from Server. **/ pBlock = CLIENT->GetBlock(5); /** If the block is good, tell the Mining Thread its okay to Mine. **/ if (pBlock) { THREADS[nIndex]->SetIsBlockFound(false); THREADS[nIndex]->SetIsNewBlock(false); THREADS[nIndex]->SetBlock(pBlock); THREADS[nIndex]->SetHashes(0); // reset hash count } /** If the Block didn't come in properly, Reconnect to the Server. **/ else { CLIENT->Disconnect(); break; } } /** Submit a block from Mining Thread if Flagged. **/ else if (THREADS[nIndex]->GetIsBlockFound()) { // /** Attempt to Submit the Block to Network. **/ unsigned char RESPONSE = CLIENT->SubmitBlock(THREADS[nIndex]->GetBlock()->GetMerkleRoot(), THREADS[nIndex]->GetBlock()->GetNonce(), 10); double Elapsed = (double)TIMER.ElapsedMilliseconds(); double nHashes = THREADS[nIndex]->GetHashes(); double khash = nHashes / Elapsed; Hashes(); TIMER.Reset(); if (RESPONSE == 200) printf("[MASTER] Block Found by %s on thread %d %.1f kHash/s (accepted) Yay !!!\n", device_name[nIndex], nIndex, khash); else if (RESPONSE == 201) { printf("[MASTER] Block Found by %s on thread %d %.1f kHash/s (rejected) Booo !!!\n", device_name[nIndex], nIndex, khash); THREADS[nIndex]->SetIsNewBlock(true); THREADS[nIndex]->SetIsBlockFound(false); } else { printf("[MASTER] Failure to Submit Block. Reconnecting...\n"); CLIENT->Disconnect(); } break; } } } catch (std::exception& e) { printf("%s\n", e.what()); } } };
//Main Connection Thread. Handles all the networking to allow //Mining threads the most performance. void SKServerConnection::ServerThread() { /** Don't begin until all mining threads are Created. **/ while ((m_vecTHREADS.size() != m_nThreads) && !m_bIsShutDown) Sleep(1000); /** Initialize the Server Connection. **/ m_pCLIENT = new LLP::Miner(m_szIP, m_szPORT); /** Initialize a Timer for the Hash Meter. **/ m_tTIMER.Start(); m_totalTIMER.Start(); m_nBestHeight = 0; m_nNewBlocks = 0; loop { if (m_bIsShutDown) { break; } try { /** Run this thread at 1 Cycle per Second. **/ Sleep(1000); if (!m_bIsEnabled) { continue; } /** Attempt with best efforts to keep the Connection Alive. **/ if (!m_pCLIENT->Connected() || m_pCLIENT->Errors()) { if (!m_pCLIENT->Connect()) continue; /** Send to the server the Channel we will be Mining For. **/ else m_pCLIENT->SetChannel(2); } /** Check the Block Height. **/ unsigned int nHeight = m_pCLIENT->GetHeight(5); if (nHeight == 0) { printf("Failed to Update Height...\n"); m_pCLIENT->Disconnect(); continue; } /** If there is a new block, Flag the Threads to Stop Mining. **/ if (nHeight != m_nBestHeight) { m_nBestHeight = nHeight; m_nNewBlocks++; printf("[MASTER] Coinshield Network | New Block %u\n", nHeight); ResetThreads(); } /** Rudimentary Meter **/ if (m_tTIMER.Elapsed() > 10) { //unsigned int nElapsed = m_tTIMER.ElapsedMilliseconds(); //unsigned int nHashes = Hashes(); double KHASH = Hashes(); //double KHASH = (double)nHashes / nElapsed; printf("[METERS] %f KHash/s | Height = %u\n", KHASH, m_nBestHeight); m_tTIMER.Reset(); } /** Check if there is work to do for each Miner Thread. **/ for (int nIndex = 0; nIndex < m_vecTHREADS.size(); nIndex++) { if (m_bIsShutDown) { break; } if (!m_vecTHREADS[nIndex]->GetMinerData()->GetGPUData()->GetGPUSetting()->GetIsEnabled()) { continue; } /** Attempt to get a new block from the Server if Thread needs One. **/ if (m_vecTHREADS[nIndex]->GetIsNewBlock()) { /** Delete the Block Pointer if it Exists. **/ Core::CBlock* pBlock = m_vecTHREADS[nIndex]->GetMinerData()->GetBlock(); if (pBlock != NULL) { delete(pBlock); pBlock = NULL; } /** Retrieve new block from Server. **/ m_pCLIENT->SetChannel(2); pBlock = m_pCLIENT->GetBlock(5); /** If the block is good, tell the Mining Thread its okay to Mine. **/ if (pBlock && pBlock->GetChannel() == 2) { m_vecTHREADS[nIndex]->SetIsNewBlock(false); m_vecTHREADS[nIndex]->SetIsBlockFound(false); m_vecTHREADS[nIndex]->GetMinerData()->SetBlock(pBlock); } /** If the Block didn't come in properly, Reconnect to the Server. **/ else { m_pCLIENT->Disconnect(); } } /** Submit a block from Mining Thread if Flagged. **/ else if (m_vecTHREADS[nIndex]->GetIsBlockFound()) { /** Attempt to Submit the Block to Network. **/ unsigned char RESPONSE = m_pCLIENT->SubmitBlock(m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetMerkleRoot(), m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetNonce(), 30); printf("[MASTER] Hash Found on Miner Thread %i\n", nIndex); unsigned long long truc = m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetNonce(); printf("[MASTER] nonce %08x %08x\n", (uint32_t)(truc >> 32)), (uint32_t)(truc & 0xFFFFFFFFULL); /** Check the Response from the Server.**/ if (RESPONSE == 200) { printf("[MASTER] Block Accepted By Coinshield Network.\n"); m_vecTHREADS[nIndex]->SetBlocksFound(m_vecTHREADS[nIndex]->GetBlocksFound() + 1); } else if (RESPONSE == 201) { printf("[MASTER] Block Rejected by Coinshield Network.\n"); m_vecTHREADS[nIndex]->SetRejected(m_vecTHREADS[nIndex]->GetRejected() + 1); m_vecTHREADS[nIndex]->SetIsNewBlock(true); m_vecTHREADS[nIndex]->SetIsBlockFound(false); } /** If the Response was Incomplete, Reconnect to Server and try to Submit Block Again. **/ else { printf("[MASTER] Failure to Submit Block. Reconnecting...\n"); m_pCLIENT->Disconnect(); } break; } } } catch (std::exception& e) { std::cout << e.what() << std::endl; } } if (m_bIsShutDown) { for (size_t index = 0; index < m_vecTHREADS.size(); ++index) { m_vecTHREADS[index]->SetIsShuttingDown(true); while (!m_vecTHREADS[index]->GetDidShutDown()){} } m_bDidShutDown = true; } }