Skip to content

Commit

Permalink
finish stratum protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
KaKeimei committed Jun 2, 2024
1 parent f5f0c7a commit e48fb7e
Showing 1 changed file with 189 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,192 @@ sidebar_position: 10
---

# Stratum挖矿协议

本文介绍Stratum挖矿协议,当前最主流的加密货币挖矿协议。

## 什么是Stratum挖矿协议?

Stratum挖矿协议是一种用于加密货币挖矿的协议,旨在优化矿工与矿池之间的通信。该协议由Slush Pool在2012年引入,取代了早期的HTTP挖矿协议,解决了效率和扩展性的问题。

在Stratum协议出现之前,加密货币挖矿主要使用[RPC挖矿协议](../config/set-up-your-own.md),例如`getwork`, `getblocktemplate`等。这种协议在早期的比特币挖矿中非常常见,但随着挖矿难度和矿工数量的增加,RPC协议暴露出了一些显著的缺点。

### RPC(或HTTP)协议挖矿的方式与缺陷

#### 挖矿流程

1. **连接矿池**
- 矿工通过RPC连接矿池的服务器,通常使用标准的RPC POST请求来获取挖矿任务。

2. **任务请求**
- 矿工发送包含钱包地址和其他相关信息的请求,向矿池索要挖矿任务。
- 矿池返回一个包含区块头、目标难度等信息的任务。

3. **计算哈希**
- 矿工开始使用给定的数据进行哈希计算,试图找到符合目标难度的哈希值。

4. **提交结果**
- 当矿工找到有效的哈希值时,使用RPC POST请求将结果提交给矿池。
- 矿池验证结果,如果有效,则将其纳入区块链。

5. **循环任务**
- 由于RPC协议是无状态的,矿工在每次任务完成后需要重新建立连接请求新任务。

#### RPC协议的缺点

1. **连接开销高**
- RPC协议是无状态的,每次获取任务和提交结果都需要重新建立连接,这增加了网络开销和延迟。
- 频繁的连接建立和关闭操作,导致矿工和矿池服务器的资源浪费。

2. **实时性差**
- RPC协议无法实时推送新任务,矿工可能会因为任务更新不及时而进行无效计算。
- 矿工在获取新任务的过程中可能会浪费计算资源,降低挖矿效率。

3. **延迟问题**
- 由于每次任务请求和结果提交都需要重新建立连接,网络延迟会显著影响挖矿效率。
- 矿工在高延迟网络环境下,可能会错失有效任务,导致收益减少。

4. **扩展性差**
- RPC协议设计用于网页浏览,初衷并非高频次的任务请求和结果提交,难以适应大规模矿工的高并发需求。
- 随着矿工数量增加,矿池服务器的负载会显著增加,导致性能瓶颈。
- 随着区块数量增大,生成一次工作任务所需要耗费的网络带宽和计算资源也会增加。

5. **容错性低**
- RPC协议缺乏对连接中断的容错处理,矿工在网络波动时容易丢失任务或结果,影响挖矿的稳定性。
- 矿池和矿工之间的通信容易受到网络故障和攻击的影响。


## Stratum协议细节

