/*

作 者: 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 区块链模拟示例(一)工程建立的更多相关文章

  1. cpp 区块链模拟示例(二)工程代码解析

    /* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ window ...

  2. cpp 区块链模拟示例(三)新基本原形工程的建立

    /* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ window ...

  3. cpp 区块链模拟示例(四) 区块链工作量证明

    本文主要在之前的区块链原形上添加了工作量证明,并且为后继的交易功能做好准备. 上一个章节我们已经创建了区块链的基本原形,但是区块的哈希计算和加入太过于简单,如果按照这种速度添加区块那么区块链估计一个小 ...

  4. cpp 区块链模拟示例(五) 序列化

    有了区块和区块链的基本结构,有了工作量证明,我们已经可以开始挖矿了.剩下就是最核心的功能-交易,但是在开始实现交易这一重大功能之前,我们还要预先做一些铺垫,比如数据的序列化和启动命令解析. 根据< ...

  5. cpp 区块链模拟示例(六) 交易

    交易(transaction)是比特币的核心所在,而区块链的唯一目的,也正是为了能够安全可靠地存储交易.在区块链中,交易一旦被创建,就没有任何人能够再去修改或是删除它.在今天的文章中,我们会实现交易的 ...

  6. cpp 区块链模拟示例(七) 补充 Merkle树

    Merkle 树 完整的比特币数据库(也就是区块链)需要超过 140 Gb 的磁盘空间.因为比特币的去中心化特性,网络中的每个节点必须是独立,自给自足的,也就是每个节点必须存储一个区块链的完整副本.随 ...

  7. 区块链共识机制之工作量证明(POW)

    像比特币.以太坊.NXT.Bitshares等这些区块链系统,其本质上是一种加密经济组织,它建立在点对点网络上,是去中心化.无管辖的,由密码学.经济学和社会共识来共同维护.这些加密网络因各种原因有着多 ...

  8. 使用Geth 构建以太坊区块链并模拟挖矿过程

    使用Geth 构建以太坊区块链并模拟挖矿过程 Go-ethereum 是以太坊官方的一个Golang 实现,我们可以使用Geth 工具来创建创世区块并启动区块链,使用Clef 实现以太坊钱包的功能,以 ...

  9. 用Java为Hyperledger Fabric(超级账本)开发区块链智能合约链代码之部署与运行示例代码

    部署并运行 Java 链代码示例 您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger ...

随机推荐

  1. 一次完整的HTTP事务是怎样一个过程?(转)

    HTTP协议 关于HTTP协议可以参考以下: HTTP协议漫谈 http://kb.cnblogs.com/page/140611/ HTTP协议概览 http://www.cnblogs.com/v ...

  2. laravel5.5 excel扩展包的安装和使用

    (文章引用来源 http://www.cnblogs.com/djwhome/p/9322112.html   有自己的补充用于记录) (在此次项目中,本人亲自尝试,标题中文无论如何转换(GBK.gb ...

  3. [蓝桥杯]ALGO-20.算法训练_求先序排列

    问题描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度<=). 输入格式 两行,每行一个字符串,分别表示中序和后序排列 输出格式 一个字符串,表示所求 ...

  4. k8s Nodeport方式下service访问,iptables处理逻辑(转)

    原文 https://www.myf5.net/post/2330.htm k8s Nodeport方式下service访问,iptables处理逻辑 2017年07月11日 0条评论 976次阅读 ...

  5. 刘志梅201771010115.《面向对象程序设计(java)》第二周学习总结

    实验二 Java基本程序设计(1) 实验时间 2018-9-6 第一部分:理论知识学习 3.1一个简单的Java应用程序 关键字public称为访问修饰符,这些修饰符用于控制程序的其他部分对这段代码的 ...

  6. 生产者-消费者(wait-notify实现)

    使用wait/notify来实现生产者消费者时能够达到在线程阻塞的效果,这样就不会出现轮询,然后浪费cpu时间的目的.代码如下:1. 状态类,表示是否已经生产: package com.demo; p ...

  7. java常见面试题及答案 11-20(JVM)

    11.JVM内存分哪几个区,每个区的作用是什么? Java虚拟机主要分为以下一个区: 方法区:1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区 ...

  8. JAVA Maven 安装 jar 包到本地仓库,以 Oracle11g 的访问包 为例

    maven 作为 java 的首选包管理工具,使我们在创建和维护项目的时候变得十分简单,但是 maven 仓库并不是拥有的一切 jar 包的, 很多 jar 包由于收费或者版权什么的其他原因,并不存在 ...

  9. Android Studio模拟器磁盘空间不足(Not enough disk space to run AVD)

    在Android Studio中运行模拟器时,提示Error: Not enough disk space to run AVD '....'. Exiting.是说安装模拟的磁盘空间不足,导致无法运 ...

  10. <转> plsql dev中Dynamic Performance Tables not accessible分析解决

    相信很多使用plsql dev的朋友多遇到过类此如下面的提示: Dynamic Performance Tables not accessible, Automatic Statistics Disa ...