比特幣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();}

推薦閱讀