cpp 区块链模拟示例(一)工程建立
/*
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
技术交流群 群号码:432336863
欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
部分老代码存放地点
http://www.oschina.net/code/list_by_user?id=614253
*/
今天,我将开启一个使用c++模拟区块链的系列,记录自己学习区块链与实践的心得体会.
文章将参考《一步步教小白使用C++构建区块链》(c++语言)
《用 Go 构建一个区块链 ---- Part 1: 基本原型》 (go语言) 等博客文,
通过使用c++编写和讲解一个简单的区块链代码,来加深自己对区块链原理的理解。
区块链中大量使用哈希算法。
算法将参与需要计算的整体内容全部作为元素添加至哈希计算中,最后得出一个独一无二的计算结果。
他的好处在于,可以用来验证一个文件没有被任何人更改。如果同时拥有待验证内容和哈希计算的结果,那么你可以很快验证自己的待验证内容是否正确。同时,正确内容遭到刻意的修改而计算出正确的哈希结果这种事情几乎不存在。
在这个示例中 我们使用来自Zedwood的C++ sha256函数提供我们需要的哈希计算,该链接中有sha256.h,sha256.cpp和LICENSE.txt文件,我们将它们保存在项目文件夹中。
前言少叙,开始建立工程。使用工具为vs2017,环境为windows操作系统.
创建一个窗口程序,名字叫做MyBlockChainCppSample.如图

建成后,MyBlockChainCppSample.cpp就是main文件包含main入口函数,暂时不必管它.如图

