區塊鏈教程btcpool礦池源碼分析StratumServer模組解析

來源:互聯網
上載者:User

標籤:變更   api   receive   dmi   Nid   info   ble   mit   abr   

兄弟連區塊鏈教程btcpool礦池源碼分析StratumServer模組解析

核心機制總結
  • 接收的job延遲超過60秒將丟棄
  • 如果job中prevHash與本地job中prevHash不同,即為已產生新塊,job中isClean狀態將置為true
    ????* true即要求礦機立即切換job
  • 三種情況下將向礦機下發新job:
    ???? 收到新高度的job
    ????
    過去一個job為新高度且為空白塊job,且最新job為非空塊job
    ????* 達到預定的時間間隔30秒
  • 最近一次下發job的時間將寫入檔案(由file_last_notify_time指定)
  • 本地job有效期間為300秒
  • 每10秒拉取一次新使用者列表(由list_id_api_url指定),使用者寫入本地map中
  • sserver最大可用SessionId數為16777214
  • btcpool支援BtcAgent擴充協議和Stratum協議,使用magic_number(0x7F)區分
  • 處理Stratum協議:
    ???? suggest_target與suggest_difficulty等價,用於設定初始挖礦難度,需在subscribe之前請求
    ????
    使用sessionID作為extraNonce1_以確保礦機任務不重複
    ???? authorize之前有15秒讀逾時,authorize之後有10分鐘讀逾時,10分鐘無提交將中斷連線
    ????
    初始難度為16384,或從suggest_difficulty指定,下次將一次調整到位保持10s提交share
    ????* 每個session會維護一個localJobs_隊列,隊列長度為10條
  • share被拒絕的幾種情況:
    ???? JOB_NOT_FOUND,localJobs_隊列中該job已被擠出
    ????
    DUPLICATESHARE,share已提交過,已提交的share會計入submitShares
    ???? JOB_NOT_FOUND,jobRepository_中job不存在,即job已到期(300秒到期時間)
    ????
    JOB_NOT_FOUND,jobRepository_中job狀態為Stale,即job是舊的非新job
    ???? TIME_TOO_OLD,share中提交的nTime小於job規定的minTime
    ????
    TIME_TOO_OLD,share中提交的nTime比目前時間大10分鐘
    ????* LOW_DIFFICULTY,share中提交的hash不滿足難度目標
  • 處理BtcAgent擴充協議:
    ???? Agent下礦機預設難度也為16384
    ????
    使用Agent sessionID作為extraNonce2_前半部分,以確保Agent下礦機任務不重複
    ???? 礦池下發新任務時,如session為BtcAgent,將為Agent下所有礦機計算難度
    ????????
    如難度發生變更,將按難度不同,分別構造多條CMD_MINING_SET_DIFF指令一併下發處理
StratumServer命令使用
sserver -c sserver.cfg -l log_dir#-c指定sserver設定檔#-l指定日誌目錄
sserver.cfg設定檔
//是否使用testnettestnet = true;//kafka叢集kafka = {brokers = "1.1.1.1:9092,2.2.2.2:9092,3.3.3.3:9092";};//sserver配置sserver = {//IP和連接埠ip = "0.0.0.0";port = 3333;//server id,全域唯一,取值範圍[1, 255]id = 1;//最近一次挖礦通知時間寫入檔案,用於監控file_last_notify_time = "/work/xxx/sserver_lastnotifytime.txt";//如果啟用模擬器,所有share均被接受,用於測試enable_simulator = false;//如果啟用,所有share都將成塊並被提交,用於測試enable_submit_invalid_block = false;//兩次share提交的間隔時間share_avg_seconds = 10;};users = {//使用者列表apilist_id_api_url = "example.com/get_user_id_list";};
SOLVED_SHARE訊息

