unsigned ChooseWinner(const std::vector<bigint_t> &choices, TRng &rng) { std::vector<std::pair<double,unsigned> > values; for(unsigned i=0;i<choices.size();i++){ values.push_back(std::make_pair(1.0 / wide_as_double(8, choices[i].limbs), i)); } std::sort(values.begin(), values.end()); double acc=0; for(unsigned i=0;i<values.size();i++){ acc+=sqrt(values[i].first); values[i].first=acc; } std::uniform_real_distribution<double> distribution(0.0,acc); double sel=distribution(rng); for(unsigned i=0;i<values.size();i++){ if(sel<=values[i].first) return values[i].second; } return values.back().second; }
void Run() { try{ auto beginConnect = std::make_shared<Packet_ClientBeginConnect>(m_clientId, m_minerId); Log(Log_Info, "Connecting with clientId=%s, minerId=%s", m_clientId.begin(), m_minerId.begin()); SendPacket(beginConnect); auto endConnect = RecvPacket<Packet_ServerCompleteConnect>(); Log(Log_Info, "Connected to exchange=%s, running=%s", endConnect->exchangeId.c_str(), endConnect->serverId.c_str()); while (1){ Log(Log_Verbose, "Waiting for round to begin."); auto beginRound = RecvPacket<Packet_ServerBeginRound>(); Log(Log_Info, "Round beginning with %u bytes of chain data.", beginRound->chainData.size()); Log(Log_Verbose, "Waiting for request for bid."); auto requestBid = RecvPacket<Packet_ServerRequestBid>(); // Get an estimate of the skew between our clock and theirs. If it is positive, // then we are ahead of them. double tNow = now()*1e-9; double skewEstimate = tNow - requestBid->timeStampRequestBids*1e-9; // And work out how long they expect it to last, independent of the skew double period = requestBid->timeStampReceiveBids*1e-9 - requestBid->timeStampRequestBids*1e-9; Log(Log_Info, "Received bid request: serverStart=%lf, ourStart=%lf, skew=%lg. Bid period=%lf", requestBid->timeStampRequestBids*1e-9, tNow, skewEstimate, period); std::shared_ptr<Packet_ClientSendBid> bid = std::make_shared<Packet_ClientSendBid>(); // Making the bid MakeBid(beginRound, requestBid, period, skewEstimate, bid->solution, bid->proof); bid->timeSent = now(); Log(Log_Verbose, "Bid ready."); SendPacket(bid); Log(Log_Verbose, "Bid sent."); Log(Log_Verbose, "Waiting for results."); auto results = RecvPacket<Packet_ServerCompleteRound>(); Log(Log_Info, "Got round results."); for (unsigned i = 0; i < results->submissions.size(); i++){ double taken = requestBid->timeStampReceiveBids*1e-9 - results->submissions[i].timeRecv*1e-9; bool overDue = requestBid->timeStampReceiveBids < results->submissions[i].timeRecv; Log(Log_Info, " %16s : %.6lg, %lg%s", results->submissions[i].clientId.c_str(), wide_as_double(BIGINT_WORDS, results->submissions[i].proof), taken, overDue ? " OVERDUE" : "" ); if (m_knownCoins.find(results->submissions[i].clientId) == m_knownCoins.end()){ m_knownCoins[results->submissions[i].clientId] = 0; } } if (results->winner.clientId == m_clientId){ Log(Log_Info, ""); Log(Log_Info, "You won a coin!"); Log(Log_Info, ""); } m_knownRounds++; m_knownCoins[results->winner.clientId]++; Log(Log_Info, " %16s : %6s, %8s\n", "ClientId", "Coins", "Success"); auto it = m_knownCoins.begin(); while (it != m_knownCoins.end()){ Log(Log_Info, " %16s : %6d, %.6lf", it->first.c_str(), it->second, it->second / (double)m_knownRounds); ++it; } Log(Log_Verbose, ""); } } catch (std::exception &e){ Log(Log_Fatal, "Exception : %s.", e.what()); throw; } }