我们接下来创建区块和区块链的结构说明和实现。
区块的结构放在Block.h,由Block.cpp实现。
区块链的结构放在Blockchain.h,由Blockchain.cpp实现.
还有刚才提到的sha256.h,sha256.cpp和LICENSE.txt也要添加进工程中.
#pragma once #include <cstdint>
#include <iostream> using namespace std; #define DifficultyNum 4 class Block {
public:
string sPrevHash; //记录上个块的哈希值
Block(uint32_t nIndexIn, const string &sDataIn); //构造函数
string GetHash(); //获取哈希函数
void MineBlock(uint32_t nDifficulty); //挖矿函数
private:
uint32_t _nIndex; //该区块的索引值
int64_t _nNonce; //区块随机数 用于哈希值的产生??
string _sData; //区块描述字符
string _sHash; //区块哈希值
time_t _tTime; //创建时间
string _CalculateHash() const; //哈希值计算函数
};
Block.h
#include "Block.h"
#include "sha256.h"
#include <time.h>
#include <sstream> Block::Block(uint32_t nIndexIn, const string &sDataIn) : _nIndex(nIndexIn), _sData(sDataIn) {
_nNonce = -;
_tTime = time(nullptr);
} string Block::GetHash() {
return _sHash;
} void Block::MineBlock(uint32_t nDifficulty) {
char cstr[DifficultyNum + ];
for (uint32_t i = ; i < DifficultyNum; ++i) {
cstr[i] = '';
}
cstr[DifficultyNum] = '\0';
string str(cstr);
do {
_nNonce++;
_sHash = _CalculateHash();
} while (_sHash.substr(, nDifficulty) != str);
cout << "Block mined: " << _sHash << endl;
} inline string Block::_CalculateHash() const {
stringstream ss;
ss << _nIndex << _tTime << _sData << _nNonce << sPrevHash;
return sha256(ss.str());
}
Block.cpp
#pragma once #include <cstdint>
#include <vector>
#include "Block.h" using namespace std; class Blockchain {
public:
Blockchain(); //区块链构造函数
void AddBlock(Block bNew); //区块链添加区块函数
private:
uint32_t _nDifficulty; //难度值
vector<Block> _vChain; //记录区块链
Block _GetLastBlock() const; //获取最后一个区块
};
Blockchain.h
#include "Blockchain.h"
Blockchain::Blockchain() {
_vChain.emplace_back(Block(, "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();
}
Blockchain.cpp
最后的工程结构如图

在MyBlockChainCppSample.cpp中添加以下代码
#include "Blockchain.h"
int main() {
Blockchain bChain = Blockchain();
cout << "Mining block 1..." << endl;
bChain.AddBlock(Block(1, "Block 1 Data"));
cout << "Mining block 2..." << endl;
bChain.AddBlock(Block(2, "Block 2 Data"));
cout << "Mining block 3..." << endl;
bChain.AddBlock(Block(3, "Block 3 Data"));
return 0;
}
到此代码添加结束 但是VC中编译代码可能会遇到以下问题
1 提示 stdafx.h未添加 这是VC默认要添加预编译头 我们可以设置不需要预编译头来解决这个问题(也可以在每个cpp文件中添加stdafx.h)
解决方式如图

2 会提示sprintf函数 不能使用。这是因为该函数时候早期使用的,在字符串处理上可能存在潜在处理错误。我们可以定义一个宏来告知编译器我们知道此类错误并愿意使用
定义如图

最后编译结果如图
这是设置 #define DifficultyNum 6 , 难度为6的计算结果
Mining block 1...
Block mined: 000000182cfdfadfd84a0578f64d68a1c38bbaf4cbcf18027b0be00ee9a37e18
Mining block 2...
Block mined: 0000002f57459a48244bbf39d089a2b6e7b9aac8dca7ef8b7e71ef6a24753522
Mining block 3...
Block mined: 000000a2eaf0c37a192b182e038e4b20146bfdadb5fffb3bb836d8a7af89c16d
请按任意键继续. . .
这是设置 #define DifficultyNum 4 , 难度为4的计算结果
Mining block 1...
Block mined: 0000dcdb20156ad2777f685bab10bde456b756c40ac7c1a70ab5015ccf207309
Mining block 2...
Block mined: 0000350fb47c51201df28dd8e5b0baf517bcf6175dad8df29feba87b5eaadfbe
Mining block 3...
Block mined: 0000aede11083363a82c9ec43346b1895d818ecde528a171e837e5577478cd78
请按任意键继续. . .
下篇进行代码解析
cpp 区块链模拟示例(一)工程建立的更多相关文章
- cpp 区块链模拟示例(二)工程代码解析
/* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ window ...
- cpp 区块链模拟示例(三)新基本原形工程的建立
/* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ window ...
- cpp 区块链模拟示例(四) 区块链工作量证明
本文主要在之前的区块链原形上添加了工作量证明,并且为后继的交易功能做好准备. 上一个章节我们已经创建了区块链的基本原形,但是区块的哈希计算和加入太过于简单,如果按照这种速度添加区块那么区块链估计一个小 ...
- cpp 区块链模拟示例(五) 序列化
有了区块和区块链的基本结构,有了工作量证明,我们已经可以开始挖矿了.剩下就是最核心的功能-交易,但是在开始实现交易这一重大功能之前,我们还要预先做一些铺垫,比如数据的序列化和启动命令解析. 根据< ...
- cpp 区块链模拟示例(六) 交易
交易(transaction)是比特币的核心所在,而区块链的唯一目的,也正是为了能够安全可靠地存储交易.在区块链中,交易一旦被创建,就没有任何人能够再去修改或是删除它.在今天的文章中,我们会实现交易的 ...
- cpp 区块链模拟示例(七) 补充 Merkle树
Merkle 树 完整的比特币数据库(也就是区块链)需要超过 140 Gb 的磁盘空间.因为比特币的去中心化特性,网络中的每个节点必须是独立,自给自足的,也就是每个节点必须存储一个区块链的完整副本.随 ...
- 区块链共识机制之工作量证明(POW)
像比特币.以太坊.NXT.Bitshares等这些区块链系统,其本质上是一种加密经济组织,它建立在点对点网络上,是去中心化.无管辖的,由密码学.经济学和社会共识来共同维护.这些加密网络因各种原因有着多 ...
- 使用Geth 构建以太坊区块链并模拟挖矿过程
使用Geth 构建以太坊区块链并模拟挖矿过程 Go-ethereum 是以太坊官方的一个Golang 实现,我们可以使用Geth 工具来创建创世区块并启动区块链,使用Clef 实现以太坊钱包的功能,以 ...
- 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码
部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...
随机推荐
- mongodb 安装使用备记
# 1.1 安装 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931B ...
- 转wave 文件解析
转 1 WAVE 文件格式分析 WAVE 文件作为多媒体中使用的声音波形文件格式之一,它是以RIFF(Resource Interchange File Format)格式为标准的.每个WAVE文件的 ...
- MySQL安全机制 DDL DCL
一.MySQL用户管理 1. 修改用户密码 ===root修改自己密码=== 方法一: # mysqladmin -uroot -p'123' password 'new_password' //12 ...
- solidworks建立三维模型里面的几何对象和工程图里面的元素的联系
本文是帮助里面的一个例子, 首先打开一个三维模型和对应的工程图,保持三维模型为当前激活窗口,在三维模型里面选中一个面或者一个边,然后运行下面的代码, 会将工程图里面的第一视图里面对应的投影元素的线型的 ...
- denyhosts、中文文档乱码、端口占用查询
1.安装 denyhosts, 设置 hosts.allow ,系统自动将攻击的ip 添加如 hosts.deny2.打开中文文档乱码, 将文档下载到windows, 通过富文本编辑器查看文档编码3. ...
- Java 身份证判断性别获取年龄
import com.alibaba.fastjson.JSON; import org.junit.Test; import java.text.SimpleDateFormat; import j ...
- list按照某个元素进行排序
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.u ...
- python 修改dataframe的列名
1. 修改全部列名 df.columns base_data_model.columns = [u'有效率',u'提交率',u'参与度',u'回放占比',u'主好评率',u'辅好评率',u'是否付费' ...
- 201772020113李清华《面向对象程序设计(java)》第一周学习总结
201772020113<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com b ...
- django毕设之路1.0
Django的核心理念 1.更python化 2.DRY:(don't repeat yourself),不做重复的工作 3.松耦合和灵活 4.快速开发 2.Django的MTV概 M:Model模型 ...