币圈信息资讯 欧意交易所 一文详解比特币原理

一文详解比特币原理

广告位

一、什么是比特币

比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。

二、问题引入

假设现有4个人分别称之为ABCD,他们之间发起了3个交易,A转给B10个比特币,B转给C5个比特币,C转给D2个比特币。如果是传统的记账方式,这些交易会记录在银行的系统中,这些信息由银行来记录,我们相信银行不会随意添加、删除或修改一条交易记录,我们也不会关注到底有哪些交易,我们只关注自己的账户余额。而比特币的记账方式为ABCD每个人保存了这样一份账本,账本上记录了上述交易内容,如果每个人账本实时的一致,ABCD就不再需要银行。

比特币是这样做的,每当有人发起一笔交易,他就要将一笔交易广播至全网,由全网中的某一个人,把一段时间内的交易打包好记录到一个区块上,再按照顺序把这些区块,一个一个的链接在一起,进而形成了一个链条,这就是所谓的区块链。
一文详解比特币原理插图

那么问题来了

1、我凭什么要参与这个系统,我为什么要动用自己的计算机资源来存储这些信息呢?

2、以谁的记录为准呢?比如上面的账单顺序,A用户可能是这个顺序,但是B可能顺序不一样,甚至可能B根本就没有接收到C给D转账的这个消息。

3、比特币如果做到支付功能,保证该是谁的钱就是谁的钱,而且只有其所有者才能花。

4、如何防伪、防篡改以及双重支付,防伪是验证每条交易的真的是某人发出的,比如B可能杜撰一条消息,说某某给我转了一笔钱,这就是一个假消息,或者B说我给某人转了多少钱,但是实际上他并没有这么多钱,又怎么办。防篡改指的是B可能想从区块链上把自己曾经转给某人钱的记录删掉,这样他的余额就会增加。双重支付是指,B只有10比特币,他同时向C和D转10个比特币,造成双重花费。

三、为什么要记账?

因为记账有奖励,记账有手续费的收益,而且打包区块的人有系统奖励,奖励方案是,每十分钟生成一个区块,每生成一个区块会奖励一定数量的比特币,最开始是50个BTC,过4年会奖励25个BTC,再过4年再减少一半,以此类推。这样比特币的产生会越来越少,越来越趋近于一个最大值,计算公式是:50×6×24×365×4×(1+1/2+1/4+1/8+…)≈2100万,其中最初奖励50个比特币,每小时有6个区块,每天24小时,每年365天,前四年是如此,之后每四年减半。

此外,记账奖励还有每笔交易的小额手续费,每个交易发起都会附带一定的手续费,这些手续费是给记账的矿工的。

四、以谁为准?

各个节点通过工作量证明机制来争夺记账权,他们计算一个很复杂的数学题,第一个计算出来的节点就是下一个区块的产生者。这个数学题很难,难到没有一个人能同过脑子算出来,它是基于概率的方法,矿工必须通过遍历、猜测和尝试的办法才能解开这个未知数。那么这个数学难题到底是什么呢?下面详细介绍。

4.1哈希函数

哈希函数又称为数字摘要或散列函数,它的特点是输入一个字符串,可以生成另外一个字符串,但是如果输入不同,输出的字符串就一定不同,而且通过输出的字符串,不能反推出输入。举个简单的例子,对1-100内的数模10,可以认为是一种哈希方法,比如98%10=8,66%10=6,98和66是输入,模10是哈希函数,8和6是输出,在这个模型中,通过6和8无法推断输入是66和98,因为还可能是56和88等,当然因为这个例子比较简单,所以会出现哈希碰撞,即66和56的结果都是6,输出的结果相同。一个优秀的哈希函数,可以做到输出一定不同,哈希碰撞的概率几乎为0。常见的哈希函数有很多,比如MD系列和SHA系列等,比特币采用的SHA256算法,即输入一个字符串,输出一个256位的二进制数。下面是程序运行的结果。

一文详解比特币原理插图1

通过程序结果可以看出,输入的源信息不同,得到的结果也不同(为了方便,结果用64位16进制表示),即使是orange多了一个句号,也会产生截然不同的结果。同时,通过输出的十六进制字符串,也无法倒推出输入。对于比特币,只要了解SHA256的功能即可,如果感兴趣可以深入了解SHA256的具体算法。需要SHA256的C++源码留言邮箱或私信。

4.2挖矿原理

首先介绍一下比特币每个区块的数据结构,每个区块由区块头和区块体两部分组成。

