/*c++
做 者: itdef 程序員
歡迎轉帖 請保持文本完整並註明出處
技術博客 http://www.cnblogs.com/itdef/
技術交流羣 羣號碼:432336863
歡迎c c++ windows驅動愛好者 服務器程序員溝通交流
部分老代碼存放地點
http://www.oschina.net/code/list_by_user?id=614253windows
*/服務器
書接上文函數
咱們先來看區塊的結構區塊鏈
1 class Block { 2 public: 3 string sPrevHash; //記錄上個塊的哈希值 4 Block(uint32_t nIndexIn, const string &sDataIn); //構造函數 5 string GetHash(); //獲取哈希函數 6 void MineBlock(uint32_t nDifficulty); //挖礦函數 7 private: 8 uint32_t _nIndex; //該區塊的索引值 9 int64_t _nNonce; //區塊隨機數 用於哈希值的產生 10 string _sData; //區塊描述字符 11 string _sHash; //區塊哈希值 12 time_t _tTime; //建立時間 13 string _CalculateHash() const; //哈希值計算函數 14 };
區塊結構很清晰。 一個區塊就是一個建立時間、描述字符、區塊隨機數字等數據組成。ui
咱們要建立一個區塊就是根據建立時間、描述字符、區塊隨機數字等數據來計算出一個哈希值(_CalculateHash函數的功能)。 spa
inline string Block::_CalculateHash() const { stringstream ss; ss << _nIndex << _tTime << _sData << _nNonce << sPrevHash; return sha256(ss.str()); }
因爲_nNonce與建立時間是一值在變化的,_CalculateHash()會產生一個個的哈希。.net
在MineBlock()函數中對這些哈希進行檢測,看看是否符合標準,一旦符合標準,那麼久誕生了一個區塊。code
這裏的MineBlock()函數中,根據設置的DifficultyNum,來檢測哈希數值前DifficultyNum位是否爲零,只有符合標準纔是產生的區塊的可以使用的哈希值
隨即產生的哈希值中,前DifficultyNum位爲零,只在必定機率下才產生。 這也是爲了限制區塊的產生速度,在本次區塊鏈技術模擬中,咱們稱之爲"工做量證實"
void Block::MineBlock(uint32_t nDifficulty) { char cstr[DifficultyNum + 1]; for (uint32_t i = 0; i < DifficultyNum; ++i) { cstr[i] = '0'; } cstr[DifficultyNum] = '\0'; string str(cstr); do { _nNonce++; _sHash = _CalculateHash(); } while (_sHash.substr(0, nDifficulty) != str); cout << "Block mined: " << _sHash << endl; }
Block 結構體中 sPrevHash就是記錄該區塊的上一個區塊的哈希值。區塊鏈技術中使用一種方法將哈希值與區塊一一對應。
這樣知道一個區塊和區塊中的sPrevHash。經過查找能夠依次遍歷區塊鏈中的每一個區塊。這些有關聯的區塊也正是使用這種方法組成了區塊鏈.
區塊鏈結構體以下
class Blockchain { public: Blockchain(); //區塊鏈構造函數 void AddBlock(Block bNew); //區塊鏈添加區塊函數 private: uint32_t _nDifficulty; //難度值 vector<Block> _vChain; //記錄區塊鏈 Block _GetLastBlock() const; //獲取最後一個區塊 };
大體的示意圖以下
咱們的模擬文章中,區塊鏈使用了vector<Block> _vChain來記錄每一個區塊,每一個區塊中都有本身在這個vector中的索引_nIndex,這樣查找起來更簡單快捷。
區塊鏈建立的時候會插入一個索引爲零,描述字符爲" Genesis Block "的區塊,稱之爲創始塊. 創世塊與其餘塊的區別是交易的輸入與輸出,這個在後繼章節再詳細介紹。
AddBlock()與_GetLastBlock()相對比較簡單,_GetLastBlock()就是返回vector<Block> _vChain的最後一個元素。
AddBlock()就是經過挖礦產生一個區塊,放入到記錄vector<Block> _vChain中。固然要記得設置該塊的sPrevHash爲以前區塊鏈中最後一個塊的哈希值.
Blockchain::Blockchain() { _vChain.emplace_back(Block(0, "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(); }
《build-a-blockchain-with-c》 的講解和VC工程的創建就到此爲止。
相對《用 Go 構建一個區塊鏈》 ,《build-a-blockchain-with-c》代碼量少並且簡單。
下面的章節咱們將進行 《用 Go 構建一個區塊鏈》的c++化 並講解代碼內容