# 矿池挖矿

## 独立挖矿 <a href="#du-li-wa-kuang" id="du-li-wa-kuang"></a>

如上所述，独立矿工通常使用bitcoind挖矿。他们使用的挖矿软件周期性的调用bitcoind，使用getblocktemplate获取新的交易。它提供了coinbase交易通常发送到的新的交易列表和公钥。

![](https://3241666809-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7bMYffAbmPfKcZL6Ma%2Fsync%2F4d97fde35c0afa44518e35db776423884471d6b9.svg?generation=1589798405181729\&alt=media)

挖矿软件利用模板来构建一个块和创建一个块的头部，接着它把长度为80字节的块头发送到挖矿的硬件部分（如ASIC），同时发送的还有目标门限（难度系数）。挖矿硬件通过暴力方式尝试每一个可能的块头的值并产生相应的哈希值。

如果产生的所有的值都高于门限，挖矿硬件将从挖矿软件处获取一个新的块头。这个块头的获得通过添加额外的临时数据到coinbase交易的coinbase字段。另一方面，如果找到的一个哈希值低于门限，挖矿硬件返回块头和临时数据给挖矿软件。后者将头和块结合起来，并将完整的块发送到bitcoind，等待bitcoind将其广播出去并可能在不久的将来添加到块链中。

## 矿池挖矿 <a href="#kuang-chi-wa-kuang" id="kuang-chi-wa-kuang"></a>

矿池的矿工遵循着相似的工作流程，如下图所示，它允许矿池主根据矿工的工作份额支付工资。矿池通过bitcoind连接网络来获得新的交易。使用后面讨论的方法之一，每个矿工的采矿软件都与矿池连接，并取得它需要的信息来构建区块标头。

![](https://3241666809-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7bMYffAbmPfKcZL6Ma%2Fsync%2F16cf0e11dc5271a4b61d99335f96a3a41dba9907.svg?generation=1589798405298537\&alt=media)

在这种集中开采的方式中，矿池设置目标门槛比网络难度大了好几个数量值（难度较低）。这将导致采挖矿机返回许多符合纳入条件的Hash值的块链头，而不是那些不符合目标的Hash.这就能够证明（一般而言）矿工查出了Hash值出现的百分之一可能性。

接着，矿工将需要验证的低于目标的块头信息副本发送到矿池，而在 Merkle root中提及的交易区块对于矿池来说是有效的（这通常意味着coinbase交易必须支付矿池的费用。 ）

矿工发送矿池的数据称为一个份额(share )，因为它证明了矿工所做的工作份额。有时候，矿池会接收到低于全网算力目标的的份额——矿池会将它们添加到网络块链中。

那挖矿获得的区块奖励和产生的交易费用是支付给矿池的。矿池根据矿工的工作份额支付部分款项的。例如，如果矿池的目标门槛比全网目标门槛低100倍， 即平均每一个成功的区块需要产生100个份额，所以矿池将支付每个份额所得款项的百分之一。基于这个基本的分配系统系统，不同的矿池使用不同的奖励分配系统。

## 区块原型 <a href="#qu-kuai-yuan-xing" id="qu-kuai-yuan-xing"></a>

在单独挖坑和矿池挖矿中，挖矿软件都要获取必要的信息来构建块头。本小节无法以线性的方式介绍，这些信息是如何传播和使用的。然而，在真实实现中，并行线程和队列是用来保持ASIC hashers工作达到最大算力的。

### getwork RPC <a href="#getwork-rpc" id="getwork-rpc"></a>

最早且最简单的方式是现在已经弃用的核心挖矿协议是getwork RPC，它向矿工直接构建块头。由于一个块头只包含一个4个字节的随机字符串（nonce），只能支持4.0 GH(gigahashes)，现在的许多矿工要在每秒做几十个或几百个getwork的请求。单独挖坑的矿工仍然可以使用getwork，但现在大多数的矿池不建议或不允许使用它。

### getblocktemplate RPC <a href="#getblocktemplate-rpc" id="getblocktemplate-rpc"></a>

getblocktemplate RPC是经过改进的一种挖矿方式，这种方式给挖矿软件提供了更多信息：

1. 需要支付给矿池或者单独挖矿矿工bitcoind 钱包的coinbase交易的费用信息。
2. bitcoind钱包提供的交易信息或矿池建议需要包含的交易信息，允许挖矿软件检查交易，选择性地添加额外交易和去除非必须的交易。
3. 其他为了下一个区块构建区块标头所需的信息：区块的版本，前一个块Hash值和位（目标）。
4. 矿池当前接受份额(share)的目标阈值。 （对于单独挖矿的矿工，就是全网的算力目标。 ）

利用收到的交易，采矿软件在coinbase的额外nonce字段上增加了一个nonce，然后把所有的交易转换成Merkel树,来推导在区块标头中用到的Merkle root。每当额外的nonce字段需要改变，采矿软件就会重建Merkle的必要部分并更新块头中的时间和Merkle root的区域。

和所有的bitcoind RPC一样， getblocktemplate通过HTTP发送。为了确保他们获得的是最新的工作，大部分矿工用HTTP longpoll来使一个getblocktemplate要求随时保持开放。这就意味着当P2P网络上的任何矿工发布出一个新的区块或是矿池想要发送更多的交易到挖矿软件的时候，矿池能够及时将一个新的getblocktemplate发送给矿工。

### Stratum <a href="#stratum" id="stratum"></a>

Stratum mining protocol 是一种广泛使用的替代getblocktemplate的挖矿协议。Stratum侧重于给矿工自己构建标头所需的最少信息：

1. 构建一个coinbase交易需要支付矿池所需的信息。
2. 当coinbase交易更新，有了一个新的额外nonce，为了创造一个新的 Merkle root，Merkle树上的一部分需要被重新散列。而Merkle树的其它部分，如果存在的话，将不被发送。这样能够有效地限制在数据量，需要被发送的数据总量（最多）在大约一千字节。
3. 为构建下一个区块块头的非Merkle root的所有其他所需信息。
4. 矿池接受份额的当前目标阈值。

利用收到的coinbase交易，挖矿软件在coinbase的额外nonce字段上增加了一个nonce，对coinbase交易进行散列，并把Hash值添加到接收的部分Merkle树上。因为需要创建Merkle root，该树又被散列，Merkle root会被添加到块头信息中。每当额外的nonce字段需要改变，挖矿软件就更新和重新散列coinbase的交易，重建Merkle root，并更新标头的Merkle root区域。

和getblocktemplate不同，用Stratum的矿工无法在他们目前挖掘的区块上检查或添加交易。还有就是 ，Stratum协议直接使用双向TCP套接字，因此当新的区块在P2P网络中发布，矿工们并不需要使用HTTP longpoll来确保获得矿池的即时更新。

资源：欲了解更多信息，请参阅GPLv3许可下的[BFGMiner](https://github.com/luke-jr/bfgminer)挖掘软件或AGPLv3许可下的[Eloipool](https://gitorious.org/bitcoin/eloipool)采矿软件。还有许多其他的挖矿的程序，但它们很多都是BFGMiner或Eloipool的分支。