区块体中包含了矿工搜集的若干交易信息,图中假设有8个交易被收录在区块中,所有的交易生成一颗默克尔树,默克尔树是一种数据结构,它将叶子节点两两哈希,生成上一层节点,上层节点再哈希,生成上一层,直到最后生成一个树根,称之为默克尔树根,只有树根保留在区块头中,这样可以节省区块头的空间,也便于交易的验证。

区块头中包含父区块的哈希,版本号,当前时间戳,难度值,随机数和上面提到的默克尔树根。

一文详解比特币原理插图2

假设区块链已经链接到了某个块,有ABCD四个节点已经搜集了前十分钟内全网中的一些交易信息,他们选出其中约4k条交易,打包好,生成默克尔树根,将区块头中的信息,即发区块哈希+版本号+时间戳+难度值+随机数+默克尔树根组成一个字符串str,通过两次哈希函数得出一个256的二进制数,即SHA256(SHA256(str)) = 10010011……共256位,比特币要求,生成的结果,前n位必须是0,n就是难度值,如果现在生成的二进制数不符合要求,就必须改变随机数的值,重新计算,只到算出满足条件的结果为止。假设现在n是5,则生成的二进制数必须是00000……(共256位)。一旦挖矿成功,矿工就可以广播这个消息到全网,其他的矿工就会基于该区块继续挖矿。下一个区块头中的父区块哈希值就是上一个区块生成的00000……这个数。

解决这个数学难题要靠运气,理论上,运气最好的矿工可能1次哈希就能算出结果,运气差的可能永远都算不出来。但是总体来看,如果一个矿工的算力越大,单位时间内进行的哈希次数就越多,就越可能在短时间内挖矿成功。

那么n是如何确定的呢?比特币设计者希望,总体上平均每十分钟产生一个区块,总体上来看,挖矿成功的概率为1/2^n。现假设世界上有1W台矿机,每台矿机的算力是14T次/s = 1.4×10^13次/s,单位次/s称之为哈希率,10分钟是600s,所以10分钟可以做8×10^19次哈希运算,从概率角度看,想要挖矿成功需要做2^n次运算,可以列出等式2^n = 8×10^19,可以解出n约为66。所以对于这种方法,我们没有办法使得自己的运气变的更好,只能提高自己的算力,尽快的算出结果。

另外,需要模拟挖矿过程的C++代码可以回复邮箱,代码可以通过调整难度值,模拟比特币的挖矿算法,控制区块产生的速度。

五、如何防伪、防篡改、防双重支付等问题

这部分是理解比特币很重要的部分。

5.1电子签名技术

身份认证技术在生活中很常见,可以是人脸识别、签字、指纹等,但是这些方法在数字货币领域并不安全,因为它们一旦数字化,都可以通过复制的方法伪造。所以比特币采用了电子签名的方法。

注册成为比特币用户时,系统会根据随机数生成一个私钥,私钥会生成一个公钥,公钥又会生成一个地址,其中私钥必须保密,可以保存到硬盘里或者记到脑子里,因为这个私钥是使用相应地址上的比特币的唯一标识,一旦丢失,所有的比特币将无法使用。下面介绍具体的转换过程,不感兴趣可以不看,只要知道随机数->私钥->公钥->钱包地址这个过程,其中私钥可以对一串字符进行加密,而公钥可以对其进行解密,这就是非对称加密,这类算法总体上的功能都是一样的,只是具体算法有区别,由于这些算法比较复杂,与SHA265算法一样不多做介绍,感兴趣可以深入了解具体算法,但是对于比特币系统,只要了解其功能即可。典型的算法是RSA,比特币采用椭圆曲线加密算法。

转换过程(选读,不影响理解)

1、首先使用随机数发生器生成一个私钥,它是一个256位的二进制数。私钥是不能公开的,相当于银行卡的密码。

2、私钥经过SECP256K1算法生成公钥,SECP256K1是一种椭圆曲线加密算法,功能和RSA算法类似,通过一个已知的私钥,生成一个公钥,但是通过公钥不能反推出私钥。

3、同SHA256算法一样,RIPEMD160也是一种HASH算法,由公钥可以得到公钥的哈希值,而通过哈希值无法推出公钥。

4、将一个字节的版本号连接到公钥哈希头部,然后对其进行两次SHA256运算,将结果的前4字节作为公钥哈希的校验值,连接在其尾部。

5、将上一步的结果使用BASE58进行编码,就得到了钱包地址(相当于银行账户)。比如A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

