丁丁打折网 - 网友优惠券分享网站,有688999个用户

京东优惠券 小米有品优惠券

当前位置 : 首页>web3>C++手撸比特币:挖矿原理深度解析与实战模拟

C++手撸比特币:挖矿原理深度解析与实战模拟

类别:web3 发布时间:2025-10-04 20:20

好的,我将把你的代码实现进行润色,使其更具人性化和可读性,并符合搜索引擎优化规则。

亲手用C++模拟比特币挖矿:一次有趣的尝试

最近我闲来无事,就想挑战一下自己,看看能不能用C++写一个简单的比特币模拟程序。别误会,我不是想发家致富,只是纯粹出于技术爱好,想更深入地了解比特币的运作原理。

这个程序还不够完善,但已经能够模拟打包交易到区块,然后进行挖矿的过程。为了简化,我只实现了一个单节点的挖矿,没有涉及分布式系统的复杂性。你可以把它看作是整个网络中一个节点的视角。

如果你也对区块链技术感兴趣,不妨跟着我的思路一起探索一下。我会尽量用通俗易懂的语言,把代码的逻辑讲清楚。

准备工作

首先,你需要把所有的代码复制到你的C++开发环境中。注意,代码中有两处文件路径需要你手动修改,务必确保路径正确,否则程序可能无法正常运行。

代码结构

整个程序主要分为以下几个部分:

  1. Blockchain 类 (Blockchain.h 和 Blockchain.cpp):负责管理整个区块链,包括添加新的区块、获取最新的区块等。
  2. Block 类 (Block.h 和 Block.cpp):代表一个区块,包含区块的索引、数据、时间戳、随机数以及前一个区块的哈希值等信息。
  3. SHA256 类 (sha256.h 和 sha256.cpp):实现 SHA256 哈希算法,用于计算区块的哈希值。
  4. User 类 (user.h 和 user.cpp):模拟用户的行为,包括打包交易等。
  5. 主程序 (TestforBitcoin.cpp):程序的入口,负责创建区块链、模拟用户挖矿等。
  6. 交易数据 (300dataTX.txt):包含300条模拟交易数据,用于打包到区块中。

Blockchain 类

Blockchain.h

#pragma once#include "Block.h"#include <vector> // 向量库class Blockchain {public: Blockchain(); // 默认构造函数 void AddBlock(Block bNew); // 增加区块函数 uint32_t _nDifficulty; // 难度值 std::vector<Block> _vChain; // 保存区块的变量 Block _GetLastBlock() const; // 获取最新的区块,由const关键字,表示输出的内容不可更改};

Blockchain.cpp

#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();}

重点: 你可以在 Blockchain.cpp 中修改难度值 _nDifficulty。难度值越高,挖矿所需的时间就越长。

Block 类

Block.h

#pragma once#include <cstdint> // 包含了uint32_t等无符号整型#include <iostream> // 标准输入输出库#include <fstream>#include <string>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; // 区块生成时间private: string _CalculateHash() const; // 计算Hash值,const保证输出的函数值不能被改变。public: 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) // 构造函数{ _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();}

重点: MineBlock 函数是挖矿的核心,它不断尝试不同的 _nNonce 值,直到找到一个满足难度要求的哈希值。

SHA256 类

这部分代码实现了 SHA256 哈希算法,用于计算区块的哈希值。由于 SHA256 算法比较复杂,这里就不详细解释了。你可以把它看作是一个黑盒,只要知道它的作用是将任意长度的数据转换为固定长度的哈希值即可。

User 类

user.h

#pragma once#include <iostream> // 标准输入输出库#include <vector> #include <string> #include <fstream>#include <sstream>#include "BlockChain.h"#include "sha256.h"using namespace std;class User {public: Blockchain uBlockchain; // 当前节点创建一个自己的区块链,因为每个用户都保存一条自己的区块链 string batchTX(); // 打包交易};

user.cpp

#include "user.h"string User::batchTX() { ifstream myfile("300TXdata.txt"); // 读取txt文档中的300条交易数据 string temp[300]; int i = 0; if (!myfile.is_open()) { cout << "未成功打开文件" << endl; } while (getline(myfile, temp[i++])) // 将取出来的第一行放在数组中i的位置然后i++ { getline(myfile, temp[i++]); // 将取出来的下一行放在数组i后面的位置然后i++ } for (int i = 0; i < 300; i++) // 这是一个伪默克尔树生成过程,为了便于实现,就这样写了。 // 实际上真的默克尔树生成也不难,暂时先这样吧。 { stringstream ss; // 该对象可以通过<<接收多个数据,保存到ss对象中,并通过str方法,将内容赋给一个string对象 ss << temp[0] << temp[i]; temp[0] = sha256(ss.str()); } myfile.close(); return temp[0];}

重点: batchTX 函数模拟了用户打包交易的过程。为了简化,这里使用了一个“伪默克尔树”的实现方式。实际上,真正的默克尔树生成过程会更加复杂。

主程序

TestforBitcoin.cpp

#include <iostream>#include <cstdint>#include "Blockchain.h"#include "user.h"#include <stdio.h>#include <cstdlib>#include <ctime>#include "time.h"#include "sha256.h"using namespace std;int main() { srand((int)time(0)); // 随机数种子 Blockchain bChain = Blockchain(); // 首先创建一个区块链 User user[100]; // 创建100个用户 int miner_id; for (int i = 0; i < 100000; i++) // 十万次出块,记录出块速度 { miner_id = rand() % 100; for (int j = 0; j < 100; j++) { user[j].uBlockchain = bChain; // 把100个节点的区块链初始化。 } user[miner_id].uBlockchain = bChain; // 对挖矿区块初始化 printf("Mining block %d...\n", i); user[miner_id].uBlockchain.AddBlock(Block(i, user[miner_id].batchTX())); bChain = user[miner_id].uBlockchain; printf("Miner ID is %d...\n", miner_id); } system("pause"); return 0;}

重点: 主程序模拟了 100 个用户,并在一个循环中不断进行挖矿。每次循环,会随机选择一个用户作为矿工,然后将该用户打包的交易添加到区块链中。

交易数据

300dataTX.txt

这个文件包含了 300 条模拟交易数据,每条交易数据包括发送方、接收方和金额等信息。你可以根据自己的需要修改这个文件。

运行程序

确保所有代码都已正确复制到你的 C++ 开发环境中,并且文件路径已正确设置。然后,编译并运行程序。

你将会看到程序不断输出挖矿信息,包括区块的哈希值、随机数以及矿工的 ID 等。你还可以在 out.txt 文件中查看生成的区块数据。

总结

通过这个简单的比特币模拟程序,你可以更深入地了解区块链的运作原理,包括区块的生成、哈希值的计算以及挖矿的过程。虽然这个程序还不够完善,但它为你提供了一个很好的起点,你可以根据自己的兴趣和需求,进一步扩展和完善它。

希望这个分享对你有所帮助!如果你有任何问题,欢迎随时提问。

丁丁打折网©版权所有,未经许可严禁复制或镜像 ICP证: 湘ICP备20009233号-2

Powered by 丁丁打折网本站为非营利性网站,本站内容均来自网络转载或网友提供,如有侵权或夸大不实请及时联系我们删除!本站不承担任何争议和法律责任!
技术支持:丁丁网 dddazhe@hotmail.com & 2010-2020 All rights reserved