超硬核区块链算法仿真:联盟链PBFT多线程仿真实现 :c语言完全详解版

1 22年年底想用gpt做出一个pbft的算法仿真,到了25年终于可以结合gpt grok perplexcity deepseek等实现了!!!!!


1.1简化版

// 定义 Windows 版本,确保条件变量相关函数可用
#define _WIN32_WINNT 0x0600#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <locale.h>// 定义常量:节点数、请求数
#define NODE_COUNT 4         // 1 个主节点(编号 0)和 3 个副本
#define REQUEST_COUNT 10     // 模拟 10 个请求// 消息类型枚举:PBFT 的三个阶段
typedef enum {MSG_PREPREPARE,  // 主节点发送,初始广播请求MSG_PREPARE,     // 副本收到 Pre-Prepare 后回复 Prepare 消息MSG_COMMIT       // 副本收到 Commit 后回复 Commit 消息
} MsgType;// 消息结构体:用于节点间通信
typedef struct Message {int request_id;         // 请求编号MsgType type;           // 消息类型int sender;             // 发送节点编号struct Message *next;   // 链表指针(用于构建消息队列)
} Message;// 消息队列结构体:每个节点拥有一个独立的队列
typedef struct {Message *head;Message *tail;CRITICAL_SECTION cs;    // 互斥锁,保证队列操作的线程安全CONDITION_VARIABLE cv;  // 条件变量,用于等待队列不为空
} MessageQueue;// 初始化消息队列
void init_queue(MessageQueue *q) {q->head = q->tail = NULL;InitializeCriticalSection(&q->cs);InitializeConditionVariable(&q->cv);
}// 入队操作:将消息加入队列尾部
void enqueue(MessageQueue *q, Message *msg) {EnterCriticalSection(&q->cs);msg->next = NULL;if (q->tail == NULL) {q->head = q->tail = msg;} else {q->tail->next = msg;q->tail = msg;}WakeConditionVariable(&q->cv);LeaveCriticalSection(&q->cs);
}// 出队操作:若队列为空,则阻塞等待
Message* dequeue(MessageQueue *q) {EnterCriticalSection(&q->cs);while (q->head == NULL) {SleepConditionVariableCS(&q->cv, &q->cs, INFINITE);}Message *msg = q->head;q->head = msg->next;if (q->head == NULL)q->tail = NULL;LeaveCriticalSection(&q->cs);return msg;
}// 模拟网络延迟(简单随机延迟,单位毫秒)
DWORD simulate_delay() {return (DWORD)(rand() % 50);  // 延迟 0-49 毫秒
}// 全局消息队列数组:每个节点一个队列
MessageQueue nodeQueues[NODE_COUNT];// 非主节点(副本)的线程函数
DWORD WINAPI node_thread_proc(LPVOID param) {int node_id = *(int*)param;while (1) {Message *msg = dequeue(&nodeQueues[node_id]);// 检查终止信号:当 request_id 和 type 均为 -1 时退出if (msg->request_id == -1 && msg->type == (MsgType)-1) {free(msg);break;}// 模拟网络延迟Sleep(simulate_delay());// 副本处理消息:收到 Pre-Prepare 回复 Prepare;收到 Commit 回复 Commitif (msg->type == MSG_PREPREPARE) {Message *reply = (Message*)malloc(sizeof(Message));reply->request_id = msg->request_id;reply->type = MSG_PREPARE;reply->sender = node_id;enqueue(&nodeQueues[0], reply); // 回复发送给主节点(节点0)} else if (msg->type == MSG_COMMIT) {Message *reply = (Message*)malloc(sizeof(Message));reply->request_id = msg->request_id;reply->type = MSG_COMMIT;reply->sender = node_id;enqueue(&nodeQueues[0], reply);}free(msg);}return 0;
}int main() {// 设置控制台编码和区域,支持中文输出SetConsoleOutputCP(CP_UTF8);setlocale(LC_ALL, "zh_CN.UTF-8");srand((unsigned int)time(NULL));// 初始化每个节点的消息队列for (int i = 0; i < NODE_COUNT; i++) {init_queue(&nodeQueues[i]);}// 创建非主节点线程(节点1到 NODE_COUNT-1)HANDLE nodeThreads[NODE_COUNT - 1];int nodeIds[NODE_COUNT - 1];for (int i = 1; i < NODE_COUNT; i++) {nodeIds[i - 1] = i;nodeThreads[i - 1] = CreateThread(NULL, 0, node_thread_proc, &nodeIds[i - 1], 0, NULL);}// 定义 PBFT 共识阈值(对于 4 个节点,f = floor((n-1)/3)=1,因此阈值可以设为 2,即需要至少 2 个 Prepare/Commit 回复)int threshold = 2;// 模拟 PBFT 共识过程,每个请求依次执行for (int req = 0; req < REQUEST_COUNT; req++) {printf("\n====== 请求 %d ======\n", req);// 主节点(节点0)发送 Pre-Prepare 消息给所有副本for (int i = 1; i < NODE_COUNT; i++) {Message *msg = (Message*)malloc(sizeof(Message));msg->request_id = req;msg->type = MSG_PREPREPARE;msg->sender = 0;enqueue(&nodeQueues[i], msg);}// 主节点自身模拟处理 Pre-Prepare 延迟Sleep(simulate_delay());// 收集 Prepare 消息int prepareCount = 0;while (prepareCount < threshold) {Message *reply = dequeue(&nodeQueues[0]); // 从主节点的队列中取消息if (reply->request_id == req && reply->type == MSG_PREPARE) {prepareCount++;printf("收到 Prepare 消息,发送者: %d\n", reply->sender);}free(reply);}printf("Pre-Prepare 阶段完成,收到 %d 个 Prepare 回复\n", prepareCount);// 主节点发送 Commit 消息给所有副本for (int i = 1; i < NODE_COUNT; i++) {Message *msg = (Message*)malloc(sizeof(Message));msg->request_id = req;msg->type = MSG_COMMIT;msg->sender = 0;enqueue(&nodeQueues[i], msg);}// 主节点自身模拟处理 Commit 延迟Sleep(simulate_delay());// 收集 Commit 消息int commitCount = 0;while (commitCount < threshold) {Message *reply = dequeue(&nodeQueues[0]);if (reply->request_id == req && reply->type == MSG_COMMIT) {commitCount++;printf("收到 Commit 消息,发送者: %d\n", reply->sender);}free(reply);}printf("Commit 阶段完成,收到 %d 个 Commit 回复,共识达成!\n", commitCount);}// 发送终止信号给所有非主节点线程for (int i = 1; i < NODE_COUNT; i++) {Message *term = (Message*)malloc(sizeof(Message));term->request_id = -1;term->type = (MsgType)-1;term->sender = -1;enqueue(&nodeQueues[i], term);}// 等待所有非主节点线程结束WaitForMultipleObjects(NODE_COUNT - 1, nodeThreads, TRUE, INFINITE);// 清理:删除每个队列的互斥锁和关闭线程句柄for (int i = 0; i < NODE_COUNT; i++) {DeleteCriticalSection(&nodeQueues[i].cs);}for (int i = 0; i < NODE_COUNT - 1; i++) {CloseHandle(nodeThreads[i]);}printf("\nPBFT 仿真结束!\n");return 0;
}

1.2deepseek 改进版:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>// 可配置参数
#define MIN_NODES 4
#define DEFAULT_NODES 10
#define DEFAULT_REQUESTS 20
#define LOG_LEVEL 1// 自动计算共识阈值
#define CONSENSUS_THRESHOLD (2 * ((NODE_COUNT - 1) / 3))// 类型定义
typedef enum { MSG_REQUEST, MSG_PREPREPARE, MSG_PREPARE, MSG_COMMIT } MsgType;typedef struct Message {MsgType type;int sender;int request_id;int sequence;struct Message* next;
} Message;typedef struct {Message* head;Message* tail;CRITICAL_SECTION cs;CONDITION_VARIABLE cv;
} MessageQueue;typedef struct {int id;bool is_primary;int last_sequence;MessageQueue queue;int* received_prepare; // 动态数组int* received_commit;
} PBFTNode;// 全局变量
PBFTNode* nodes = NULL;
HANDLE* node_threads = NULL;
CRITICAL_SECTION log_cs;
int NODE_COUNT = DEFAULT_NODES;
int REQUEST_COUNT = DEFAULT_REQUESTS;
PerformanceStats perf_stats;// 简洁日志系统
#if LOG_LEVEL >= 1
void node_log(int node_id, const char* format, ...) {EnterCriticalSection(&log_cs);va_list args;printf("[N%d] ", node_id);va_start(args, format);vprintf(format, args);va_end(args);printf("\n");LeaveCriticalSection(&log_cs);
}
#else
#define node_log(...)
#endif// 初始化节点
void init_node(int id) {nodes[id].id = id;nodes[id].is_primary = (id == 0);nodes[id].last_sequence = -1;nodes[id].received_prepare = calloc(NODE_COUNT, sizeof(int));nodes[id].received_commit = calloc(NODE_COUNT, sizeof(int));InitializeCriticalSection(&nodes[id].queue.cs);InitializeConditionVariable(&nodes[id].queue.cv);nodes[id].queue.head = nodes[id].queue.tail = NULL;
}// 高效广播(减少内存复制)
void broadcast(int sender, Message* msg) {Message template = *msg;for (int i = 0; i < NODE_COUNT; i++) {if (i == sender) continue;Message* copy = malloc(sizeof(Message));*copy = template;EnterCriticalSection(&nodes[i].queue.cs);if (nodes[i].queue.tail) {nodes[i].queue.tail->next = copy;} else {nodes[i].queue.head = copy;}nodes[i].queue.tail = copy;WakeConditionVariable(&nodes[i].queue.cv);LeaveCriticalSection(&nodes[i].queue.cs);LOG_DEBUG(sender, "Sent to N%d", i);}free(msg);
}// 共识处理线程
DWORD WINAPI node_process(LPVOID param) {int id = *(int*)param;while (1) {// 消息处理逻辑(同前)// ...// 性能统计if (msg->type == MSG_COMMIT && count >= CONSENSUS_THRESHOLD) {InterlockedIncrement(&perf_stats.completed_requests);}}return 0;
}int main(int argc, char* argv[]) {// 解析命令行参数if (argc >= 2) NODE_COUNT = atoi(argv[1]);if (argc >= 3) REQUEST_COUNT = atoi(argv[2]);// 初始化系统InitializeCriticalSection(&log_cs);nodes = malloc(NODE_COUNT * sizeof(PBFTNode));node_threads = malloc(NODE_COUNT * sizeof(HANDLE));int* ids = malloc(NODE_COUNT * sizeof(int));for (int i = 0; i < NODE_COUNT; i++) {ids[i] = i;init_node(i);}// 启动线程for (int i = 0; i < NODE_COUNT; i++) {node_threads[i] = CreateThread(NULL, 0, node_process, &ids[i], 0, NULL);}// 性能统计perf_stats.start_time = clock();// 发送请求for (int req = 0; req < REQUEST_COUNT; req++) {broadcast(-1, &(Message){.type=MSG_REQUEST, .request_id=req});Sleep(100); // 控制请求速率}// 等待完成Sleep(1000); // 终止和清理// ...perf_stats.end_time = clock();print_performance_stats();return 0;
}

2  以下是调试和运行结果:


3.详细版本解释:

这个程序模拟了一个小型区块链网络:

节点:80个节点,其中节点0是主节点(负责发起请求),节点1到79是从节点(负责响应)。
目标:处理100个请求,通过PBFT的三个阶段(Pre-Prepare、Prepare、Commit)达成共识。
通信方式:每个节点有自己的消息队列,主节点和从节点通过队列传递消息,模拟网络通信。
并发性:使用多线程(79个从节点线程+1个主线程),模拟区块链节点的并行工作。
延迟:每个消息传递有0-10ms的随机延迟,模拟真实网络环境。
同步工具:使用互斥锁和条件变量,确保线程安全和消息顺序。
运行过程可以分为五个主要阶段:

初始化阶段:设置节点、队列和线程。
主节点发起请求:发送Pre-Prepare消息,启动共识。
从节点处理消息:接收并回复Prepare和Commit消息。
主节点收集回复:收集足够的消息,完成共识。
统计和清理:输出性能指标,释放资源。



 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38483.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【并发编程】聊聊forkJoin的原理和最佳实践

对于线程池来说&#xff0c;其实本质就是一个生产者消费者的模式&#xff0c;而通过竞争的方式从队列中获取任务执行。本质上其实就是按照任务级别进行处理&#xff0c;但是对于一些可以分而治之的任务&#xff0c;传统的线程池没有办法分治处理。一是无法对大任务进行拆分&…

【数据预测】基于遗传算法GA的LSTM光伏功率预测 GA-LSTM光伏功率预测【Matlab代码#91】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. 遗传算法GA2. 长短期记忆网络LSTM3. 基于GA-LSTM的光伏功率预测4. 部分代码展示5. 运行结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】 …

Java 填充 PDF 模版

制作 PDF 模版 安装 OnlyOffice 从 OnlyOffice 官网下载 OnlyOffice Desktop&#xff0c;安装过程很简单&#xff0c;一路下一步即可。用 OnlyOffice 制作 PDF 模版&#xff08;表单&#xff09; 使用 OnlyOffice 表单设计器&#xff0c;制作表单&#xff0c;如下图 注意命名…

使用安装 Kettle 教程 Pentoho 10.2.0.0-222 安装 连接mysql

流程 准备下载安装测试链接常见问题 准备 需要提前安装好 JDK 配置好环境变量 &#xff08;教程看前文&#xff09; 安装好mysql&#xff08;教程看前文&#xff09; 下载好pentaho链接数据库驱动 下载pentaho安装包 https://pentaho.com/wp-content/uploads/2024/04/three-s…

MySQL表的增加、查询、修改、删除的基础操作

MySQL表的增加、查询、修改、删除的基础操作 一、CRUD二、新增数据 insert2.1 单行数据 全列插入2.2 多行数据 指定列插入 三、查询 select3.1 全列查询&#xff08;select *&#xff09;3.2 指定列查询3.3 表达式查询3.4 去重&#xff1a;distinct3.5 带有排序的查询&#x…

Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站

开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组&#xff0c;开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App&#xff0c;登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…

Linux上位机开发实战(能用的开发板计算资源)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 大家所能想到的嵌入式上位机开发&#xff0c;如果是linux&#xff0c;同时涉及到嵌入式的话&#xff0c;一般都会认为是把pc linux的软件port到板子…

STM32中断

中断的基本概念 中断具体定义&#xff1a;操作系统课程里有清晰的阐述。 STM32中断&#xff1a;中断来了&#xff0c;主程序都得立即暂停&#xff0c;程序由硬件电路自动跳转到中断程序中。中断执行前&#xff0c;进行现场保护&#xff1b;中断执行后&#xff0c;会再还原现场…

maven在windows系统上的详细安装和配置

下载 Maven 安装包 去官网下载&#xff0c;下载链接 下载到指定位置&#xff0c;解压&#xff0c;之后在该目录下新建一个文件夹 【repository】&#xff0c;作为本地仓库 Maven 的配置 配置本地仓库 ① 打开上一步新建的目录 repository&#xff0c; 复制路径 ② 打开 con…

如何为AI开发选择合适的服务器?

选择适合的服务器可以为您的AI项目带来更高的效率&#xff0c;确保最佳性能、可扩展性和可靠性&#xff0c;从而实现无缝的开发与部署。 选择适合的AI开发服务器可能并不容易。您需要一台能够处理大量计算和大型数据集的服务器&#xff0c;同时它还需要符合您的预算并易于管理…

OpenCV中的矩阵操作

OpenCV中的矩阵操作主要围绕Mat类展开&#xff0c;涵盖创建、访问、运算及变换等。 1. 创建矩阵 ‌零矩阵/单位矩阵‌&#xff1a; Mat zeros Mat::zeros(3, 3, CV_32F); // 3x3浮点零矩阵 Mat eye Mat::eye(3, 3, CV_32F); // 3x3单位矩阵 自定义初始化‌&#xff1a…

【C++进阶】函数:深度解析 C++ 函数的 12 大进化特性

目录 一、函数基础 1.1 函数定义与声明 1.2 函数调用 1.3 引用参数 二、函数重载&#xff1a;同名函数的「多态魔法」&#xff08;C 特有&#xff09; 2.1 基础实现 2.2 重载决议流程图 2.3 与 C 语言的本质区别 2.4 实战陷阱 三、默认参数&#xff1a;接口的「弹性设…

spring boot 登入权限RBAC模式

首先准备好5张表 user_info表&#xff0c;用户的信息表 role表&#xff0c;角色表&#xff08;比如超级管理员、管理员、审核员、采购......&#xff09; 创建user_role表&#xff0c;user_info表&#xff0c;role表的中间表 注意了&#xff0c;role_id和user_id是 u…

C#里使用libxl来对列或行进行分组显示

有时候由于EXCEL里的行数很多, 需要把某些行进行隐藏起来,那么就需要使用到行或列进行隐藏的操作。 这时候需要使用函数GroupCols和GroupRows来对这些列或行进行分组。 分组不能出现交叉的情况,否则会抛出异常。 如下图所示: 可以使用下面的代码来输出上面的EXCEL: p…

LangChain 基础

一、LangChain 模块和体系 LangChain 是一个用于开发由大型语言模型&#xff08;LLMs&#xff09;驱动的应用程序的框架。 官方文档&#xff1a;https://python.langchain.com/docs/introduction/ LangChain 简化了LLM应用程序生命周期的每个阶段&#xff1a; 开发&#xf…

IDEA 快捷键ctrl+shift+f 无法全局搜索内容的问题及解决办法

本篇文章主要讲解IDEA、phpStrom、webStrom、pyCharm等jetbrains系列编辑器无法进行全局搜索内容问题的主要原因及解决办法。 日期&#xff1a;2025年3月22日 作者&#xff1a;任聪聪 现象描述&#xff1a; 1.按下ctrlshiftf 输入法转为了繁体。 2.快捷键ctrlshiftr 可以全局检…

2025年- G24-Lc98-217.包含重复(使用hashSet解决)-java版

1.题目描述 2.思路 思路一&#xff1a; 我的想法是直接用集合来判断&#xff0c;如果集合的元素不能添加说明之前已经存在这个元素&#xff0c;也就是发现了重复元素&#xff0c;所以返回false。 补充一&#xff1a; Map、ArrayList的定义和声明 3.代码实现 class Soluti…

MySQL事务全解析:从概念到实战

在数据库操作中&#xff0c;事务是一个至关重要的概念&#xff0c;它确保了数据的完整性和一致性。今天&#xff0c;就让我们深入探讨MySQL事务的方方面面&#xff0c;从基础概念到实际应用&#xff0c;全面掌握这一技能。 一、为什么需要事务 假设张三要给李四转账100元&…

CVPR 2025 | 文本和图像引导的高保真3D数字人高效生成GaussianIP

小小宣传一下CVPR 2025的工作GaussianIP。 arXiv&#xff1a;https://arxiv.org/abs/2503.11143 Github&#xff1a;https://github.com/silence-tang/GaussianIP 欢迎star, issue~ 摘要 文本引导的3D人体生成随着高效3D表示及2D升维方法&#xff08;如SDS&#xff09;的发展…

Model Context Protocol:下一代AI系统集成范式革命

在2023年全球AI工程化报告中,开发者面临的核心痛点排名前三的分别是:模型与业务系统集成复杂度(58%)、上下文管理碎片化(42%)、工具调用标准化缺失(37%)。传统API集成模式在对接大语言模型时暴露明显短板:RESTful接口无法承载动态上下文,GraphQL缺乏工具编排能力,gR…