一文详解比特币原理插图3

所以,通过以上的过程我们可以总结出私钥、公钥、钱包之间的关系如下图。可以看到通过私钥可以推出所有的值,公钥哈希和钱包地址之间可以通过BASE58和BASE58解码算法相互转化。

一文详解比特币原理插图4

了解了公钥、私钥、地址的概念后,防伪验证的过程就很容易理解,当A发起一笔交易后,对消息进行哈希,生成数字摘要,对数字摘要,通过私钥加密,生成一个密码。之后A会广播这个条交易消息、公钥以及密码。收到消息的人首先对交易信息进行哈希生成摘要1,再通过公钥对密码进行解密,生成摘要2,这样,如果两个摘要相同,说明这个消息确实是A发出的。所谓的签名,就是密文。

一文详解比特币原理插图5

5.2余额检查

余额的概念应该说根深蒂固,余额是伴随着称之为借贷记账法而产生的,也是目前银行普遍采用的方法,将一个人的交易记录统计好后算出一个余额,但是在比特币中没有余额这个概念,因为其采用的是UXTO模型的记账方法。比如A->B10个比特币,B->C5个比特币,对于第二笔交易来说,B在发起这笔交易时要注明第一笔交易的信息,这样就可以知道B曾经从A那里收到过10个比特币,说明满足第二笔交易发起的条件。所以比特币中余额的检查是通过追溯的方法。

一文详解比特币原理插图6

上图描述了两笔交易,交易10001中,B向C转了10个比特币,验证这笔交易的过程是:首先将B的签名通过B的公钥解密,然后再和交易的具体内容(B签名左侧)对比,如果相同,说明消息是B发出的,然后再检查10000这个交易是否真的存在以及它的内容的真实性。这两点都满足了,就说明交易10001是可以被接受的,否则拒绝接受。

实际上,真实的交易比这个复杂的多,因为有可能是多笔交易构成了输入,比如B->C20个比特币,是由多笔交易A->B10,D->B10构成的,则前一笔交易ID就是两个ID,甚至可能更多。这里为了简单描述,只列举一笔交易。

5.3双重支付

A同时发了两条消息,同时给B和C转了10个比特币,实际上他只有10个会怎么样?假设D节点先收到了转给B10个BTC,然后收到了转给C10个比特币,通过上面的验证方法,自然会拒绝后面的一个,与此同时,E节点可能先收到了转给C10个BTC,然后收到了转给B10个比特币,他自然会拒绝后者。至于哪一笔交易最终会上链,就要看D和E哪个先解决难题,成功挖矿。

5.4防止篡改

假设A转给B10个比特币,但是他想把这个信息从区块链上删除,这样大家就都不知道这个事情存在,就可以赖账。

首先说一下最长链原则,假设某一个区块后面有两个矿工同时挖到了矿,或者由于网络延迟等原因产生了分歧,这时,各个节点先随意根据自己认为对的区块挖矿,只到下一个区块产生,这时会有两条链,但是有一条是长的,比特币规定,以最长的链为准。如果某个节点仍然的固执的以较短的链为准,他就是在和大多数算力作对,这样做的结果是,他挖的块不被大家认可,会浪费时间和算力。
一文详解比特币原理插图7

回到上面的场景,A想赖账,就只能从记录了A->B10个比特币这个消息的区块的前一个区块开始重新挖矿,造出一个支链来,但是实际上的区块已经前进了很多,他只能不停的追赶,而且在追赶的同时,主链也在前进,他必须以比主链快的速度前进,如果他的算力足够大,理论上通过较长的时间确实可以追赶成功,就实现了对交易信息的篡改。然而其实这几乎是不可能的,因为就算算力再大,平均出块速度也是10分钟,从非技术的角度讲,一个人如果掌握了全网一半以上的算力,他为什么不在主链上继续挖矿呢?一个富可敌国的人应该不会甘愿去做一个小偷吧。

一文详解比特币原理插图8

六、总结

区块链并不等同于比特币,比特币也不是区块链,区块链只是比特币应用的一种技术,这个技术能给我们带来启发,比特币的伟大之处在于应用了前所未有的区块链技术。区块链技术还能在哪些方面应用还需继续探索。

比特币是区块链技术最成功的应用,但是比特币本身也有很多问题,它想通过发行货币来挑战主权货币,这个动机有待商榷。此外,由于比特币的匿名性,只需要一个公钥或地址就能进行交易,为黑色产业提供了很好的平台。另外,比特币并不是一个成熟的支付系统,它具有吞吐率低,可拓展性差等缺点。

