## 核心机制总结
### ① gbtmaker
* 监听 Bitcoind ZMQ 中 BITCOIND_ZMQ_HASHBLOCK 消息,一有新块产生,将立即向 kafka 发送新 Gbt
* 另默认每 5 秒间隔(可从配置文件中指定)主动 RPC 请求 Bitcoind ,获取 Gbt 发送给 kafka
* Gbt 消息大小约 2M ,含交易列表
### ② jobmaker
* 同时监听 kafka KAFKA_TOPIC_RAWGBT 和 KAFKA_TOPIC_NMC_AUXBLOCK ,以支持混合挖矿
* 接收的 Gbt 消息,如果与本地时间延迟超过 60 秒将丢弃,如果延迟超过 3 秒将打印 log
* 可用的 Gbt 消息,将以 gbtTime+isEmptyBlock+height 来构造 key 写入本地 Map ,另 gbtHash 也会写入本地队列
* 本地 gbtHash 队列仅保存最近 20 条,本地 gbtMap 中 Gbt 消息有效期:非空 Gbt 有效期 90 秒,空 Gbt 有效期 15 秒,过期将清除
* 有效期可从配置文件中指定
* Gbt 消息如果高度低于本地 Gbt 高度,且本地 Gbt 非空,且与本地时间间隔没超过 2 倍 stratumJobInterval_ , Gbt 消息将丢弃
* 三种情况下将立即向 kafka 发送 StratumJob :
* 高度大于本地高度(即已发现新块)
* 高度与本地高度相同,但前个 Job 为空块 Job ,但新 Gbt 非空块
* 达到预定的时间间隔 20 秒(可从配置文件中指定)
### ③ sserver
* 接收的 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 已被挤出
* DUPLICATE_SHARE , 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 指令一并下发处理
### ④ blkmaker
* blkmaker 可以连多个 bitcoind 节点
* blkmaker 监听和接收 4 类消息: RAWGBT 、 STRATUM_JOB 、 SOLVED_SHARE 和 NMC_SOLVED_SHARE
* 监听 RAWGBT 目的为获取 gbtHash/ 交易列表,用于构建 Block , gbtHash 和 vtxs 写入 rawGbtMap_
* rawGbtMap_ 保存最近 100 条 gbtHash/vtxs 对
* 监听 STRATUM_JOB 目的为获取 jobId_/gbtHash , jobId_ 和 gbtHash 写入 jobId2GbtHash_
* jobId2GbtHash_ 保存最近 120 条 jobId_/gbtHash 对
* 监听 SOLVED_SHARE 目的为获取 BlockHeader 和 coinbaseTx
* BlockHeader+coinbaseTx+vtxs 构造 Block
* 构造好的 Block 会提交连接的所有 bitcoind 节点
* 构造好的 Block 入库,入库字段包括:
* puid 、 worker_id 、 worker_full_name 、 job_id 、 height 、 hash
* rewards (即 coinbaseValue )、 size (即 blksize )、 prev_hash 、 bits 、 version 、 created_at
* created_at 为入库时间非爆块时间
### ⑤ sharelogger
* 接收 SHARE_LOG ,写入 shares_ ,每 2 秒写入文件(路径由 data_dir 指定)
* 每天一个新文件,文件名形如: sharelog-2016-07-12.bin
* 最多维护最近 3 天的文件句柄
### ⑥ slparser
* 支持三种功能:
* 指定 Date 和 UID ,将打印指定日期指定用户的 share 信息到 stdout
* UID=0 时,将打印指定日期所有用户的 share 信息
* 指定 Date 但未指定 UID ,读取指定日期 sharelog ,统计数据并写入数据库
* 按 Worker 、 user 、 pool 三个维度统计 :Accept1h 、 Accept1d 、 score1h 、 score1d 、 Reject1h 、 Reject1d
* 数据库仅保留最近 3 个月统计数据
* 如果 Date 和 UID 均未指定,将监听文件变化,读取 share 并统计数据,每 15 秒写入数据库
* 同时启动 Httpd 服务,开放 ServerStatus 和 WorkerStatus
### ⑦ statshttpd
* 监听并接收 SHARE_LOG ,按 Worker 、 user 、 pool 统计 acceptCount_ 、 acceptShareSec_ 、 rejectShareMin_
* 同时统计 totalWorkerCount_ 和 totalUserCount_
* 延时超过 1 小时的 SHARE_LOG 将被忽略
* 每 15s 写入数据库(可由 flush_db_interval 指定),每 30 分钟清理过期 Worker
* 如果 Worker 超过 1 小时未提交 share ,将被置为过期状态
* 计算每个 Worker 的 accept1m_ 、 accept5m_ 、 accept15m_ 、 reject15m_ 、 accept1h_ 、 reject1h_
* 以及 acceptCount_ 、 lastShareIP_ 、 lastShareTime_
* DROP 并 CREATE 数据表 mining_workers_tmp , Worker 统计数据批量写入 mining_workers_tmp
* mining_workers_tmp 数据写入数据表 mining_workers
* 监听并接收 COMMON_EVENTS ,获取 workerName 和 minerAgent ,更新数据表 mining_workers
* 启动 Httpd 服务,开放 ServerStatus 和 WorkerStatus
### ⑧ poolwatcher
* 监听 StratumJob ,更新 poolStratumJob_ ,用于和第三方矿池比对
* 作为 client 连接第三方矿池,如收到挖矿任务,仅当接收的 job 高度 = 本地矿池 job 高度 +1 时,将构造 EmptyGBT
* 如下几种情况将丢弃从第三方矿池接收的 job :
* job 高度与本地矿池 job 高度相同
* job 高度不等于本地矿池 job 高度 +1 ,高度跳跃太大
* nBits 与本地矿池 job nBits 不同
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31557831/viewspace-2216547/ ,如需转载,请注明出处,否则将追究法律责任。