```c++
if (isSubmitInvalidBlock == true || bnBlockHash <= bnNetworkTarget) {
????//
????// build found block
????//
????FoundBlock foundBlock;
????foundBlock.jobId
= share.jobId;
????foundBlock.workerId
= share.workerHashId;
????foundBlock.userId
= share.userId;
????foundBlock.height
= sjob->height;
????memcpy(foundBlock.header80
, (const uint8t *)&header, sizeof(CBlockHeader));
????snprintf(foundBlock.workerFullName
, sizeof(foundBlock.workerFullName_),
????????"%s", workFullName.c_str());
????// send
????sendSolvedShare2Kafka(&foundBlock, coinbaseBin);

????// mark jobs as stale
????jobRepository_->markAllJobsAsStale();

????LOG(INFO) << ">>>> found a new block: " << blkHash.ToString()
????<< ", jobId: " << share.jobId << ", userId: " << share.userId
????<< ", by: " << workFullName << " <<<<";
}

## 計算挖礦難度```c++//建構函式//kMinDiff_為最小難度,static const uint64 kMinDiff_ = 64;//kMaxDiff_為最大難度,static const uint64 kMaxDiff_ = 4611686018427387904ull;//kDefaultDiff_為預設初始難度,static const uint64 kDefaultDiff_ = 16384;//kDiffWindow_為N個share的時間視窗,static const time_t kDiffWindow_ = 900;//kRecordSeconds_為1個share的時間,static const time_t kRecordSeconds_ = 10;//sharesNum_和shares_初始值均為90DiffController(const int32_t shareAvgSeconds) :????startTime_(0),????minDiff_(kMinDiff_), curDiff_(kDefaultDiff_), curHashRateLevel_(0),????sharesNum_(kDiffWindow_/kRecordSeconds_), /* every N seconds as a record */????shares_ (kDiffWindow_/kRecordSeconds_){????if (shareAvgSeconds >= 1 && shareAvgSeconds <= 60) {????????shareAvgSeconds_ = shareAvgSeconds;????} else {????????shareAvgSeconds_ = 8;????}}//代碼btcpool/src/StratumSession.h//計算挖礦難度//不低於最小難度64uint64 DiffController::calcCurDiff() {uint64 diff = _calcCurDiff();if (diff < minDiff_) {diff = minDiff_;}return diff;}uint64 DiffController::_calcCurDiff() {const time_t now = time(nullptr);const int64 k = now / kRecordSeconds_;const double sharesCount = (double)sharesNum_.sum(k);if (startTime_ == 0) { // first time, we set the start timestartTime_ = time(nullptr);}const double kRateHigh = 1.40;const double kRateLow = 0.40;//時間視窗(900秒)內預期的share數double expectedCount = round(kDiffWindow_ / (double)shareAvgSeconds_);//return now >= startTime_ + kDiffWindow_;if (isFullWindow(now)) { /* have a full window now */// big miner have big expected share count to make it looks more smooth.expectedCount *= minerCoefficient(now, k);}if (expectedCount > kDiffWindow_) {//最多1秒提交1個,預期share數最大為900expectedCount = kDiffWindow_; // one second per share is enough}// this is for very low hashrate miner, eg. USB miners// should received at least one share every 60 seconds//非完整時間視窗、且時間已超過60s、提交的share數小於(60秒1個)、當前難度大於或等於2倍最小難度//此時降低難度為之前1/2if (!isFullWindow(now) && now >= startTime_ + 60 &&sharesCount <= (int32_t)((now - startTime_)/60.0) &&curDiff_ >= minDiff_*2) {setCurDiff(curDiff_ / 2);sharesNum_.mapMultiply(2.0);return curDiff_;}// too fast//如果提交share數超過預期數的1.4倍時if (sharesCount > expectedCount * kRateHigh) {//如果share數大於預期share數,且當前難度<最大難度時,提升難度為原來2倍while (sharesNum_.sum(k) > expectedCount &&curDiff_ < kMaxDiff_) {setCurDiff(curDiff_ * 2);sharesNum_.mapDivide(2.0); //share數/2}return curDiff_;}// too slow//如果是完整時間視窗,且當前難度大於或等於2被最小難度if (isFullWindow(now) && curDiff_ >= minDiff_*2) {//如果share數低於預期數的0.4,且當前難度大於或等於2倍最小難度,降低難度為原來的1/2while (sharesNum_.sum(k) < expectedCount * kRateLow &&curDiff_ >= minDiff_*2) {setCurDiff(curDiff_ / 2);sharesNum_.mapMultiply(2.0); //share數乘2}assert(curDiff_ >= minDiff_);return curDiff_;}return curDiff_;}
sserver校正share的機制
//本地job列表localJobs_最多保留最近10條任務,如有新任務,將擠出1條老任務。如果share所對應的job未在本地列表中,將StratumError::JOB_NOT_FOUND//本地share列表submitShares_中,如果已有本條share,即重複,將StratumError::DUPLICATE_SHARE//校正share不通過//  job列表exJobs_沒有找到job,exJobs_中job有300秒到期時間,到期將刪除,報StratumError::JOB_NOT_FOUND//  share中nTime小於job的最小時間,過老,報StratumError::TIME_TOO_OLD//  share中nTime超過job中的nTime 10分鐘,過新,報StratumError::TIME_TOO_NEW//  區塊雜湊>job難度目標,不合格,報StratumError::LOW_DIFFICULTY
sserver下發新job的機制