可能文字还是比较苍白,可以看看李永乐老师讲解的视频,虽然没有这个详细,但是通俗易懂。

七、代码实现

Blockchain.h这个没什么说的,创建一个区块链类

#pragma once

#include”Block.h”

#include//向量库

class Blockchain

{

public:

Blockchain();//默认构造函数

void AddBlock(Block bNew);//增加区块函数

uint32_t _nDifficulty;//难度值

vector _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//包含了uint32_t等无符号整型

#include//标准输入输出库

#include

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

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<

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

}

sha256.h 这是一个哈希算法,没什么说的,网上抄的,这个东西我到现在也没看懂,太深奥了。但是只要知道功能就行了。

#pragma once

#ifndef SHA256_H

#define SHA256_H

#include

class SHA256

{

protected:

typedef unsigned char uint8;

typedef unsigned int uint32;

typedef unsigned long long uint64;

const static uint32 sha256_k[];

static const unsigned int SHA224_256_BLOCK_SIZE = (512 / 8);

public:

void init();

void update(const unsigned char* message, unsigned int len);

void final(unsigned char* digest);

static const unsigned int DIGEST_SIZE = (256 / 8);

protected:

void transform(const unsigned char* message, unsigned int block_nb);

unsigned int m_tot_len;

unsigned int m_len;

unsigned char m_block[2 * SHA224_256_BLOCK_SIZE];

uint32 m_h[8];

};

std::string sha256(std::string input);

#define SHA2_SHFR(x, n) (x >> n)

#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) – n)))

#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) – n)))

#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))

#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))

#define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))

#define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))

#define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))

#define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))

#define SHA2_UNPACK32(x, str) \

{ \

*((str) + 3) = (uint8) ((x) ); \

*((str) + 2) = (uint8) ((x) >> 8); \

*((str) + 1) = (uint8) ((x) >> 16); \

*((str) + 0) = (uint8) ((x) >> 24); \

}

#define SHA2_PACK32(str, x) \

{ \

*(x) = ((uint32) *((str) + 3) ) \

| ((uint32) *((str) + 2) << 8) \

| ((uint32) *((str) + 1) << 16) \

| ((uint32) *((str) + 0) << 24); \

}

#endif

sha256.cpp

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include “sha256.h”

const unsigned int SHA256::sha256_k[64] = //UL = uint32

{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,

0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,

0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,

0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,

0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,

0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,

0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,

0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,

0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,

0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,

0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,

0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,

0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,

0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,

0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,

0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };

void SHA256::transform(const unsigned char* message, unsigned int block_nb)

{

uint32 w[64];

uint32 wv[8];

uint32 t1, t2;

const unsigned char* sub_block;

int i;

int j;

for (i = 0; i < (int)block_nb; i++) {

sub_block = message + (i << 6);

for (j = 0; j < 16; j++) {

SHA2_PACK32(&sub_block[j << 2], &w[j]);

}

for (j = 16; j < 64; j++) {

w[j] = SHA256_F4(w[j – 2]) + w[j – 7] + SHA256_F3(w[j – 15]) + w[j – 16];

}

for (j = 0; j < 8; j++) {

wv[j] = m_h[j];

}

for (j = 0; j < 64; j++) {

t1 = wv[7] + SHA256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])

+ sha256_k[j] + w[j];

t2 = SHA256_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);

wv[7] = wv[6];

wv[6] = wv[5];

wv[5] = wv[4];

wv[4] = wv[3] + t1;

wv[3] = wv[2];

wv[2] = wv[1];

wv[1] = wv[0];

wv[0] = t1 + t2;

}

for (j = 0; j < 8; j++) {

m_h[j] += wv[j];

}

}

}

void SHA256::init()

{

m_h[0] = 0x6a09e667;

m_h[1] = 0xbb67ae85;

m_h[2] = 0x3c6ef372;

m_h[3] = 0xa54ff53a;

m_h[4] = 0x510e527f;

m_h[5] = 0x9b05688c;

m_h[6] = 0x1f83d9ab;

m_h[7] = 0x5be0cd19;

m_len = 0;

m_tot_len = 0;

}

void SHA256::update(const unsigned char* message, unsigned int len)

