Skip to content

Commit 987477e

Browse files
author
建平
committed
共识机制(块同步)
1 parent b86cdcc commit 987477e

3 files changed

Lines changed: 326 additions & 79 deletions

File tree

README.md

Lines changed: 147 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ void Blockchain::updateUTXOPool(const Block& block) {
12631263
### 保持一致性
12641264

12651265
* 所有全节点遵循同样的**共识规则**
1266-
* 当有新区块生成,会通过点对点网络广播;
1266+
* 当有==新区块生成==,会通过点对点网络广播;
12671267
* 节点在接收到新区块后:
12681268

12691269
* 验证区块(工作量、哈希、交易等);
@@ -1475,9 +1475,16 @@ make
14751475

14761476
#### 更新UTOX
14771477

1478-
#### 共识机制
14791478

14801479

1480+
#### 区块查找
1481+
1482+
区块链查找仅用于handleConsensusResult(见后),所以包含在此处,其实其应该是P2P_Node的基本功能。
1483+
1484+
- 根据区块高度查找(区块号)
1485+
- 根据区块Hash查找
1486+
1487+
#### 获取最小共识节点
14811488

14821489

14831490

@@ -2319,41 +2326,6 @@ p2p_node包含了一个Blockchain成员,其所有对区块链的操作都通
23192326
23202327
23212328
2322-
2323-
2324-
2325-
2326-
2327-
2328-
2329-
2330-
2331-
2332-
2333-
2334-
2335-
2336-
2337-
#### 共识机制
2338-
2339-
##### 共识投票
2340-
2341-
```c++
2342-
std::mutex consensus_mutex_;
2343-
std::map<std::string, std::pair<int, int>> consensus_votes_;
2344-
```
2345-
2346-
##### 区块查找
2347-
2348-
区块链查找仅用于handleConsensusResult(见后),所以包含在此处,其实其应该是P2P_Node的基本功能。
2349-
2350-
- 根据区块高度查找(区块号)
2351-
- 根据区块Hash查找
2352-
2353-
##### 获取最小共识节点
2354-
2355-
2356-
23572329
## 网络通讯进阶
23582330
23592331
先把3个线程改成3个进程跑起来吧
@@ -3275,6 +3247,144 @@ void P2PNode::connect(const std::string& host, int port) {
32753247
32763248
32773249
3250+
### 业务流程
3251+
3252+
3253+
3254+
#### 共识机制(块同步)
3255+
3256+
1. 让我详细解释一下这个共识机制的工作流程:
3257+
3258+
1. 共识发起:
3259+
3260+
- 当节点收到新的区块时,会发起共识
3261+
- 发起者会广播 `CONSENSUS_VOTE` 消息给所有节点
3262+
- 消息包含:区块哈希、完整区块内容、投票者ID,投票决定
3263+
3264+
2. 投票过程:
3265+
3266+
- 所有节点都会收到投票请求
3267+
- 每个节点需要验证区块的有效性
3268+
- 节点根据验证结果投赞成票或反对票
3269+
- 投票信息通过 `CONSENSUS_VOTE` 消息广播给所有节点
3270+
3271+
3. 投票检查:
3272+
3273+
​ 当收到投票消息时
3274+
3275+
- 如果本节点已经处理过该节点的投票,丢弃该消息,否则计入已投票节点
3276+
- 如果本节点已经给该块投过票了(不同节点广播的投票),跳过投票阶段
3277+
- 验证节点,如果通过则投赞成票,否则投反对票。记录该块当前节点已投票
3278+
- 更新投票记录
3279+
- 每次更新后检查是否达到共识阈值
3280+
3281+
4. 共识达成:
3282+
3283+
- 当赞成票比例超过阈值(比如2/3)时,认为达成共识
3284+
- 达成共识的节点会广播 `CONSENSUS_RESULT` 消息
3285+
- 消息包含:区块哈希、共识结果(通过/拒绝),区块信息,投票者ID(==怎么用==)
3286+
3287+
5. 共识结果处理:
3288+
3289+
- 所有节点收到共识结果后,根据结果决定是否将区块添加到链中
3290+
- 如果共识通过,区块被添加到链中
3291+
- 如果共识拒绝,区块被丢弃
3292+
3293+
6. 防止重复:
3294+
3295+
- 每个节点都维护
3296+
3297+
- 个投票记录表 `consensus_votes_`,记录每个区块的赞成票和反对票数量
3298+
- 个是否投票表voted_blocks_,记录每个块当前节点是否已经投票_
3299+
- 一个投票节点表voted_nodes_,记录每个块已投票节点记录
3300+
3301+
- 每个节点维护 `voted_blocks_` 记录已投票的区块
3302+
3303+
- 防止对同一个区块重复投票
3304+
3305+
- 确保共识过程的完整性
3306+
3307+
3308+
这个机制的特点:
3309+
3310+
1. 去中心化:所有节点都可以发起共识和投票
3311+
2. 透明性:所有投票都是公开的
3312+
3. 安全性:需要多数节点同意才能达成共识
3313+
4. 容错性:可以容忍部分节点故障或恶意行为
3314+
3315+
3316+
```c++
3317+
std::mutex consensus_mutex_;
3318+
std::map<std::string, std::pair<int, int>> consensus_votes_; // blockHash -> (赞成票数, 反对票数)
3319+
std::map<std::string, bool> voted_blocks_; // blockHash -> 是否已投票
3320+
std::map<std::string, std::set<std::string>> voted_nodes_; // blockHash -> 已投票的节点列表
3321+
```
3322+
3323+
##### 添加新块时触发投票
3324+
3325+
​ 节点收到新块添加NEW_BLOCK时发起投票
3326+
3327+
- 解析新块
3328+
3329+
- ==(0525补充)检查块是否已经在链上了,如果是则丢弃==
3330+
3331+
- 检查该块是否正在投票,如果是则丢弃该消息
3332+
3333+
- 本地验证区块,如果失败则丢弃
3334+
3335+
- 检查块是否已经在链上(==如果在链上上一步应该验证失败==)
3336+
3337+
- 广播共识投票(包括自己?==修改broadcastConsensusVote==)
3338+
3339+
3340+
3341+
##### 收到投票
3342+
3343+
节点收到CONSENSUS_VOTE消息,开始处理投票
3344+
3345+
- ==(0525补充)检查块是否已经在链上了,如果是则丢弃==(防止已经完成节点添加的节点收到其他节点因为网络延迟还在发送的投票消息)
3346+
- 创建一个块对象
3347+
- 验证此投票是否合法(消息携带的块HASH和新块的HASH是否一致)
3348+
- 检查==发送者==是否已经对此块投过票,避免重复投票
3349+
- 如果是直接返回
3350+
- 如果不是则将发送节点添加进本地该块的已投票节点(下次收到该节点对此块的投票丢弃)
3351+
3352+
- 检查本地是否已经投过票(如果本地已经投过则仅记录本次投票信息)
3353+
- 如果未投票,开始投票
3354+
- 验证块哈希(索引号,前一块的Hash值,块Hash验证,块难度,验证交易,验证MerkleRoot)
3355+
- 成功投赞成票
3356+
- 失败投反对票
3357+
- 标记本节点已经对该块发起过投票
3358+
- 如果已经投票标记已经投过票
3359+
- 验证通过则发起通过投票,否则发起拒绝投票
3360+
- 将此块计入已投票列表
3361+
- 记录投票信息
3362+
- 记录投票节点
3363+
- 检查共识
3364+
3365+
##### 共识检测
3366+
3367+
- 获取当前投票总数
3368+
- 比较投票数是否满足最小共识节点数
3369+
- 比较投票通过数的比率是否达到阈值
3370+
- 如果超过则广播发送共识通过(包含块信息)
3371+
- 否则广播共识拒绝
3372+
3373+
##### 共识结果
3374+
3375+
- 解析块和信息
3376+
- 查看是否达成共识,如果是添加节点
3377+
- 检查本地是否存在该节点,如果是则跳过
3378+
- 检查是否包含块信息,如果不是则跳过
3379+
- 创建块,并验证块
3380+
- 如果验证失败则跳过
3381+
- 如果验证成功则将块加入本地
3382+
- 清理投票记录(指定块)
3383+
- 清理投票块记录(指定块)
3384+
- 清理投票节点记录(指定块)
3385+
3386+
#### UTXO同步
3387+
32783388

32793389

32803390

0 commit comments

Comments
 (0)