比特币C++代码实现

【比特币C++代码实现】这是我最近写的一个近乎于完整的模拟比特币的代码实现 , 实际上还不够完整 , 不过已经能实现打包交易进入区块 , 然后挖矿了 。 这个程序是只有一个节点在挖矿 , 所以暂时也不涉及分布式系统的东西 , 还算比较简单容易理解 。 这个程序就是整个网络中一个节点的视角 。 分享出来希望对大家有所帮助 。
部署过程就是把代码统统贴过去 , 要注意的就是代码中有两个文件的路径 , 要手动改一下 , 代码中有两个文件的路径 , 要手动改一下 , 代码中有两个文件的路径 , 要手动改一下 , 重要的事情说三遍 , 然后就可以运行 , 观察比特币挖矿过程啦!有问题欢迎提问 。
BloCKchain.h这个没什么说的 , 创建一个区块链类
#pragma once#include"Block.h"#include<vector>//向量库class Blockchain{public: Blockchain();//默认构造函数 void AddBlock(Block bNew);//增加区块函数 uint32_t _nDifficulty;//难度值 vector<Block> _vChain;//保存区块的变量 Block _GetLastBlock() const;//获取最新的区块 , 由const关键字 , 表示输出的内容不可更改};Blockchain.cpp修改难度值在这里修改Blockchain的构造函数中的nDifficulty就可以了 。
#include"Blockchain.h"Blockchain::Blockchain(){ _vChain.emplace_back(Block(0, "Genesis Block")); _nDifficulty = 4;//难度值设置3基本上秒出结果 , 4可以看出差距 , 5大约要等2分钟左右 。 }void Blockchain::AddBlock(Block bNew){ bNew.sPrevHash = _GetLastBlock().GetHash(); bNew.MineBlock(_nDifficulty); _vChain.push_back(bNew); bNew.WriteBlcokToTXT();//调用区块类中的写文件方法} Block Blockchain::_GetLastBlock() const{ return _vChain.back();}Block.h这里是声明区块类
#pragma once#include<cstdint>//包含了uint32_t等无符号整型#include<iOStream>//标准输入输出库#include <fstream>using namespace std;static time_t first_time = 0;//这个地方是为了记录每个区块产生距离第一个区块的时间而设置的全局变量//创建区块类class Block{public: string sPrevHash;//前一个区块的哈希值 Block(uint32_t nIndexIn, const string& sDataIn);//构造函数 string GetHash();//返回哈希值 void MineBlock(uint32_t nDifficulty);//挖矿 , 其参数nDifficulty表示指定的难度值 void NoMineBlock();//不挖矿直接添加区块 uint32_t _nIndex;//区块索引值 , 第几个区块 , 从0开始计算 int64_t _nNonce;//区块随机数 string _sData;//区块描述字符 string _sHash;//区块Hash值 time_t _tTime;//区块生成时间 string _CalculateHash() const;//计算Hash值 , const保证输出的函数值不能被改变 。 void WriteBlcokToTXT();//将区块数据写入到TXT文件中};Block.cpp
#include"Block.h"#include"sha256.h"#include"time.h"#include<sstream>Block::Block(uint32_t nIndexIn, const string& sDataIn) :_nIndex(nIndexIn), _sData(sDataIn)//构造函数Block的两个参数为nIndexIn和sDataIn , 分别赋值到Block中的_nIndex和_sData(构造函数初始化用法){ _nNonce = -1;//Nounce设置为-1 _tTime = time(nullptr);//设置时间 if (nIndexIn == 0)//此处整个时间记录下来是为了记录当前区块生成所需要的时间 , 而不是当前时间 first_time = _tTime;}string Block::GetHash()//返回哈希值函数的实现{ return _sHash;}void Block::MineBlock(uint32_t nDifficulty)//挖矿函数 , 参数为难度值 。 { //char cstr[nDifficulty + 1]; char cstr[10 + 1];//这个数组实际上设置多大都可以 , 但是要大于nDifficulty的值 for (uint32_t i = 0; i < nDifficulty; ++i)//填充数组 , 使数组的前nDifficulty位都为0 , 作为难度 。 { cstr[i] = '0'; } cstr[nDifficulty] = '\0'; string str(cstr);//创建一个string类的对象 , 初始化为cstr(将字符串数组转换为string类对象)  do { _nNonce++; _sHash = _CalculateHash();  } while (_sHash.substr(0, nDifficulty) != str);//substr表示从下标0开始--->nDifficulty的内容 //要寻找一个Nounce使得总体哈希值的前n位的0(即0的个数)和难度值的个数相同 , 则挖矿成功 。 cout << "Block mined:" << _sHash << endl;} inline string Block::_CalculateHash() const{ stringstream ss;//该对象可以通过<<接收多个数据 , 保存到ss对象中 , 并通过str方法 , 将内容赋给一个string对象 ss << _nIndex << _tTime << _sData << _nNonce << sPrevHash; //return sha256(ss.str()); return sha256(sha256(ss.str()));} void Block::WriteBlcokToTXT()//将生成的区块数据输出到一个txt文档中来保存路径自己改{ ofstream outfile("out.txt", ios::app);//此处修改保存区块数据的路径 outfile <<"Index:"<<_nIndex<<endl; outfile << "Nonce:" << _nNonce << endl; outfile << "_sData:" << _sData << endl; outfile << "_sHash:" << _sHash << endl; outfile << "sPrevHash:" << sPrevHash << endl; outfile << "_tTime:" << _tTime - first_time << endl; outfile << endl; outfile.close();}

推荐阅读