{

unsigned int block_nb;

unsigned int new_len, rem_len, tmp_len;

const unsigned char* shifted_message;

tmp_len = SHA224_256_BLOCK_SIZE – m_len;

rem_len = len < tmp_len ? len : tmp_len;

memcpy(&m_block[m_len], message, rem_len);

if (m_len + len < SHA224_256_BLOCK_SIZE) {

m_len += len;

return;

}

new_len = len – rem_len;

block_nb = new_len / SHA224_256_BLOCK_SIZE;

shifted_message = message + rem_len;

transform(m_block, 1);

transform(shifted_message, block_nb);

rem_len = new_len % SHA224_256_BLOCK_SIZE;

memcpy(m_block, &shifted_message[block_nb << 6], rem_len);

m_len = rem_len;

m_tot_len += (block_nb + 1) << 6;

}

void SHA256::final(unsigned char* digest)

{

unsigned int block_nb;

unsigned int pm_len;

unsigned int len_b;

int i;

block_nb = (1 + ((SHA224_256_BLOCK_SIZE – 9)

< (m_len % SHA224_256_BLOCK_SIZE)));

len_b = (m_tot_len + m_len) << 3;

pm_len = block_nb << 6;

memset(m_block + m_len, 0, pm_len – m_len);

m_block[m_len] = 0x80;

SHA2_UNPACK32(len_b, m_block + pm_len – 4);

transform(m_block, block_nb);

for (i = 0; i < 8; i++) {

SHA2_UNPACK32(m_h[i], &digest[i << 2]);

}

}

std::string sha256(std::string input)

{

unsigned char digest[SHA256::DIGEST_SIZE];

memset(digest, 0, SHA256::DIGEST_SIZE);

SHA256 ctx = SHA256();

ctx.init();

ctx.update((unsigned char*)input.c_str(), input.length());

ctx.final(digest);

char buf[2 * SHA256::DIGEST_SIZE + 1];

buf[2 * SHA256::DIGEST_SIZE] = 0;

for (int i = 0; i < SHA256::DIGEST_SIZE; i++)

sprintf(buf + i * 2, “%02x”, digest[i]);

return std::string(buf);

}

user.h创建一个用户类

#pragma once

#include //标准输入输出库

#include

#include

#include

#include

#include “BlockChain.h”

#include “sha256.h”

using namespace std;

class User

{

public:

Blockchain uBlockchain;//当前节点创建一个自己的区块链,因为每个用户都保存一条自己的区块链

string batchTX();//打包交易

};

user.cpp这里是实现用户的打包交易,通过默克尔树的方式将若干条交易打包。其中300TXdata.txt后面我会贴上,一定注意文件的路径问题,不然可能运行不了。(大神当我没说)。

#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++

{

//cout << temp[i++] << endl;

getline(myfile, temp[i++]);//将取出来的下一行放在数组i后面的位置然后i++

//cout << temp[i] << endl;

}

for (int i = 0; i < 300; i++)//这是一个伪默克尔树生成过程,为了便于实现,就这样写了。

//实际上真的默克尔树生成也不难,暂时先这样吧。

{

stringstream ss;//该对象可以通过<<接收多个数据,保存到ss对象中,并通过str方法,将内容赋给一个string对象

ss << temp[0] << temp[i];

temp[0] = sha256(ss.str());

//cout << temp[0] << endl;

}

myfile.close();

return temp[0];

}

TestforBitcoin.cpp这就是测试程序了,我是假设100个用户中某个用户挖矿成功了,然后来挖矿。实际上不是这样的过程,而是先挖矿才知道是哪个用户挖矿成功,不过对于一个用户来说,都无所谓了,只是为了模拟的逼真一点,加了个随机数。

#include

#include

#include”Blockchain.h”

#include”user.h”

#include

#include

#include

#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;

}

300dataTX.txt这里包含了300条交易,用户A->用户B的转账,以及金额,这个东西我是用一个程序模拟生成的,如果需要这个这个程序我之后再发出来。

01100SUSPE 10111ZKHWI 79

10010VQJGH 00100UXYMT 34

00011YMAWT 10010XTPCF 43

10101TZZMF 01110SHOLR 51

01011WVQDR 11101VDFBV 59

11001RRPTU 01011QZWRG 68

11100TFFJG 10101TMVIS 76

00010OBWAS 00001OIMYE 85

10000ROVQD 11010RWCPI 93

01111MKMHH 01100LSBFT 1

11011PGDXT 01010OOSVF 10

01001KUCNF 10011JBRMR 18

10110NQTEQ 00101MXICU 26

00000IDKUU 10011HTZSG 35

