Brother even block chain tutorial Btcpool The source code analysis of the mine pool Stratumserver module parsing
Summary of core mechanisms
- The received job delay will be discarded for more than 60 seconds
- If the Prevhash in the job is different from the local job Prevhash, the Isclean state in the job is set to true if a new block has been generated
???? * True requires the miner to switch job immediately
- In three cases, a new job will be issued to the miner:
???? receive new heights of job
???? The last job is a new height and is empty block job, and the latest job is a non-empty block job
???? * Reach the scheduled time interval of 30 seconds
- The last time the job was issued will be written to the file (specified by File_last_notify_time)
- Local job is valid for 300 seconds
- Pull a new user list every 10 seconds (specified by List_id_api_url), which the user writes to the local map
- Sserver Maximum available SessionID number is 16777214
- Btcpool supports btcagent extension protocol and stratum protocol, using Magic_number (0x7F) to differentiate
- Processing the stratum protocol:
???? The Suggest_target is equivalent to Suggest_difficulty, which is used to set the initial mining difficulty, and needs to be requested before subscribe
???? Use SessionID as extranonce1_ to ensure that the mining machine tasks are not duplicated
???? 15-Second read timeout before authorize, 10-minute read timeout after authorize, 10-minute no commit disconnects
???? Initial difficulty is 16384, or specified from Suggest_difficulty, the next time the adjustment is in place hold 10s commit share
???? * Each session will maintain a localjobs_ queue with a queue length of 10
- Share are rejected in several cases:
???? the JOB has been extruded in the Job_not_found,localjobs_ queue
???? DUPLICATEShare,share has been submitted, the submitted SHARE accounting into Submitshares
???? job does not exist in Job_not_found,jobrepository_, that is, the job has expired (300-second expiration time)
???? Job_not_found,jobrepository_ job status is stale, that is, the job is an old non-new job
???? the Ntime submitted in Time_too_old,share is less than the mintime of the job provision
???? The Ntime submitted in Time_too_old,share is 10 minutes larger than the current time
???? * The hash submitted in Low_difficulty,share does not meet the difficulty target
- To process the btcagent extension protocol:
???? Agent under the mining machine default difficulty is also 16384
???? Use Agent SessionID as the first half of the extranonce2_ to ensure that the agent does not duplicate the mining machine task
???? When a new task is issued in a mine pool, such as the session is btcagent, it will be difficult for all the miners under the agent.
???????? If the difficulty changes, will be different difficulty, the construction of multiple Cmd_mining_set_diff instructions are issued together with the processing
The Stratumserver command uses
sserver -c sserver.cfg -l log_dir#-c指定sserver配置文件#-l指定日志目录
Sserver.cfg configuration file
//是否使用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 message
"' 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 << "<<<<";
}
# # Calculation of mining difficulty ' c++//constructor//kmindiff_ for minimum difficulty, static const UInt64 kmindiff_ = 64;//kmaxdiff_ for maximum difficulty, static const UInt64 KMAXDIFF_ = 4611686018427387904ull;//kdefaultdiff_ is the default initial difficulty, static const UInt64 kdefaultdiff_ = 16384;//kdiffwindow_ Time window for n share, static const time_t Kdiffwindow_ = 900;//krecordseconds_ for 1 share time, static const time_t Krecordseconds_ = 10;//sharesnum_ and Shares_ initial values are 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 <=) {???????? Shareavgseconds_ = shareavgseconds;????} else {???????? Shareavgseconds_ = 8;????}} Code btcpool/src/stratumsession.h//Calculate Mining Difficulty//no less than minimum difficulty 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_.s Um (k); if (starttime_ = = 0) {//First time, we set the start Timestarttime_ = time (nullptr);} Const double Kratehigh = 1.40;const double kratelow = 0.40;//time window (900 seconds) expected share number of double Expectedcount = round (Kdiffwindow _/(double) shareavgseconds_);//return now >= starttime_ + kdiffwindow_;if (Isfullwindow (now)) {/* has a full window Now *///big miner has big expected share count to make it looks more Smooth.expectedcount *= minercoefficient (now, k);} if (Expectedcount > Kdiffwindow_) {//Up to 1 SEC submission 1, expected share maximum of 900expectedCount = Kdiffwindow_;//One second per share is en ough}//this was for very low hashrate miner, eg. USB miners//should received at least one share every the non-full time window, and the time has exceeded 60s, the number of seconds//submitted is less than (60 seconds 1), the current difficulty is greater than or equal to twice times the minimum difficulty// This reduces the difficulty to before 1/2if (!isfullwindow (now) && now >= starttime_ + &&sharescount <= (int32_t) (Now-start TIME_)/60.0) &&curdiff_ >= mindiff_*2) {Setcurdiff (curdiff_/2); sharesnum_.mapmultiply (2.0); return curdiff_;} Too fast//if the number of share submitted exceeds the expected number 1.4 times times if (Sharescount > Expectedcount * kratehigh) {//If share number is greater than expected share number, and current difficulty < maximum difficulty , lifting difficulty is twice times the original while (Sharesnum_.sum (k) > Expectedcount &&curdiff_ < kmaxdiff_) {Setcurdiff (curdiff_ * 2); Sharesnum_.mapdivide (2.0); Share number/2}return curdiff_;} Too slow//if it is a full time window and the current difficulty is greater than or equal to 2 is the minimum difficulty if (Isfullwindow (now) && curdiff_ >= mindiff_*2) {// If the number of share is lower than the expected number of 0.4, and the current difficulty is greater than or equal to twice times the minimum difficulty, reduce the difficulty for the original 1/2while (Sharesnum_.sum (k) < Expectedcount * Kratelow && Curdiff_ >= mindiff_*2) {Setcurdiff (curdiff_/2); sharesnum_.mapmultiply (2.0);//share multiply 2}assert (curDiff_ >= MINDIFF_); return curdiff_;} return curdiff_;}
The mechanism of sserver checking 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
The mechanism of sserver new job
1, if received new height statum job, will be issued immediately new 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 does 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(+),//Todo:make as config arg
Lastjobsendtime(0)
{
???? ASSERT (Kminingnotifyinterval < kmaxjobslifetime);
}
Blockchain tutorial Btcpool Mining pool Source Code Analysis Stratumserver module parsing