1、如果收到新高度statum job,將立即下發新job

```c++
bool isClean = false;
if (latestPrevBlockHash != sjob->prevHash) {
????isClean = true;
????latestPrevBlockHash = sjob->prevHash;
????LOG(INFO) << "received new height statum job, height: " << sjob->height
????<< ", prevhash: " << sjob->prevHash
.ToString();
}
shared_ptr<StratumJobEx> exJob = std::makeshared<StratumJobEx>(sjob, isClean);
{
????ScopeLock sl(lock
);
if (isClean) {
????????// mark all jobs as stale, should do this before insert new job
????????for (auto it : exJobs) {
????????????it.second->markStale();
????????}
????}
????// insert new job
????exJobs
[sjob->jobId_] = exJob;
}
if (isClean) {
????sendMiningNotify(exJob);
????return;
}

2、如果過去一個job為新高度且為空白塊job,並且最新job非空塊job,將儘快下發新job

if (isClean == false && exJobs.size() >= 2) {
????auto itr = exJobs
.rbegin();
????shared_ptr<StratumJobEx> exJob1 = itr->second;
????itr++;
????shared_ptr<StratumJobEx> exJob2 = itr->second;

????if (exJob2->isClean == true &&
????????exJob2->sjob
->merkleBranch.size() == 0 &&
????????exJob1->sjob
->merkleBranch_.size() != 0) {
????????sendMiningNotify(exJob);
????}
}

3、每超過一定時間間隔(30秒),將下發新job

void JobRepository::checkAndSendMiningNotify() {
????// last job is ‘expried‘, send a new one
????if (exJobs.size() &&
????????lastJobSendTime
+ kMiningNotifyInterval_ <= time(nullptr))
????{
????????sharedptr<StratumJobEx> exJob = exJobs.rbegin()->second;
????????sendMiningNotify(exJob);
????}
}

JobRepository::JobRepository(const char kafkaBrokers,
????const string &fileLastNotifyTime,
????Server
server):
running(true),
kafkaConsumer
(kafkaBrokers, KAFKA_TOPIC_STRATUMJOB, 0/patition/),
server
(server), fileLastNotifyTime(fileLastNotifyTime),
kMaxJobsLifeTime
(300),
kMiningNotifyInterval(30), // TODO: make as config arg
lastJobSendTime
(0)
{
????assert(kMiningNotifyInterval < kMaxJobsLifeTime);
}

區塊鏈教程btcpool礦池源碼分析StratumServer模組解析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.