10100LZJKG 01000KHYJS 43

01110GVABS 11100FDPZE 52

11001JJQRD 00010IQGPH 60

00101EFPHH 10000DMFGT 68

10111GAGYT 00111GIVWF 77

00000BOFOE 11011BWMNR 85

11110EKWEQ 01001ESLDU 93

01110ZYNVU 11110HNCTG 2

01001CUMLG 00000BBTKS 10

10111XPDCR 10100EXSAD 19

00101ADUSD 01111ZLJQH 27

11001DZTIH 11001CHIHT 35

01110YVJZT 01111XCZXF 44

11100BJAPE 00111AQQNQ 20

00010WFZFQ 10000VMOEU 28

10111ZSQWU 00110YAFUG 37

00101UOHMF 11110TWWLS 45

11011WKGCR 01001WRVBD 54

01101RYXTD 10111RFMRH 62

10000UUWJH 00101UBDIT 70

00010PHNSS 10000OXCYE 79

10100SDEIE 01110RLTOQ 87

01011NZCYQ 11100MGKFU 95

11011QNTPU 01010PUJVG 4

11101LJKFF 10111KQALR 12

00010OEJVR 00101NMYCD 21

10000JSAMD 11011IAPSH 29

01100MORCG 01100LWGIT 37

11010HCQSS 11000GRFZE 46

01001JYHJE 10010JFWPQ 54

10111ETYZQ 00100MBNGU 62

00011HHXQT 10011HPMWF 71

10000CDNGF 01011JLDMR 79

01110FZMWR 11101EGUDD 88

11000ANDND 00010HUTTH 96

00101DIUDG 10000CQJJS 4

10111GWTTS 00100FMAAE 13

00001BSKKE 11011AAZQQ 21

11111EOBAQ 01001DVQGU 29

01110ZCAQT 11111YJPXF 38

01000CXRHF 00011BFGNR 46

10110WTIXR 10000WBXED 55

00101ZHGNC 01110ZPWUG 63

11001UDXEG 11000UKNKS 71

01111XROUS 01101XYEBE 80

11100SMNLE 00111RUCRQ 88

00010VIEBP 10001UQTHT 96

10110QWDRT 00110PEKYF 5

00100TSUIF 11110SZJOR 13

11011OGLYR 01000NVAED 22

01101RBKOC 10110QJRVG 30

11001MXBFG 00101LFQLS 38

00010PLRVS 10001OTHCE 47

10100KHQLD 01111JOGKQ 55

01000MDHCP 11100MKXAT 63

11011HQYST 01010PYNRF 72

11101KMXJF 10110KUMHR 80

00011FAOZQ 00101MQDXC 89

10011IWFPC 11011HDUOG 97

00100DSEGG 01101KZTES 5

11010GFVWS 11001FNKUE 14

01000JBUMD 10010IJBLP 22

10101EXKDP 00100DFABT 30

00011HLBTT 10010GSRRF 39

10001CHAJE 01011BOIIR 47

01111FVRAQ 11101ECGYC 56

11010ZQIQC 00011ZYXPG 64

01000CMHHG 10010CUWFS 72

10110XAYXR 00100XHNVD 49

00001AWPND 11010ADEMP 57

11101VKOEP 01000UZDCT 65

01111YFFUT 11101XNUSF 74

01000TBVKE 00011SJLJQ 82

10110WPUBQ 10001VWKZC 91

00110RLLRC 01110QSBPG 99

10000UHKHF 11010TORGS 7

01111PUBYR 01000OCQWD 16

11101SQSOD 00110RYHNP 24

00001NEREP 10001UUGDT 32

10110PAIVS 00101PHXTE 41

00100KWZLE 11111SDOKQ 49

11010NJYCQ 01000NRNAC 58

01111IFOSC 10110PNEQG 66

11101LBFIF 00110KJVHR 74

00011OPEZR 10001NWUXD 83

10101JLVHD 01111ISKNP 91

01000MYMXP 11101LOBET 99

11010HULOS 01001GCAUE 8

11100KQCEE 10110JYRLQ 16

00011FEBUQ 00100ELIBC 25

10011IASLB 11010HHHRF 33

00101CVJBF 01111CDYIR 41

11010FJHSR 11101FRXYD 50

01000AFYID 10011ANOOP 58

10100DTPYO 00100CAFFS 66

00010YPOPS 10000XWDVE 75

10001BKFFE 01010ASULQ 83

01111WYWVQ 11100VGLCC 92

