cpp 区块链模拟示例(二)工程代码解析
/*
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
技术交流群 群号码:432336863
欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
部分老代码存放地点
http://www.oschina.net/code/list_by_user?id=614253
*/
书接上文
我们先来看区块的结构
1 class Block { 2 public: 3 string sPrevHash; //记录上个块的哈希值 4 Block(uint32_t nIndexIn, const string &sDataIn); //构造函数 5 string GetHash(); //获取哈希函数 6 void MineBlock(uint32_t nDifficulty); //挖矿函数 7 private: 8 uint32_t _nIndex; //该区块的索引值 9 int64_t _nNonce; //区块随机数 用于哈希值的产生 10 string _sData; //区块描述字符 11 string _sHash; //区块哈希值 12 time_t _tTime; //创建时间 13 string _CalculateHash() const; //哈希值计算函数 14 };
区块结构很清晰。 一个区块就是一个创建时间、描述字符、区块随机数字等数据组成。
我们要创建一个区块就是根据创建时间、描述字符、区块随机数字等数据来计算出一个哈希值(_CalculateHash函数的功能)。
inline string Block::_CalculateHash() const { stringstream ss; ss << _nIndex << _tTime << _sData << _nNonce << sPrevHash; return sha256(ss.str()); }
由于_nNonce与创建时间是一值在变化的,_CalculateHash()会产生一个个的哈希。
在MineBlock()函数中对这些哈希进行检测,看看是否符合标准,一旦符合标准,那么久诞生了一个区块。
这里的MineBlock()函数中,根据设置的DifficultyNum,来检测哈希数值前DifficultyNum位是否为零,只有符合标准才是产生的区块的可使用的哈希值
随即产生的哈希值中,前DifficultyNum位为零,只在一定概率下才产生。 这也是为了限制区块的产生速度,在本次区块链技术模拟中,我们称之为"工作量证明"
void Block::MineBlock(uint32_t nDifficulty) { char cstr[DifficultyNum + 1]; for (uint32_t i = 0; i < DifficultyNum; ++i) { cstr[i] = '0'; } cstr[DifficultyNum] = '\0'; string str(cstr); do { _nNonce++; _sHash = _CalculateHash(); } while (_sHash.substr(0, nDifficulty) != str); cout << "Block mined: " << _sHash << endl; }
Block 结构体中 sPrevHash就是记录该区块的上一个区块的哈希值。区块链技术中使用一种方法将哈希值与区块一一对应。
这样知道一个区块和区块中的sPrevHash。通过查找可以依次遍历区块链中的每个区块。这些有关联的区块也正是使用这种方法组成了区块链.
区块链结构体如下
class Blockchain { public: Blockchain(); //区块链构造函数 void AddBlock(Block bNew); //区块链添加区块函数 private: uint32_t _nDifficulty; //难度值 vector<Block> _vChain; //记录区块链 Block _GetLastBlock() const; //获取最后一个区块 };
大致的示意图如下
我们的模拟文章中,区块链使用了vector<Block> _vChain来记录每个区块,每个区块中都有自己在这个vector中的索引_nIndex,这样查找起来更简单快捷。
区块链创建的时候会插入一个索引为零,描述字符为" Genesis Block "的区块,称之为创始块. 创世块与其他块的区别是交易的输入与输出,这个在后继章节再详细介绍。
AddBlock()与_GetLastBlock()相对比较简单,_GetLastBlock()就是返回vector<Block> _vChain的最后一个元素。
AddBlock()就是通过挖矿产生一个区块,放入到记录vector<Block> _vChain中。当然要记得设置该块的sPrevHash为之前区块链中最后一个块的哈希值.
Blockchain::Blockchain() { _vChain.emplace_back(Block(0, "Genesis Block")); _nDifficulty = DifficultyNum; } void Blockchain::AddBlock(Block bNew) { bNew.sPrevHash = _GetLastBlock().GetHash(); bNew.MineBlock(_nDifficulty); _vChain.push_back(bNew); } Block Blockchain::_GetLastBlock() const { return _vChain.back(); }
《build-a-blockchain-with-c》 的讲解和VC工程的建立就到此为止。
相对《用 Go 构建一个区块链》 ,《build-a-blockchain-with-c》代码量少而且简单。
下面的章节我们将进行 《用 Go 构建一个区块链》的c++化 并讲解代码内容
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
2016-08-06 模板学习实践三 functor
2016-08-06 模板学习实践二 pointer