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 ...
随机推荐
- nodejs教程 安装express及配置app.js文件的详细步骤
来自:http://www.jb51.net/article/36710.htm express.js是nodejs的一个MVC开发框架,并且支持jade等多种模板.下面简单来说说express的 ...
- JavaBasic_正则表达式
就是符合一定规则的字符串 规则字符在java.util.regex.Pattern类中 字符转义\. 匹配.字符\* 匹配*字符\\ 匹配\字符\n 新行(换行)符 ('\u000A') \r 回车符 ...
- 解决ubuntu16.04桌面左侧栏和顶部栏消失的问题
重要事情说三遍! 不要轻易重装系统! 不要轻易重装系统! 不要轻易重装系统! 问题所在:误删了unity桌面. 解决方法: $sudo apt-get install unity
- Tag (input) should be an empty-element tag.
因为:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...
- Delphi 7升级到XE2的字符串问题
原来的Delphi中有两种字符串:AnsiString和WideString.默认的string即AnsiString.而在Delphi 2009中,新增加了一种UnicodeString.为什么不沿 ...
- js中slice方法(转)
1.String.slice(start,end)returns a string containing a slice, or substring, of string. It does not m ...
- 第四章 FFmpeg转码
4.1 FFmpeg软编码H.264与H.265 4.1.1 x264编码参数简介 4.1.2 H.264编码举例
- 使用css实现时间轴
本文将使用css来实现一个左右交叉布局的时间轴,效果如下: 使用的都是一些常用的css,代码如下: <!DOCTYPE> <html> <head> <tit ...
- 解决Tomcat启动时项目重复加载问题
前几天一个同学项目要上线,部署到服务器时,因为客户需要通过IP直接可以访问到,所以在server.xml做了如下的配置 导致启动tomcat时候出现一个项目重复加载了两次,很容易就出现了内存溢出. 这 ...
- js数据类型检测
目录 1. typeof {} 2. {} instanceof Object 3. {}.constructor === Object 4. Object.property.toString.cal ...