primecoin-pool学习
On going…
./primecoind -gen -debug -frontport=6667 -host=121.43.185.81 -feeaddr=AVjsWxuvcmjDvULpuegjKbgjrCthi2JVeq -daemon
Primecoin XPM Pool Server
https://github.com/madMAx43v3r/xpmpool
Primecoin XPM GPU Miner for xpmpool (aka. madPrimeMiner)
https://github.com/madMAx43v3r/xpmclient
The solo-mining server code is at: https://github.com/madMAx43v3r/xpmserver
Primecoin XPM GPU Miner for xpmpool (aka. madPrimeMiner)
https://github.com/eXtremal-ik7/xpmclient
挖矿有两种方式,一种叫SOLO挖矿,另一种是去矿池挖矿。
目前最广泛使用的挖矿协议 Stratum
数据库相关操作
pool.h
dbo::backend::Postgres* mBackend; |
createTables |
Pools are groups of cooperating miners who agree to share block rewards in proportion to their contributed mining power.
By joining a mining pool you share your hash rate with the pool. Once the pool finds a block you get a payout based on the percent of hash rate contributed to the pool.
If you contributed 1% of the pools hashrate, you’d get .125 bitcoins out of the current 12.5 bitcoin block reward.
Mining pools coordinate many hundreds or thousands of miners, over specialized pool-mining protocols.
Successful blocks pay the reward to a pool bitcoin address, rather than individual miners.
The pool server will periodically make payments to the miners’ bitcoin addresses,
once their share of the rewards has reached a certain threshold.
Typically, the pool server charges a percentage fee of the rewards for providing the pool-mining service.
Miners participating in a pool split the work of searching for a solution to a candidate block,
earning “shares” for their mining contribution.
The mining pool sets a higher target (lower difficulty) for earning a share, typically more than 1,000 times easier
than the bitcoin network’s target. When someone in the pool successfully mines a
block, the reward is earned by the pool and then shared with all miners in proportion
to the number of shares they contributed to the effort.
How does a mining pool measure the individual contributions, so as to fairly
distribute the rewards, without the possibility of cheating?
The answer is to use bitcoin’s Proof-of-Work algorithm to measure each pool miner’s contribution, but set at
a lower difficulty so that even the smallest pool miners win a share frequently enough
to make it worthwhile to contribute to the pool.
By setting a lower difficulty for earning shares, the pool measures the amount of work done by each miner.
Each time a pool miner finds a block header hash that is less than the pool target, she proves she
has done the hashing work to find that result. More importantly, the work to find shares contributes,
in a statistically measurable way, to the overall effort to find a hash lower than the bitcoin network’s target.
Thousands of miners trying to find low-value hashes will eventually find one low enough to satisfy the bitcoin network target.
用抛骰子游戏来说明挖矿:
假设当前的网络难度是抛出 4 以下的数字,那么矿池会把矿池难度设置为 8 以下的数字,难度比网络难度低,矿工每次抛出 8 以下的数字就完成一次工作,赚到 shares
当许多矿工都在抛的时候,就有几率抛出小于 4 的情况,这样整个矿池就获得奖励,然后按照每个矿工的 share 数值分利润。
费率等相关计算
In all these schemes $ B $ stands for a block reward minus pool fee and $ p $ is a probability of finding a block in a share attempt
($ p=\frac{1}{D} $, where $ D $ is current block difficulty)
Pay-per-Share
The Pay-per-Share (PPS) approach offers an instant, guaranteed payout to a miner for his contribution to the probability that the pool finds a block.
Each share costs exactly the expected value of each hash attempt $ R= B × p $
Proportional
Miners earn shares until the pool finds a block (the end of the mining round). After that each user gets reward $ R=B × \frac{n}{N} $, where $ n $ is amount of his own shares, and $ N $ is amount of all shares in this round. In other words, all shares are equal, but its cost is calculated only in the end of a round.
Based on the accepted shares, members get rewarded using different methods, which include the following:
- Pay-per share (PPS): Allows instant payout solely based on accepted shares contributed by the pool member, who are allowed to withdraw their earnings instantly from the pool’s existing balance.
- Proportional (PROP): At the end of a mining round, a reward which is proportional to the number of the member’s shares with respect to total shares in the pool, is offered.
- Shared Maximum Pay Per Share (SMPPS): A method similar to PPS but limits the payout to the maximum that the pool has earned.
- Equalized Shared Maximum Pay Per Share (ESMPPS): A method similar to SMPPS, but distributes payments equally among all miners in the bitcoin mining pool.
Other variations include Double Geometric Method (DGM), Recent Shared Maximum Pay Per Share (RSMPPS), Capped Pay Per Share with Recent Backpay (CPPSRB), and Bitcoin Pooled Mining (BPM).
挖矿协议
Pool miners connect to the pool server using a mining protocol such as Stratum (STM) or GetBlockTemplate (GBT).
Both the STM and GBT protocols create block templates
that contain a template of a candidate block header. The pool server constructs a can‐
didate block by aggregating transactions, adding a coinbase transaction (with extra
nonce space), calculating the merkle root, and linking to the previous block hash. The
header of the candidate block is then sent to each of the pool miners as a template.
Each pool miner then mines using the block template, at a higher (easier) target than
the bitcoin network target, and sends any successful results back to the pool server to
earn shares.
getwork 2012年末 废弃
rpc response
{ |
data大小为128字节,块头(Block Head)大小是80字节,那为何是128字节呢?那就得回到SHA256算法。
00000001 // uint32, 块版本 |
计算 POW 只需要 block header 的 76 个字节就可以了,到 bits 这个位置。然后 nonce 从0开始累加计算 hash 值。
有的情况在 nonce 累加到最大值之后仍然不会小于目标值,这个时候需要一个 extraNonce 字段。然后 nonce 设为 0,通过累加 extraNonce 计算 hash 值
Example getwork data: 00000001a10bacc7e639d1c69a01014bc5db6f2604b3477a3f273a4e019a232700000000a5942372cc60477c8a276e59c8f1a3f58654ea2f6c4402bf1b18e48455b5b8f64f10868b1c07475200000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
The data field I got was:
00000001 - version
a10bacc7e639d1c69a01014bc5db6f2604b3477a3f273a4e019a232700000000 - prev_block
a5942372cc60477c8a276e59c8f1a3f58654ea2f6c4402bf1b18e48455b5b8f6 - merkle_root
4f10868b - timestamp
1c074752 - bits
00000000 - nonce
00 - txn_count of 0 Number of transaction entries, this value is always 0
0000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000 - ??
A solo miner increments Nonce until it overflows. Then it increments extraNonce and resets Nonce. extraNonce is located in the coinbase transaction, so changing it alters the Merkle root. extraNonce is reset based on the time.
For many potential blocks, there is no value of the nonce that will give a hash less than the target. When that happens, the node must alter something in the block header and try again. The timestamp is a good candidate, since it usually takes some time to try all 2^32 nonces. New transactions may have come in across the network that can be added to the tree too.
there was also a nonce in the Merkle tree calculations, It is in the generation transaction, which changes the Merkle hash.
In a pool, the pool server will hand out unique headers to each worker/request, by using the extraNonce and rehashing the tree, to prevent duplication of work and get better odds of finding a valid block.
The extranonce can be found in the coinbase data from a coinbase transaction.
This data can be interpreted as a script pushing data onto the stack and the extranonce is the second value.
{ |
can be interpreted as:
03 = push 3 bytes onto the stack
443b04 = 3 bytes pushed onto the stack <– Block index
03 = push 3 bytes onto the stack
858402 = 3 bytes pushed onto the stack <– The extranonce
06 = push 6 bytes onto the stack
2f503253482f = 6 bytes pushed onto the stack <– arbitrary data
EDIT: This format was defined by BIP34 and applies to blocks with version >= 2. I’m not sure how the extranonce was managed before that.
My guess is that the extranonce is 8 bytes max but is stored with a compressed representation for lower values.
It seems to confirm the script structure with the extranonce being the second value pushed onto the stack. I was puzzled by the first value but it may be the same value as the bits fields stored in the header.
矿机出现之后,挖矿速度得到极大提高,当前比特币矿机算力已经达到10T/秒级别。而getwork只给外部挖矿程序提供32字节共4G的搜索空间,如果继续使用getwork协议,矿机需要频繁调用RPC接口,这显然不可行。如今BTC和LTC节点都已经禁用getwork协议,转向更新更高效的getblocktemplate协议。
区块大小序列化后 <= 1MB,否则认为非法。
Getblocktemplate
you can change the extraNonce field
getblocktemplate协议诞生于2012年中叶,此时矿池已经出现。矿池采用getblocktemplate协议与节点客户端交互,采用stratum协议与矿工交互,这是最典型的矿池搭建模式。
Stratum mining protocol (STM)
官网 端口 3333
用来替代 getwork 协议
为什么要用 STM?
- HTTP,需要矿工驱动通讯,效率不高
- Ntime Rolling,无法满足更快的矿工的任务需求:当前协议只能修改 ntime 和 nonce。
- Long Polling,一个反向的模式
Methods (client to server)
mining.authorize
mining.authorize("username", "password") |
Methods (server to client)
…
GetBlockTemplate(GBT)
getblocktemplate协议诞生于2012年中叶,此时矿池已经出现。矿池采用getblocktemplate协议与节点客户端交互,采用stratum协议与矿工交互,这是最典型的矿池搭建模式。
矿池类型
目前比特币矿池主要分为两种类型:托管矿池和P2P矿池
托管矿池
P2Pool 矿池
P2Pool是一个点对点的矿池,没有中心管理人。
比特币核心开发人员Matt Corallo发布了比特币改善提案(Bitcoin Improvement Proposal)的草案,旨在通过采用新的挖矿协议进一步实现比特币挖矿的去中心化。
BetterHash挖矿协议
P2Pool works by decentralizing the functions of the pool server, implementing a parallel blockchain-like system called a share chain.
矿池通过专用挖矿协议协调成百上千的矿工。个人矿工在建立矿池账号后,设置他们的矿机连接到矿池服务器。他们的挖矿设备在挖矿时保持和矿池服务器的连接,和其他矿工同步各自的工作。这样,矿池中的矿工分享挖矿任务,之后分享奖励。
成功出块的奖励支付到矿池的比特币地址,而不是单个矿工的。一旦奖励达到一个特定的阈值,矿池服务器便会定期支付奖励到矿工的比特币地址。通常情况下,矿池服务器会为提供矿池服务收取一个百分比的费用。
参加矿池的矿工把搜寻候选区块的工作量分割,并根据他们挖矿的贡献赚取“份额”。矿池为赚取“份额”设置了一个低难度的目标,通常比比特币网络难度低1000倍以上。当矿池中有人成功挖出一块,矿池获得奖励,并和所有矿工按照他们做出贡献的“份额”数的比例分配。
矿池的核心工作是给矿工分配任务,统计工作量并分发收益。矿池将区块难度分成很多难度更小的任务下发给矿工计算,矿工完成一个任务后将工作量提交给矿池,叫提交一个share。假如全网区块难度要求Hash运算结果的前70个比特位都是0,那么矿池给矿工分配的任务可能只要求前30位是0(根据矿工算力调节),矿工完成指定难度任务后上交share,矿池再检测在满足前30位为0的基础上,看看是否碰巧前70位都是0。
矿池如何衡量每个人的贡献,既能公平分配奖励,又避免作弊的可能?答案是在设置一个较低难度的前提下,使用比特币的工作量证明算法来衡量每个矿工的贡献。
因此,即使是池中最小的矿工也经常能分得奖励,这足以激励他们为矿池做出贡献。通过设置一个较低的取得份额的难度,矿池可以计量出每个矿工完成的工作量。每当矿工发现一个小于矿池难度的区块头hash,就证明了它已经完成了寻找结果所需的hash计算。更重要的是,这些为取得份额贡献而做的工作,能以一个统计学上可衡量的方法,整体寻找一个比特币网络的目标散列值。成千上万的矿工尝试较小区间的hash值,最终可以找到符合比特币网络要求的结果。
矿池会根据每个矿工的算力情况分配不同难度的任务,矿池是如何判断矿工算力大小以分配合适的任务难度呢?调节思路和比特币区块难度一样,矿池需要借助矿工的share率,矿池希望给每个矿工分配的任务都足够让矿工运算一定时间,比如说1秒,如果矿工在一秒之内完成了几次任务,说明矿池当前给到的难度低了,需要调高,反之。如此下来,经过一段时间调节,矿池能给矿工分配合理难度,并计算出矿工的算力。
矿工连接到矿池服务器使得一个采矿协议⽐如Stratum(STM)或者GetBlockTemplate(GBT)。STM和GBT协议都创建包含候选区块头模板的区块模板。矿池服务器通过聚集交易,添加coinbase交易(和额外的随机值空间),计算MERKLE根,并连接到上一个块hash来建立一个候选区块。这个候选区块的头部作为模板分发给每个矿工。矿工用这个区块模板在低于比特币网络的难度下采矿,并发送成功的结果返回矿池服务器赚取份额。
矿池通过getblocktemplate协议与网络节点交互,以获得区块链的最新信息,通过stratum协议与矿工交互。此外,为了让之前用getwork协议挖矿的软件也可以连接到矿池挖矿,矿池一般也支持getwork协议,通过阶层挖矿代理机制实现(Stratum mining proxy)。须知在矿池刚出现时,显卡挖矿还是主力,getwork用起来非常方便,另外早期的FPGA矿机有些是用getwork实现的,stratum与矿池采用TCP方式通信,数据使用JSON封装格式
getblocktemplate遗留下来的几个问题:
矿工驱动:在getblocktemplate协议里,依然是由矿工主动通过HTTP方式调用RPC接口向节点申请挖矿数据,这就意味着,网络最新区块的变动无法及时告知矿工,造成算力损失。
数据负载:如上所述,如今正常的一次getblocktemplate调用节点都会反馈回1.5M左右的数据,其中主要数据是交易列表,矿工与矿池需频繁交互数据,显然不能每次分配工作都要给矿工附带那么多信息。再者巨大的内存需求将大大影响矿机性能,增加成本。
Stratum协议彻底解决了以上问题:
Stratum协议采用主动分配任务的方式,也就是说,矿池任何时候都可以给矿工指派新任务,对于矿工来说,如果收到矿池指派的新任务,应立即无条件转向新任务;矿工也可以主动跟矿池申请新任务。
现在最核心的问题是如何让矿工获得更大的搜索空间,如果参照getwork协议,仅仅给矿工可以改变nNonce和nTime字段,则交互的数据量很少,但这点搜索空间肯定是不够的。想增加搜索空间,只能在hashMerkleroot下功夫,如果让矿工自己构造coinbase,那么搜索空间的问题将迎刃而解,但代价是必要要把区块包含的所有交易都交给矿工,矿工才能构造交易列表的Merkleroot,这对于矿工来说压力更大,对于矿池带宽要求也更高。
Stratum协议巧妙解决了这个问题,成功实现既可以给矿工增加足够的搜索空间,又只需要交互很少的数据量,这也是Stratum协议最具创新的地方。