示例#1
0
文件: xauth.cpp 项目: plus7/Qween
QString XAuth::getSignature(const QString& method,
                            const QString& url,
                            QList<QPair<QString, QString> > queryItems)
{
    QList<QPair<QString,QString> > xauthItems;
    QDateTime now = QDateTime::currentDateTime();

    QString nonce;
    for(int i=0;i<8;i++){
        nonce.append(QString::number(qrand() % 0xFF,10));
    }

    xauthItems << QPair<QString,QString>(QString("oauth_consumer_key"),m_consumer_key);
    xauthItems << QPair<QString,QString>(QString("oauth_signature_method"),QString("HMAC-SHA1"));
    xauthItems << QPair<QString,QString>(QString("oauth_timestamp"),QString::number(now.toTime_t(),10));
    xauthItems << QPair<QString,QString>(QString("oauth_nonce"),nonce);
    xauthItems << QPair<QString,QString>(QString("oauth_version"),QString("1.0"));
    xauthItems << QPair<QString,QString>(QString("oauth_token"),m_token_key);
    QList<QPair<QString,QString> > mergedList(xauthItems);
    mergedList.append(queryItems);

    //sort mergedList
    qSort(mergedList.begin(), mergedList.end(), LessThan);

    QByteArray key(QString(m_consumer_secret + "&" + m_token_secret).toAscii());

    QByteArray params(util::encodeQuery(mergedList).toAscii());

    qDebug() << "PARAMS";
    qDebug() << params;

    QStringList dataList;
    dataList << method << QUrl::toPercentEncoding(url) << QUrl::toPercentEncoding(params);

    QByteArray data(dataList.join("&").toAscii());

    //========== digest ==========
    unsigned int  reslen;
    unsigned char    res[SHA_DIGEST_LENGTH + 1];
    qDebug() << "key and data";
    qDebug() << key;
    qDebug() << data;
    if(!HMAC (EVP_sha1(),  (unsigned char*)key.data(),    key.length(),
              (unsigned char*)data.data(), data.length(), res, &reslen) )
      return "";
    QByteArray digest = QByteArray::fromRawData((char *)res, reslen);

    xauthItems.append(QPair<QString,QString>(QString("oauth_signature"), QString(digest.toBase64())));

    QStringList sigList;
    for(int i=0;i<xauthItems.count();i++){
        sigList << QString("%0=\"%1\"").arg(xauthItems.at(i).first, QString(QUrl::toPercentEncoding(xauthItems.at(i).second)));
    }
    return sigList.join(", ");
}
		virtual void MakeBid(
			const std::shared_ptr<Packet_ServerBeginRound> roundInfo,
			const std::shared_ptr<Packet_ServerRequestBid> request,
			double period,
			double skewEstimate,
			std::vector<uint32_t> &solution,
			uint32_t *pProof
			){
			double startTime = now()*1e-9;
			double tSafetyMargin = timeGuard;
			double tFinish = request->timeStampReceiveBids*1e-9 + skewEstimate - tSafetyMargin;

			Log(Log_Verbose, "MakeBid - start, total period=%lg.", period);

			const Packet_ServerBeginRound *pParams = roundInfo.get();

			// This doesn't change within each round, so calculate it once and re-use.
			hash::fnv<64> hasher;
			uint64_t chainHash = hasher((const char*)&pParams->chainData[0], pParams->chainData.size());

			std::vector<ensemble> candidates;
            
            double t = now()*1e-9;
            double timeBudget = tFinish - t;
            
            uint32_t shortListLength = timeBudget > 1.0 ? shortListLengthDefault : shortListLengthFast;
            
			auto compMin = [](const ensemble& left, const ensemble& right) {
				return wide_compare(8, left.value.limbs, right.value.limbs) == 1;
			};

			auto compMax = [](const ensemble& left, const ensemble& right) {
				return wide_compare(8, left.value.limbs, right.value.limbs) == -1;
			};

			tbb::task_group group;

			std::vector<std::priority_queue<ensemble, std::vector<ensemble>, decltype(compMin)>> priorityQueues;
			std::vector<uint32_t> totalTrials(tbbCores);

			for (int i = 0; i < tbbCores; i++)
			{
				std::priority_queue<ensemble, std::vector<ensemble>, decltype(compMin)> ensemble_priority_queue(compMin);

				priorityQueues.push_back(ensemble_priority_queue);

				group.run([&, i](){

					std::priority_queue<ensemble, std::vector<ensemble>, decltype(compMax)> ensemble_priority_queue_reversed(compMax);

					unsigned nTrials = 0;
					unsigned offset = tbbOffset * i;
					while (1)
					{
						bigint_t proof = PoolHash(pParams, nTrials + offset, chainHash);

						if (priorityQueues[i].size() < shortListLength || wide_compare(8, proof.limbs, ensemble_priority_queue_reversed.top().value.limbs) == -1)
						{
							std::vector<uint32_t> indexes;

							indexes.push_back(nTrials + offset);

							ensemble e = ensemble{ proof, indexes };

							priorityQueues[i].push(e);
							ensemble_priority_queue_reversed.push(e);
						}

						if (ensemble_priority_queue_reversed.size() > shortListLength) ensemble_priority_queue_reversed.pop();

						double t = now()*1e-9;
						double timeBudget = tFinish - t;

						Log(Log_Debug, "Finish trial %d, time remaining =%lg seconds.", nTrials, timeBudget);

						nTrials++;

						if ((timeBudget <= 0 && priorityQueues[i].size() >= shortListLength) || nTrials >= tbbOffset-1)
						{
							totalTrials[i] = nTrials;
							break;	// We have run out of time, send what we have
						}

					}
				});

			}

			group.wait();

			uint32_t overallTrials = std::accumulate(totalTrials.begin(), totalTrials.end(), 0);

			for (int i = 0; i < shortListLength; i++)
			{
				auto nextQueue = std::min_element(priorityQueues.begin(), priorityQueues.end(), [](const std::priority_queue<ensemble, std::vector<ensemble>, decltype(compMin)>& left, const std::priority_queue<ensemble, std::vector<ensemble>, decltype(compMin)>& right) { return wide_compare(8, left.top().value.limbs, right.top().value.limbs) == -1;
				});

				candidates.push_back(nextQueue->top());
				nextQueue->pop();
			}

			Log(Log_Info, "Tried %d elements", overallTrials);

			double gStart = now()*1e-9;
            
            std::reverse(candidates.begin(),candidates.end());
            
			// This is where we store all the best combinations of xor'ed vectors. Each combination is of size roundInfo->maxIndices
			std::vector<ensemble> finalCandidates;

			// We find optimal combinations of the proofs calculated for each index using 'Gaussian elimination' (but xor-ing instead of adding/subtracting). We start in the column of the MSB, and xor vectors that have this bit high together to make the bit in this column 0 for as many vectors as possible. We then move to the next most significant bit, and repeat the process. At each stage, we keep track of what set of indexes we are xor-ing with what orther set of indexes. The the combined set size reaches roundInfo->maxIndices, we add this candidate solution to finalCandidates.

			//// -- Gaussian Elimination Starts Here -- ////

			std::vector<uint32_t> usedIndexes;

			for (int col = 255; col > -1; col--)
			{
				int firstNonzeroRow = -1;

				for (int row = 0; row < candidates.size(); row++)
				{
					if (bitIsHigh(candidates[row].value, col) && std::find(usedIndexes.begin(), usedIndexes.end(), row) == usedIndexes.end())
					{
						firstNonzeroRow = row;
						usedIndexes.push_back(row);
						break;
					}
				}

				if (firstNonzeroRow == -1) continue;

				bigint_t firstNonzeroRowValue = candidates[firstNonzeroRow].value;
				std::sort(candidates[firstNonzeroRow].components.begin(), candidates[firstNonzeroRow].components.end());

				for (int row = 0; row < candidates.size(); row++)
				{
					if (row == firstNonzeroRow) continue;

					if (bitIsHigh(candidates[row].value, col))
					{
						std::sort(candidates[row].components.begin(), candidates[row].components.end());

						std::vector<uint32_t> mergedList(candidates[row].components.size() + candidates[firstNonzeroRow].components.size());

						std::vector<uint32_t>::iterator iterator;

						iterator = std::set_symmetric_difference(candidates[row].components.begin(), candidates[row].components.end(), candidates[firstNonzeroRow].components.begin(), candidates[firstNonzeroRow].components.end(), mergedList.begin());

						mergedList.resize(iterator - mergedList.begin());

						if (mergedList.size() <= roundInfo->maxIndices)
						{
							bigint_t tmp;
							wide_xor(8, tmp.limbs, firstNonzeroRowValue.limbs, candidates[row].value.limbs);
							candidates[row].value = tmp;
							candidates[row].components = mergedList;
						}

						if (mergedList.size() == roundInfo->maxIndices) finalCandidates.push_back(candidates[row]);
					}
				}
			}

			//// -- Gaussian Elimination Ends Here -- ////

			// Sort the finalists in descending order, s.t. smallest value is in highest index
			std::sort(std::begin(finalCandidates), std::end(finalCandidates), [](const ensemble& left, const ensemble& right) {
				return wide_compare(8, left.value.limbs, right.value.limbs) == 1;
			});

			// Choose the finalist with the lowest score for our final bid.
			if (!finalCandidates.empty())
			{
				ensemble bestEnsemble = finalCandidates.back();

				std::sort(bestEnsemble.components.begin(), bestEnsemble.components.end());

				solution = bestEnsemble.components;

				wide_copy(BIGINT_WORDS, pProof, bestEnsemble.value.limbs);
			}
			else
			{
				// Last ditch attempt to make sure we always submit something valid. Ideally we should never come in here.

				std::vector<uint32_t> indices(roundInfo->maxIndices);
				uint32_t curr = 0;
				for (unsigned j = 0; j < indices.size(); j++){
					curr = curr + 1 + (rand() % 10);
					indices[j] = curr;
				}

				bigint_t proof = HashReference(pParams, indices.size(), &indices[0], chainHash);

				solution = indices;

				wide_copy(BIGINT_WORDS, pProof, proof.limbs);
			}

			double gEnd = now()*1e-9;

			Log(Log_Info, "GE Time Elapsed = %lg seconds.", gEnd - gStart);

			Log(Log_Verbose, "MakeBid - finish.");

			double endTime = now()*1e-9;

			Log(Log_Info, "Time used = %lg seconds.", endTime - startTime);
		}