11011ZUVMB 00011YCKSF 0

01000UIMCF 10011TXBIR 8

10110XEDSR 00101WLSZD 17

00000SZCJC 11010RHRPP 25

11001VNSZO 01000UVIGS 33

01111QJRQS 11100XRZWE 42

11001SFIGE 00011SMYMQ 50

10101NTZWP 10001VAODB 59

00110QOYNB 00111QWNTF 67

10000LCPDF 11011SSEJR 75

01110OYGTR 01000NGVAD 84

11111RUFKC 00110QBUQO 92

00001MIWAO 10000LPLGS 0

10111PDNQS 00001OLCXE 9

00101KZLHD 11111JHBNQ 17

11000NNCXP 01001MVSEB 26

01110IJTNB 11111HQJUF 34

11100LXSEF 00110KEHKR 42

00011FTJUQ 10000FAYBC 51

10111IOILC 01110IWPJO 59

01101DCZBO 11111DKOZS 67

11010GYQRS 01001FFFQE 76

01100BMPID 10111ABEGP 84

00000EIGYP 00100DPVWB 93

10010ZDWOB 10000YLMNF 1

00101CRVFE 01110BZLDR 77

11011XNMVQ 11100WUCUC 86

01011AJDLC 10011ZQSKO 94

10100VXCCO 00111UERAS 2

00010YSTSR 10101XAIRD 11

10000SGKJD 01010AWZHP 19

01101VCJZP 11100VKYXB 28

11011QYAPB 01000YFPOF 36

01001TMZGE 10011TTGEQ 44

10111WHPWQ 00101VPFUC 53

00010RDGMC 11011QLWLO 61

11000URFDO 01011TZVBS 69

01110PNWTR 11100OULRD 78

11001SBNJD 00010RQCIP 86

10001NWMAP 10000MEBYB 95

00111QSDQA 00101PASPE 3

10000LGUHE 11011KOJFQ 11

01110OCTXQ 01001NJIVC 20

11110IYKNC 00110IFZMO 28

00000LLAEN 10010LTQCR 36

10111GHZUR 00000GPPSD 45

00101JVQKD 11110IDGJP 53

11001ERPBP 01001DYWZB 62

01110HNGRA 11001GUVPE 70

11100CAXHE 00111BIMGQ 78

00010FWWYQ 10000EELWC 87

10110AKNGB 01110ZACNO 95

01101DGEWN 11110CNTDR 3

11011YCDNR 01001FJSTD 12

01101BPTDD 10111AXJKP 20

00100VLKUO 00101DTAAA 29

10010YHJKA 10001YPZQE 37

00100TVAAE 01110BCPHQ 45

11001WRRRQ 11100WYGXC 54

01011ZEQHB 10010YUFNN 62

10101UAHXN 00111TIWER 70

00011XWGOR 10101WENUD 79

10010SKXEC 01011RRMLP 87

01100VGOUO 11101UNDBA 96

01001QMXMO 11010QCMLA 4

11001TIODA 01001TPDBE 64

11110OEFTD 10101OLUSP 73

00000RREKP 00011RZTIB 81

10110MNVAB 11000LVKYN 90

01110PJMQM 01110ORBPR 98

11001KXLHQ 11010JEAFC 6

01111NTCXC 10000MARVO 15

10101IGANO 00111HWIMA 23

00000LCREZ 10001KKHCD 31

10110GYIUD 01001FGXSP 40

01100JMHKP 11110ITWJB 48

11011EIYBB 00000DPNZN 57

00111GDPRM 10110GLEQQ 65

10101BROHQ 00111BZDGC 73

00011ENFYC 11001EVUWO 82

11100ZBWOO 01111YILNA 58

01100CXVFZ 11101BEKDD 66

11010XSLVD 00000WABTP 75

10101AGCDP 10110ZOSKB 83

00011VCBUA 01100CKQAN 92

11011YQSKM 11011XFHQQ 0

01101TMRAQ 01111ATYHC 8

11010WHIRC 00101VPXXO 17

00000RVZHN 10010YDONZ 25

10100TRYXZ 00100TZNED 33

00011WNPOD 11100WUEUP 42

11001RBGEP 01010RIVLB 50

01111UWEVA 10101TEUBM 59

10010PKVLM 00011OALRQ 67

00000SGMBQ 10011ROCIC 75

10110NCLSB 01100MJAYO 84

01010QQCIN 11010PXROZ 92

11001LLTYZ 01000KTIFD 0