[Stratum](https://en.bitcoin.it/wiki/Stratum_mining_protocol)协议通过优化矿工与矿池之间的通信,解决了RPC协议的缺点,提高了挖矿效率和稳定性。它采用长连接方式,使用JSON-RPC格式进行通信,实现了实时任务更新、容错性强和扩展性好等优点。

1. **连接建立**
- 矿工通过TCP连接矿池的Stratum服务器,并使用JSON-RPC格式进行通信。
- 连接成功后,矿工向矿池发送“mining.subscribe”请求,以订阅任务。

2. **任务分配**
- 矿池接收到订阅请求后,发送“mining.notify”消息,包含挖矿任务的详细信息,如区块头、目标难度等。
- 矿工收到任务后,开始进行哈希计算,寻找符合目标难度的解。

3. **提交结果**
- 当矿工找到符合条件的哈希值时,向矿池发送“mining.submit”消息,提交计算结果。
- 矿池验证结果,如果符合要求,则将其纳入区块链。

4. **任务更新**
- 矿池会周期性地发送新的任务给矿工,确保矿工始终在最新任务上进行计算。
- 通过“mining.notify”消息,矿池可以动态调整任务参数,提升挖矿效率。

### 协议优势

1. **高效通信**
- Stratum协议采用长连接方式,减少了HTTP协议中频繁建立和关闭连接的开销。
- 使用轻量级的JSON-RPC格式,使得消息传输更加高效。

2. **实时任务更新**
- 矿池能够实时向矿工推送新任务,确保矿工始终在最新的区块数据上进行计算,避免无效工作。
- 动态调整难度参数,提高挖矿效率和公平性。

3. **容错性强**
- Stratum协议支持多次尝试提交结果,容错性强,确保矿工的工作不会因为偶尔的网络波动而丢失。
- 支持冗余服务器,矿工可以在主服务器故障时自动切换到备用服务器,保证挖矿不中断。

4. **扩展性好**
- Stratum协议设计简洁,易于扩展,可以支持多种加密货币和不同的挖矿算法。
- 矿池可以根据需求开发定制化的Stratum服务器,以适应不同的矿工和硬件配置。

5. **易于分割任务**
- Stratum协议将挖矿任务分割为多个小任务,矿工可以并行处理这些小任务,提高挖矿效率。矿工无需提交一整个区块所需要的工作量证明,而是可以分别提交每个小任务的工作量证明。这样可以让低算力的矿工也有机会获得挖矿奖励。
- 通过Merkle树的性质,挖矿所需的数据量是对数级别的,而非线性级别的,降低了带宽和负载。

6. **支持AsicBoost**
- Stratum协议支持AsicBoost技术,通过扩展协议和消息类型,为矿工提供更高效的挖矿方式。
- 矿池可以通过Stratum协议向矿工发送AsicBoost相关的配置信息,实现更高效的哈希计算。

## Stratum交互例

以下是一个简单的Stratum挖矿协议交互示例,包括矿机订阅、认证、任务推送和提交结果等过程。

以下所有报文均使用\n做为行结束符。

----------

矿机订阅:
```json
{"id": 1, "method": "mining.subscribe", "params": []}
```

服务器回应:
```json
{"id": 1, "result": [ [ ["mining.set_difficulty", "b4b6693b72a50c7116db18d6497cac52"], ["mining.notify", "ae6812eb4cd7735a302a8a9dd95cf71f"]], "08000002", 4], "error": null}
```

如果没有收到该回应,则可能原因有:
1. 连接的不是Stratum服务器。
2. Stratum服务器工作状态异常。
3. 请求报文的行结束符不为\n,在粘贴多行文本到终端时可能发生这种现象,此时请单行粘贴并手动按回车。

----------

订阅成功后,矿机进行矿工名认证
```json
{"params": ["把它替换为你真实的矿工名", "password"], "id": 2, "method": "mining.authorize"}
```

服务器回应:
```json
{"error": null, "id": 2, "result": true}
```

若回应不为true,则 result 字段包含错误信息。
若没有收到任何回应,可能的原因有:
1. Stratum Server状态异常。
2. 行结束符问题。
3. 订阅和认证相隔太久,服务器放弃认证矿机。

----------

认证成功后,Stratum Server会主动推送挖矿难度和挖矿任务等信息,如下:

(难度)
```json
{"id": null, "method": "mining.set_difficulty", "params": [16384]}
```

(任务)
```json
{"params": ["0", "4d16b6f85af6e2198f44ae2a6de67f78487ae5611b77c6c0440b921e00000000", "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008", "072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000", [], "00000002", "1c2ac4af", "504e86b9", false], "id": null, "method": "mining.notify"}
```


如果没有收到难度推送,则说明Stratum Server工作不正常。
如果没有收到任务推送,则说明Stratum Server可能此时没有可推送给你的任务。对于BTCPool,可能是它没有从Kafka中读取到可用的任务,这可能是因为jobmaker没有产生对应的任务,或者kafka状态异常。当然,也有可能是Stratum Server状态异常。

----------

当矿机挖到一个符合矿池设定难度的share之后,它会进行share提交:
```json
{"params": ["slush.miner1", "0", "00000001", "504e86ed", "b2957c02"], "id": 4, "method": "mining.submit"}
```

服务器回应:
```json
{"error": null, "id": 4, "result": true}
```

若result不为true,则会包含拒绝该share的理由。

----------
请注意,不是每个submit都会挖到区块。对于一个正常的矿池来说,矿机提交的大部分submit都是挖不到区块的,但是偶尔个别的submit达到了全网难度要求,因此能够挖到区块。

当矿机挖到区块时,矿机的提交动作和平常不会有什么不同。但是,矿机和矿池均可对share难度和job中的bits/target进行比较来发现它挖到了一个符合全网难度的share。

对于联合挖矿也是如此,检查share难度是否满足job中联合挖矿币种的难度。若正在联合挖多个币种,只需检查是否满足最低难度。

需要注意的是,联合挖矿的币种可能比正在挖掘的比特币难度高,或者难度低。

若比特币难度高,则挖到比特币区块则必然挖到联合挖矿币种区块,而反过来则不一定。

若联合挖矿币种难度高(比如BCH联合挖掘域名币),则在挖到比特币时不一定能挖到联合挖矿币种,但反过来则是一定能挖到。

## 总结

Stratum挖矿协议通过优化矿工与矿池之间的通信,提高了挖矿效率和系统的稳定性。它的高效通信、实时任务更新、强大的容错性和良好的扩展性,使得它成为目前加密货币挖矿的主流协议。随着技术的发展,Stratum协议也在不断演进,进一步提升挖矿的效率和安全性。

0 comments on commit e48fb7e

Please sign in to comment.