/*ios
做 者: itdef
歡迎轉帖 請保持文本完整並註明出處
技術博客 http://www.cnblogs.com/itdef/
技術交流羣 羣號碼:432336863
歡迎c c++ windows驅動愛好者 服務器程序員溝通交流
部分老代碼存放地點
http://www.oschina.net/code/list_by_user?id=614253c++
*/程序員
今天,我將開啓一個使用c++模擬區塊鏈的系列,記錄本身學習區塊鏈與實踐的心得體會.算法
文章將參考《一步步教小白使用C++構建區塊鏈》(c++語言)windows
《用 Go 構建一個區塊鏈 ---- Part 1: 基本原型》 (go語言) 等博客文,服務器
經過使用c++編寫和講解一個簡單的區塊鏈代碼,來加深本身對區塊鏈原理的理解。ide
區塊鏈中大量使用哈希算法。函數
算法將參與須要計算的總體內容所有做爲元素添加至哈希計算中,最後得出一個獨一無二的計算結果。工具
他的好處在於,能夠用來驗證一個文件沒有被任何人更改。若是同時擁有待驗證內容和哈希計算的結果,那麼你能夠很快驗證本身的待驗證內容是否正確。同時,正確內容遭到刻意的修改而計算出正確的哈希結果這種事情幾乎不存在。學習
在這個示例中 咱們使用來自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也要添加進工程中.
1 #pragma once 2 3 4 #include <cstdint> 5 #include <iostream> 6 7 8 using namespace std; 9 10 #define DifficultyNum 4 11 12 class Block { 13 public: 14 string sPrevHash; //記錄上個塊的哈希值 15 Block(uint32_t nIndexIn, const string &sDataIn); //構造函數 16 string GetHash(); //獲取哈希函數 17 void MineBlock(uint32_t nDifficulty); //挖礦函數 18 private: 19 uint32_t _nIndex; //該區塊的索引值 20 int64_t _nNonce; //區塊隨機數 用於哈希值的產生?? 21 string _sData; //區塊描述字符 22 string _sHash; //區塊哈希值 23 time_t _tTime; //建立時間 24 string _CalculateHash() const; //哈希值計算函數 25 };
1 #include "Block.h" 2 #include "sha256.h" 3 #include <time.h> 4 #include <sstream> 5 6 Block::Block(uint32_t nIndexIn, const string &sDataIn) : _nIndex(nIndexIn), _sData(sDataIn) { 7 _nNonce = -1; 8 _tTime = time(nullptr); 9 } 10 11 string Block::GetHash() { 12 return _sHash; 13 } 14 15 void Block::MineBlock(uint32_t nDifficulty) { 16 char cstr[DifficultyNum + 1]; 17 for (uint32_t i = 0; i < DifficultyNum; ++i) { 18 cstr[i] = '0'; 19 } 20 cstr[DifficultyNum] = '\0'; 21 string str(cstr); 22 do { 23 _nNonce++; 24 _sHash = _CalculateHash(); 25 } while (_sHash.substr(0, nDifficulty) != str); 26 cout << "Block mined: " << _sHash << endl; 27 } 28 29 30 inline string Block::_CalculateHash() const { 31 stringstream ss; 32 ss << _nIndex << _tTime << _sData << _nNonce << sPrevHash; 33 return sha256(ss.str()); 34 }
1 #pragma once 2 3 #include <cstdint> 4 #include <vector> 5 #include "Block.h" 6 7 using namespace std; 8 9 class Blockchain { 10 public: 11 Blockchain(); //區塊鏈構造函數 12 void AddBlock(Block bNew); //區塊鏈添加區塊函數 13 private: 14 uint32_t _nDifficulty; //難度值 15 vector<Block> _vChain; //記錄區塊鏈 16 Block _GetLastBlock() const; //獲取最後一個區塊 17 };
1 #include "Blockchain.h" 2 3 4 Blockchain::Blockchain() { 5 _vChain.emplace_back(Block(0, "Genesis Block")); 6 _nDifficulty = DifficultyNum; 7 } 8 9 void Blockchain::AddBlock(Block bNew) { 10 bNew.sPrevHash = _GetLastBlock().GetHash(); 11 bNew.MineBlock(_nDifficulty); 12 _vChain.push_back(bNew); 13 } 14 15 Block Blockchain::_GetLastBlock() const { 16 return _vChain.back(); 17 }
最後的工程結構如圖
在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
請按任意鍵繼續. . .
下篇進行代碼解析