01111OHSPD 10100NPHVP 9

00001JVJFO 00011IDYLA 17

10000MRIVA 11001LYPCM 26

01110HFZMM 01111GMOSQ 34

11000JBPCQ 11010JIFJC 42

01111EWOTB 10000EEEZN 51

10111HKFJN 00110HSVPZ 59

00001CGWZZ 10001BNLGD 67

10111FUVQC 01001EJKWP 76

01100AQMGO 11111HXBMA 84

11000DLDWA 00001CTSDM 93

00110YZCNM 10000FHRTQ 1

10101BVTDP 00110ACIJB 9

00011WRKTB 11000DYZAN 18

11111ZFIKN 01111YMYQZ 26

01100CAZAZ 11111BIPHD 34

11010WOYQC 00001WEGXO 43

10100ZKPHO 10110ZSEFA 51

00100UGGXA 01100UNVWM 60

11011XUFOL 11000WBUMQ 68

01101SPWEP 01110RXLCB 76

11011VLNUB 00101UTCTN 85

00010QZMLN 10011PHBJZ 93

10100TVDBY 00111SCSZC 1

00010OJTRC 11100NYJQO 10

11000RESIO 01010QMIGA 18

01101MAJYA 10100LIZWM 27

11011POAOL 00101OWPNP 35

00001JKZFP 10011JRODB 43

10110MGQVB 01101MNFUN 52

01010HTPMN 11011HBWKZ 60

11000KPGCY 01010KXVAC 68

01111FDXSC 10100ELMRO 77

00001IZWJO 00010HGLHA 85

10001DVMZZ 11001KCCXL 94

00111GIDPL 01101FQTOP 2

11000BECGP 11011IMSEB 10

01010ESTWB 10001DIIUN 19

10110ZOKMM 00110GVZLY 95

00001CKJDY 10010BRYBC 3

10111FXATC 01000EFPSO 12

01101ZTRKO 11111ZBGIA 20

11000CPQAZ 00001CXFYL 29

01110XDHQL 10001XKWPP 37

10100AZFHP 00110ZGNFB 45

00010VMWXA 11000UCMVN 54

11111YINNM 01010XQDMY 62

01101TEMEY 11110SMBCC 70

11011WSDUC 00001VZSSO 79

10110ROUCN 10111QVJJZ 87

00100UJTTZ 01101TRIZL 96

10010PXKJL 11000OFZQP 4

01101STBZP 01110RBQGB 12

11101MHAQA 00100MOPWM 21

00011PDQGM 10011PKGNY 29

10101KZHXY 00111KGXDC 37

00010NMGNB 11101NUWTO 46

11010IIXDN 01011PQMKZ 54

01100LWWUZ 10100KLDAL 63

11011GSNKL 00100NZCQP 71

00001JOEAO 10010IVTHA 79

10101EBDRA 01101LJSXM 88

01010HXUHM 11101GFJNY 96

11000KTLXY 01011JAAEC 4

01110FHJOB 10100EOZUN 13

00010IDAEN 00010HKQLZ 21

10001CQRVZ 11010CGHBL 30

00111FMQLK 01100FUFRP 38

11001AIHBO 11011AQWIA 46

01000DWGSA 10001CDNYM 55

10110YSXIM 00101XZMOY 63

00000BNOYX 10010AVDFB 71

10110WBNPB 01000VJUVN 80

01111ZXEFN 11110YFTLZ 88

11001ULUVZ 00011TAKCL 97

01111XHTMK 10001WOJSO 5

10100SCKCO 00111RKAJA 13

00000VQBTA 11001UYQZM 22

11110PMAJM 01000PUPPY 30

01101SIRZX 11110SPGGB 38

11011NWIQB 00000NDXWN 47

10111QRHGN 10111PZWEZ 55

00101LFYWY 00111SNNVK 64

10010OBXNK 11001NJELO 72

01100JXNDO 01111QEDBA 80

11100MLETA 00100LSUSM 89

00011HGDKL 10000OOLIX 97

10101KUUAX 00110JKJZB 5

00111NQLQB 11101MYAPN 14

11010IMKHN 01011HTZFZ 22

广告位
本文来自网络,不代表币圈信息资讯立场,转载请注明出处:https://www.huyuew.com/?p=2915

作者: qer123

上一篇
下一篇

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

联系我们

联系我们

0898-88881688

在线咨询: QQ交谈

邮箱: email@wangzhan.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部
首页
欧意注册
欧意下载