-
2018-09-10 13:20:47
#C/C++实现区块链(下)之区块链实现(原创代码,转载必究)
算法原理传送门:https://blog.csdn.net/qq_27180763/article/details/82588136
算法实现传送门:https://blog.csdn.net/qq_27180763/article/details/82588194###看了上面的算法,相信大家基本可以猜到,相对于比特币的限量的性质,对于本算法来说,难解程度的根本原因即为向量环路的迭代次数。迭代次数越多,则算法越难解,从而导致解题需要花费更多的时候,再基于这点,在数学上,当解题次数足够大时,效率会无限小,从而导致了解题时间无限长最后导致加密货币的发放无限小。
###创世区块创建(部分大妈在前面有实现,而区块这一部分将会详细解答)
void Make_First_Block() { Getpublickey(); blo.data = circle; blo.pre_hash = 0; blo.this_hash = (blo.pre_hash+public_Key) * (a+b); Block.push_back(blo); }
###由于在区块链中,本区快的数字签名是基于上一区块的数字签名和区块本身的DATA决定, 所以,在这里我们采用了上一区块的数字签名加上难解的PublicKey乘上长轴和短轴的和实现本区块的数字签名的算法。
###添加区块(当当前区块被算出时,添加新区块,检查签名正确性。)
void Append_Block() { pre_blo = blo; bool flag = true; auto temp = public_Key; circle = circle + 1; Getpublickey(); blo.data = circle; blo.pre_hash = blo.this_hash; blo.this_hash = (blo.pre_hash + public_Key) * (a + b); for(list<block>::iterator itor = Block.begin(); itor != Block.end(); itor++) { if ((*itor).this_hash != (*itor).pre_hash + temp * (a + b)) { flag = false; break; } } if (flag) { Block.push_back(blo); }; }
###这个迭代其实可以不用的,因为我在外部还定义了一个block类型的全局变量Pre_block和blo。Pre_block存储了上一个区块的信息。而本区块的信息则存储在Blo中。只有当用户解出当前区块后,才可以得到新区块。而data参数,为了方便仅存储了当前区块所在的位置。
###区块的计算(用类实现)
class Get_Block :Create_Block { public: int diffcult; int number = 1; Get_Block():Create_Block("OK"){ } void calc() { double start = clock(); while (true){ for (unsigned long long z = 1; z < ULLONG_MAX; z++){ for (unsigned long long j = 1; j < 65535; j = j + 1) { for (unsigned long long i = 1; i < 65535; i = i + 1) { Cryptography *person = new Cryptography(i,j,z); person->Getpublickey(); block bloc; bloc.data = circle; bloc.pre_hash = pre_blo.this_hash; bloc.this_hash = (blo.pre_hash + person->public_Key) * (i + j); if (blo.data == bloc.data &&blo.pre_hash== bloc.pre_hash && blo.this_hash == bloc.this_hash) { double end = clock(); cout << "历时"<<end-start<<"毫秒获得的第" << number++ <<"个区块信息为:" << endl; cout << "data:" << bloc.data << endl; cout << "this_hash:" << bloc.this_hash << endl; cout << "pre_hash:" << bloc.pre_hash << endl << "=======================" << endl << endl; this->Append_Block(); start = clock(); } delete []person; } } } } } };
###完整代码:
#include <iostream> #include <stdio.h> #include <windows.h> #include <string> #include <cmath> #include <climits> #include <list> #include <time.h> using namespace std; struct Moving_Point { unsigned long long x; unsigned long long y; }; int circle = 1; class Martix { public: static const int circle_s = 1; //假定向量环路为1; static const int KEY =Martix::circle_s * 8; private: unsigned long long martix_4_2[Martix::KEY / 2][2]; //存储向量矩阵 unsigned long long martix_8_8[Martix::KEY][Martix::KEY]; //存储由向量矩阵得到的转置矩阵 unsigned long long martix_complete[KEY * 2]; //存储操作完成后的矩阵(一维) public: Martix(string a) {}; Martix(int a, int b,int circle) { int key = 8; int cir = circle; while (cir--) { martix_4_2[key / 2 - 4][0] = (-1)*b; martix_4_2[key / 2 - 4][1] = (-1)*a; martix_4_2[key / 2 - 3][0] = b; martix_4_2[key / 2 - 3][1] = (-1)*a; martix_4_2[key / 2 - 2][0] = b; martix_4_2[key / 2 - 2][1] = a; martix_4_2[key / 2 - 1][0] = (-1)*b; martix_4_2[key / 2 - 1][1] = a; key += 8; } } void Change_New_Martix() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { martix_8_8[i][j] = 0; } } for (int j = 2; j < KEY / 2 + 2; j++) { martix_8_8[0][j] = martix_4_2[j - 2][0] * (-1); martix_8_8[1][j] = martix_4_2[j - 2][1] * (-1); } for (int i = 2; i < KEY / 2 + 2; i++) { martix_8_8[i][0] = martix_4_2[i - 2][0] * (-1); martix_8_8[i][1] = martix_4_2[i - 2][1] * (-1); } for (int i = 2; i < KEY / 2 + 2; i++) { for (int j = 2; j < KEY / 2 + 2; j++) { martix_8_8[i][j] = 0; } } } public: void Save_Martix() { int key = 0; for (int i = 0; i < KEY / 2 + 2; i++) { for (int j = 0; j < KEY / 2 + 2; j++) { if (martix_8_8[i][j] != 0) { martix_complete[key++] = martix_8_8[i][j]; } } } } unsigned long long GetPublicKey() { unsigned long long public_key = martix_complete[0]; for (int i = 1; i < KEY * 2; i++) { if (i % 2 == 0) { public_key = public_key + martix_complete[i]; } else { public_key = public_key * martix_complete[i]; } } return public_key; } }; class Cryptography :Martix { public: /*作为私钥,发送方保存内容*/ unsigned long long a; //椭圆长轴的半轴长度 unsigned long long b; //椭圆短轴的半轴长度 /*作为公钥,接收方接受公钥*/ unsigned long long public_Key; //通过椭圆矩阵算法得到的公钥G Moving_Point p; //随机选定的在椭圆上的点 public: Cryptography(string a) :Martix("OK") {}; Cryptography(unsigned long long in_a, unsigned long long in_b,int diffcult) :Martix(in_a, in_b,diffcult) { this->a = in_a; this->b = in_b; p.x = 0; p.y = 0; public_Key = Getpublickey(); } unsigned long long Getpublickey() { Get_Public_Key(); return public_Key; } Moving_Point GetPoint() { Get_Point(); return p; } public: void PrintPrivateKey() { cout << "#############私钥:#############" << endl; cout << "长轴:" << 2*this->a << "\t\t"; cout << "短轴:" << 2*this->b << endl; } private: void Get_Point() { if (p.x == 0 && p.y == 0) { while (!Is_Moving_Point()) { Get_Moving_Point_P(); } } } void Get_Public_Key() { this->Change_New_Martix(); this->Save_Martix(); this->public_Key = this->GetPublicKey(); } void Get_Moving_Point_P() //得到一个随机的在椭圆上的点的坐标 { for (int i = 0; i < this->a; i++) { for (int j = 0; j < this->b; j++) { p.x = i; p.y = j; } } } bool Is_Moving_Point() { if (pow(b, 2)*pow(p.y, 2) + pow(a, 2)*pow(p.x, 2) == pow(a, 2)*pow(b, 2) && p.y <= a && p.x <= b) return true; else return false; } }; struct block { unsigned long long this_hash; unsigned long long pre_hash; unsigned long long data; }; block blo; block pre_blo = {0,0,0}; class Create_Block:public Cryptography { public: list<block> Block; public: Create_Block(string a):Cryptography("OK") {}; Create_Block(int x = rand()*2, int y = rand(), int diffcult = 1):Cryptography(x,y,diffcult){ } void Make_First_Block() { Getpublickey(); blo.data = circle; blo.pre_hash = 0; blo.this_hash = (blo.pre_hash+public_Key) * (a+b); Block.push_back(blo); } void Append_Block() { pre_blo = blo; bool flag = true; auto temp = public_Key; circle = circle + 1; Getpublickey(); blo.data = circle; blo.pre_hash = blo.this_hash; blo.this_hash = (blo.pre_hash + public_Key) * (a + b); for(list<block>::iterator itor = Block.begin(); itor != Block.end(); itor++) { if ((*itor).this_hash != (*itor).pre_hash + temp * (a + b)) { flag = false; break; } } if (flag) { Block.push_back(blo); }; } }; class Get_Block :Create_Block { public: int diffcult; int number = 1; Get_Block():Create_Block("OK"){ } void calc() { double start = clock(); while (true){ for (unsigned long long z = 1; z < ULLONG_MAX; z++){ for (unsigned long long j = 1; j < 65535; j = j + 1) { for (unsigned long long i = 1; i < 65535; i = i + 1) { Cryptography *person = new Cryptography(i,j,z); person->Getpublickey(); block bloc; bloc.data = circle; bloc.pre_hash = pre_blo.this_hash; bloc.this_hash = (blo.pre_hash + person->public_Key) * (i + j); if (blo.data == bloc.data &&blo.pre_hash== bloc.pre_hash && blo.this_hash == bloc.this_hash) { double end = clock(); cout << "历时"<<end-start<<"毫秒获得的第" << number++ <<"个区块信息为:" << endl; cout << "data:" << bloc.data << endl; cout << "this_hash:" << bloc.this_hash << endl; cout << "pre_hash:" << bloc.pre_hash << endl << "=======================" << endl << endl; this->Append_Block(); start = clock(); } delete []person; } } } } } }; int main() { Create_Block * one = new Create_Block(); one->Make_First_Block(); Get_Block* two = new Get_Block(); two->calc(); return 0; }
##实现效果
###不得不说第一个区块的挖掘永远是最快的。第二个区块确实要等好久才可以得出。以上即为C/C++实现区块链的全部源码。仅用于学习交流,不得用于商业用途,转载必究。
更多相关内容 -
区块链java代码实现
2020-08-28 04:55:15主要为大家详细介绍了区块链java代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
大势所趋——区块链(Python代码实现)
2022-02-18 10:24:283 区块链Python代码实现 4 致谢 1 区块链和人工智能 人工智能和区块链诞生至今已经有了十几年,当这些技术出现时,人们都说他们会改变世界,但至今为止,这两项技术对现实的影响依然有限。从技术上看人工智能...目录
1 区块链和人工智能
人工智能和区块链诞生至今已经有了十几年,当这些技术出现时,人们都说他们会改变世界,但至今为止,这两项技术对现实的影响依然有限。从技术上看人工智能的原理其实是从大量数据中寻找规律或模式,但区块链的技术原理是什么呢?在我看来区块链的原理一直处于云里雾里,有很多近乎玄学的解释将其笼罩,有人从经济学解释,有人从社会学解释,从”人文“角度解释的区块链总是过于夸大其词,这些说法中往往又包含不良用心。
区块链的设计思想非常伟大,它集合了很多智慧的结晶,例如加密算法,分布式算法,心理学,经济学等,由于它跨越领域太多,这也是它特别“玄学”的原因
其实区块链和人工智能一样,从技术的角度看去,他们都有着极为美妙的设计思想,这些设计的美妙就像唐诗宋词,就像毕加索的话,如果我们没有去欣赏它的美,那岂不可惜。相比于人工智能,我认为区块链在技术上更容易被普通人触碰,因为前者需要大量的数据和算力,而后者只要我们掌握其技术原理就能参与其中,不需要太高的硬件门槛。
2 区块链的相关概念及流程
2.1 官方定义
区块链的官方定义是:一个分布式账本,一种通过去中心化、去信任的方式集体维护一个可靠数据库的技术方案。那么对于圈外人该如何理解呢?以下我会详细描述一个区块链的产生过程和实现意义,从而给大家构建出一个清晰的区块链概念。
在大势所趋——区块链这篇文章中我讲解了一些基本概念。
2.2 普通区块&创世区块
我们以btc为例:“区块链”,顾名思义,就是由一个个区块依次连接起来组成的链条,可以类比为一条无限长度的直线铁链,每个铁环就是一个区块。那么区块的内容应该是什么呢?区块狭义上是有两种的,一个是普通区块,一个就是创世区块。创世区块就是一项区块链项目中的第一个区块,由于个人水平有限,对创世区块没有做过详细研究,但是根据我的了解,创世区块应该是具备与普通区块相似结构的,但会肯定会加入一些创始人想说的东西,并且在有些项目中可能会多一条记录,就是coin的发行量,例如swtc的6000亿数目就是写在创世区块之中的,一旦发行,无法修改。
那么,一个普通区块中到底有什么?
(1)index:就是从0-n依次产生的数字,可以称之为链高度。
(2)hash:一个长度为256位随机数,是这个区块的唯一编号。
(3)previous hash:上一个区块的hash,一个普通区块有且仅有一个previous hash,这就是区块链之所以称为链的原因,就是这么一环套一环链接而成的。
(4)tempstamp:用于记录该区块诞生的时间。
(5)difficulty:直观体现创造该区块的难度。
(6)nonce:随机数,用于产生下一个区块。
上述的都存在区块头中。
(7)data:存储的交易记录。只有这个存在区块体中。
2.3 区块的工作流程
(1)如果A要和B达成一笔交易,比如A转给B一个btc,B给A打10w的RMB。A首先将自己的btc来源信息、交易人等发送给B,同时还要拷贝一份发到全网。什么?这样还有隐私可言吗?当然,聪明的中本聪当然不会犯这么低级的错误。在区块链中,每个交易个体(也可以理解为每个网络节点)都会有一对公钥和私钥,公钥相当于一个“收款地址”,而私钥是一个表明自己身份的256位的数字,目前一般是用sha265来生成的,这样,别人并不知道交易的双方是谁。发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私钥对摘要进行加密,加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。
(2)那么此时,这笔交易是否就完成了呢?如果这就算完成了,那跟A直接用包裹装10w现金快递给B有什么区别呢?此时,全网的矿工都会得到这个交易记录,那么全网的矿工都会为了若干奖励开始创建区块的工作,矿工会利用hash函数生成一个256位的唯一编号赋予这个区块,但是这个编号并不是简简单单随便生成的。编号是根据区块的具体内容如交易内容、nonce等唯一确定的,换句话说,两块内容相同的区块所对应的编号一定是唯一的。可是你会问:这又怎么了?并不难啊。错!中本聪为了控制区块的生成时间,使区块的生成速率满足全网的每10分钟一个的标准,制定了严格的区块生成校验规则,也就是说,能不能生成一个成功的区块要看你的编号是否符合这个规则。例如:生成编号中的前n位必须为‘0’。
由于区块的交易内容是无法修改的,因此矿工们只能通过修改nonce去不断尝试这个函数,直到生成了一个成功的区块为止。如果当区块平均生成时间变快或者变慢,那么系统会对区块校验规则进行相应的调整,从而使平均的生成时间能够控制在规定范围。
如果一个矿工完成了一个区块,会立刻告知其他矿工,如果其他矿工此时没有完成新的区块生成,则会停下手头的工作,对区块进行验证,需要确认的信息主要有如下几点:
1).区块的编号有效;这个只要将区块放入哈希函数中,看产生的编号是否和该区块中的编号一致即可。
2).区块的前一个区块有效;之前提过,区块是一个串联的,每一个普通区块都会记载前一个区块的编号,这需要其他矿工对比当前的区块链的最后一个区块,看是否相同。
3).交易清单有效;就是说要验证A到底有没有这一个btc可以给B。在区块链的交易信息中,会记录交易中所有btc的前世今生,区块链可以做到追本溯源,因此每一个btc在哪里,为什么在这里都可以一目了然,所以这点也没问题。
当验证完一个全新的区块后,全网就会认为这个区块有效,会将它添加到现有的区块链末端,同时结束针对该区块的挖矿工作,投入到下一个挖矿周期中。
(3)但是不难想象,这样的机制是存在冲突的隐患的,就是这么巧,两个矿工同时制作了一个正确的区块,那么此时不必二选一,可以将原来线性的区块链改成树状:
但是这样会导致未来在A、B后都会增加相应的区块,那么谁长谁将作为主链延伸下去,另一个也许会渐渐被遗忘,除非哪天它变得更长。
3 区块链Python代码实现
话不多说,我们看看如何用python代码把最基本的区块链原理编写出来。首先我们看区块链的数据结构,它包含三部分信息,一是用于标志自己的id,它是一个整数,第二个是用于记录前一个区块的id,也是一个整数,由于区块用于记录信息,因此它还包含一个字段,我们用history来表示,这个字段用来记录当前发生了的信息,区块链最大的作用就是让这段信息可验证而且不可更改,我们先看数据结构的定义,先创建文件block.:
class Block: def __init__(self): self.id = None self.history = None self.parent_id = None
接下来我们看看区块如何行成”链“,同时如何记录信息。假设我们想要记录这么一个事件:张三想跟李四用一百块买三条鱼,李四收到一百块后给了张三三条鱼”,那么我们可以使用下面代码用区块链进行记录,创建main.py,然后给出如下代码:
from block import * block_A = Block() block_A.id = 1 block_A.history = '张三想要三条鱼' block_B = Block() block_B.id = 2 block_B.parent_id = block_A.id block_B.history = '张三跟李四买三条鱼' block_C = Block() block_C.id = 3 block_C.parent_id = block_B.id block_C.history = '张三给李四一百块' block_D = Block() block_D.id = 3 block_D.parent_id = block_B.id block_D.history = '李四收到张三一百块' block_E = Block() block_E.id = 3 block_E.parent_id = block_B.id block_E.history = '李四给张三三条鱼'
从代码上看不同区块之间通过parent_id形成了前后连接关系,这就是区块链中的“链”,但现在还有一个严重问题,那就是信息可以更改,假设张三想来着,他把block_E里面的history改成李四给张三两条鱼,然后找李四算账那怎办,或者李四想赖账,把block_D中的history改成“李四收到张三五十块”,然后又找张三要钱,那怎么办。
为了确保信息不被更改,我们需要对每个区块的内容进行加密或者哈希,因此上面代码修改如下:
这里需要一些知识储备,我已经总结好了:学习区块链的几个小知识(Python实现)
from block import * import hashlib import json block_A = Block() block_A.id = 1 block_A.history = '张三想要三条鱼' block_B = Block() block_B.id = 2 block_B.parent_id = block_A.id block_B.history = '张三跟李四买三条鱼' block_B.parent_hash = hashlib.sha256(json.dumps(block_A.__dict__).encode('utf-8')).hexdigest() block_C = Block() block_C.id = 3 block_C.parent_id = block_B.id block_C.history = '张三给李四一百块' block_C.parent_hash = hashlib.sha256(json.dumps(block_B.__dict__).encode('utf-8')).hexdigest() block_D = Block() block_D.id = 4 block_D.parent_id = block_C.id block_D.history = '李四收到张三一百块' block_D.parent_hash = hashlib.sha256(json.dumps(block_C.__dict__).encode('utf-8')).hexdigest() block_E = Block() block_E.id = 5 block_E.parent_id = block_B.id block_E.history = '李四给张三三条鱼' block_E.parent_hash = hashlib.sha256(json.dumps(block_D__dict__).encode('utf-8')).hexdigest()
有了哈希,如何任何一个区块被修改,那么当前区块和后续区块的哈希都得修改,例如李四把block_C的history改成“张三给李四五十块”,那么我们看到李四必须要把block_C到block_E的哈希全部改了,如果这条链很长的话,李四改起来就非常吃力。同时为了确保信息的可靠性,
张三和李四需要把上面的区块链发送给其他一百个人进行存储,这样一来张三或李四想要赖账那就更加困难,因为有一百个见证者。区块链信息记录的特点是只增不删,因此张三想要赖账的话,他只能在上面基础上再增加一个区块,也就是block_F, 里面的history写上了“张三收到李四两条鱼”,然后将这个区块发给其他100个人,为了防止随意添加区块造成信息混乱的情况,在区块链中有一个专门的角色负责将新增的区块添加到现有的区块链上,这个角色拿到区块数据后,,在不考虑parent_hash字段的情况下将数据序列化,接着找到一个特定字符串,这个字符串必须满足给定要求,那就是它与区块序列化的数据合并后,算出来的哈希值必须以5个0开头,我们从代码上看看这是什么意思:
#proof-of-work block_F = Block() block_F.id = 6 block_E.parent_id = block_E.id block_E.history = '李四给张三三条鱼' #注意我们这里没有设置parent_hash字段 block_F_serialized = json.dumps(block_F.__dict__).encode('utf-8') print(block_F_serialized) for i in range(10000000): proof_of_work = str(i).encode('utf-8') result = hashlib.sha256(block_F_serialized + proof_of_work).hexdigest() if result[:5] == '00000': #哈希结果只有以5个0开头才能添加区块到公链 print(proof_of_work) print(result) break #找到特定字符串后获取回报,所谓挖矿就是干这个事情
上面代码运行后所得结果为:
b'{"id": 6, "history": null, "parent_id": null, "parent_hash": null}' b'553448' 0000034ba1dabbf794212082b47a6bcc98cb33eed86d363993270ca58e243bb9
也就是说特定字符串内容为”553448”,它能使得新区块内容和它结合后算出来的哈希以5个0开头,专门负责给区块查找这种字符串的角色就叫“矿工”,这个查找过程就叫挖矿,一旦找到这个特定字符串后他就能获取回报,也就是加密货币。
现在我们实现了数据的修改很困难,同时区块的添加也需要付出一定成本,但假设李四就是拼了老命也想把以前记录的信息修改掉,并为此愿意付出一切代价,假设当前区块链有1000个数据块,他想修改第一个块记录的信息,于是他修改了后面999个数据块的数据,但原始数据被其他人掌握着,因此他自己修改的数据就不会被采纳。由于区块链数据被分布存储在不同地方,于是在某项地方数据可能会被修改,这样就会出现数据不一致的情况,区块链还有一个重要任务就是在这种情况下达成共识。
同时当有新的区块需要加入公链时,我们需要将新增区块通过广播的方式通知所有人,于是就有个问题,那就是有些人较早获得通知,有些获得通知较晚,更有可能你会同时收到多个消息,假设现在公链上最后一个消息编号为5,此时你同时收到了两个消息东边发来的消息为history:王五想跟李四买一斤虾;西边发来的消息为history:李六想跟张三买两条鱼,那么我们应该将哪个消息作为编号6呢,此时的做法是先等等,如果过了一会西边发来了5条消息,同时东边只发来2条消息,那么就把消息少的抛弃,将消息多的经过处理后添加到公链。
通过选择数据多的添加到公链有个好处就是让数据的修改变得几乎不可能,例如李四辛辛苦苦花了半小时修改了999个区块,然后想要广播给其他人,但是很可能这段时间内有10000个新区块生成,于是他修改的999个区块就会被丢弃掉,这样他就无法进行任何修改。这个过程其实涉及到非常复杂的分布式计算理论,我们无法简单使用代码实现。
4 致谢
区块链是个神奇的技术,期望未来区块链可以真的带来巨大的变革。要知道,随着AI的兴起,区块链的问世,属于程序员的数字时代会进一步升华,互联网时代只是一个开始!
————————————————
参考:https://blog.csdn.net/BmwGaara/article/details/79059007 -
区块链的简单实现
2021-04-24 09:50:15手写区块链,先实现Block和Chain等简单的数据结构,后续继续引入工作量证明,实现挖矿,模拟分布式节点通信什么是区块链
一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库
下面我将简单用nodejs实现一个简单的区块链,它具有区块链的基本特性,但没有涉及PoS of PoW。
块结构
一个块Block一般有:- index 块号
- previousHash 上一个区块的hash值
- timestamp 时间戳
- data 存放的数据
- hash 区块的hash值
class Block { constructor(index, previousHash, timestamp, data, hash) { this.index = index; this.previousHash = previousHash; this.timestamp = timestamp; this.data = data; this.hash = hash.toString(); } toString(){ return "\n{\nindex:"+this.index+",\npreviousHash:'"+this.previousHash+"',\ntimestamp:"+this.timestamp+",\ndata:'"+this.data+"',\nhash:'"+this.hash+"'\n}\n" } }
我们每生成一个区块,我们都会给这个区块按照特定的hash算法,来得到一个hash值,一般来说,只要这个区块的index,previoushash,timestamp,data有改动,那么它所算出的hash值也会改变,所以当你想要篡改某个区块的数据时,你需要将后面所有的区块的previoushash都进行篡改。
创世区块
第一个区块是没有前置hash的,是特殊的一个区块,我们用代码将这个区块写死
const genesisBlock = new Block.Block( 0, null, 1619079309.946, "genesis block", '80dea37cccca5fb56b9b78dbe2733fb19e8ee2aa7bb03d4ac1e361fe3fad7b51' );
hash
本文采用sha256来求得hash值
exports.caHash=function (index, previousHash, timestamp, data){ return sha256(index + previousHash + timestamp + data).toString(); }
验证块的有效性
下面是验证单个块是否有效,可以根据下面遍历整个链是否有效。
vaildBlock(block,lastBlock) { if (!Block.isValidBlockStructure(block)) return false; if ( (block.index==lastBlock.index+1) &&(block.previousHash==lastBlock.hash) &&Block.caHash(block.index,block.previousHash,block.timestamp,block.data) ) return true; return false; }
记录数据
creatBlock(data){ var lastBlock=this.getLastBlock(); var newIndex=lastBlock.index+1; var newTime=new Date().getTime()/1000; var newPreHash=lastBlock.hash; var newhash=Block.caHash(newIndex,newPreHash,newTime,data.toString()); return this.blocks[this.blocks.length]= new Block.Block( newIndex, newPreHash, newTime, data, newhash ); }
从其他节点接收一个块
addBlock(block){ if (validBlock(block,this.getLastBlock())){ blocks.push(block); return true; } return false; }
编写测试代码
var Chain=require("./Chain"); var BlockChain=new Chain.BlockChain(); var http=require('http'); var fs=require('fs'); var querystring=require('querystring'); var server=http.createServer(function (req,res) { var url=req.url; if (url=="/get"){ res.writeHead(200,{'content-type':'text/plain'+'charset=UTF8'}); var str=BlockChain.blocks; res.end(str.toString()); }else if (url=="/creat"){ var data=[]; req.on('data',function (chunk) { data.push(chunk); }) req.on('end',function (chunk){ var dataObj=querystring.parse(data.toString()) BlockChain.creatBlock(dataObj["data"]); var lastblock=BlockChain.getLastBlock(); res.setHeader('content-type','text/plain;charset=UTF8'); res.write(lastblock.toString()); res.end("生成区块"+lastblock.index+"号成功!"); }) }else { res.setHeader('content-type','text/html;charset=UTF8'); fs.readFile('./client.html',function (err,data) { res.write(data); res.end(); }) } }); server.listen(2345);
测试结果
输入一些数据,然后点击生成区块:
点击获取区块链:
完整代码
你可以从仓库里获取完整代码:
github: https://github.com/Lixingwei0623/ablockchain.
gitee: https://gitee.com/li-xingwei/simple-block-chain. -
区块链的java实现
2016-12-29 18:16:28本文90%来着于翻译,原文地址:http://java-lang-programming.com/en/articles/29概述MerkleTree被广泛的应用在比特币技术中,本文旨在通过代码实现一个简单的MerkleTree,并计算出Merkle tree的 TreeRoot。...本文90%来着于翻译,原文地址:http://java-lang-programming.com/en/articles/29
概述
MerkleTree被广泛的应用在比特币技术中,本文旨在通过代码实现一个简单的MerkleTree,并计算出Merkle tree的 TreeRoot。
Merkle Tree 是一种数据结构,用于验证在计算机之间和之间存储,处理和传输的任何类型的数据。
目前,Merkle树的主要用途是确保从对等网络中接收的数据块未受损和未改变,和检查其他对等网络没有撒谎发送假数据块。
Merkle Tree应用举例
- 比特币
- Git
- Amazon’s Dynamo
- Gassandra
比特币中的应用
比特币中每个块中都包含了所有交易的集合签名,这个签名就是用Merkle tree实现的,Merkle树用于比特币以汇总块中的所有事务,产生整个事务集合的整体数字指纹,提供非常有效的过程来验证事务是否包括在块中。
Merkle树一个很重要的用处是检查块中是否包含指定的交易,Merkle树是通过递归哈希节点对来构造的,直到只有一个哈希。
Merkle tree 代码实现
哈希树的跟节点称为Merkle根,Merkle树可以仅用log2(N)的时间复杂度检查任何一个数据元素是否包含在树中:
package test; import java.security.MessageDigest; import java.util.ArrayList; import java.util.List; public class MerkleTrees { // transaction List List<String> txList; // Merkle Root String root; /** * constructor * @param txList transaction List 交易List */ public MerkleTrees(List<String> txList) { this.txList = txList; root = ""; } /** * execute merkle_tree and set root. */ public void merkle_tree() { List<String> tempTxList = new ArrayList<String>(); for (int i = 0; i < this.txList.size(); i++) { tempTxList.add(this.txList.get(i)); } List<String> newTxList = getNewTxList(tempTxList); while (newTxList.size() != 1) { newTxList = getNewTxList(newTxList); } this.root = newTxList.get(0); } /** * return Node Hash List. * @param tempTxList * @return */ private List<String> getNewTxList(List<String> tempTxList) { List<String> newTxList = new ArrayList<String>(); int index = 0; while (index < tempTxList.size()) { // left String left = tempTxList.get(index); index++; // right String right = ""; if (index != tempTxList.size()) { right = tempTxList.get(index); } // sha2 hex value String sha2HexValue = getSHA2HexValue(left + right); newTxList.add(sha2HexValue); index++; } return newTxList; } /** * Return hex string * @param str * @return */ public String getSHA2HexValue(String str) { byte[] cipher_byte; try{ MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(str.getBytes()); cipher_byte = md.digest(); StringBuilder sb = new StringBuilder(2 * cipher_byte.length); for(byte b: cipher_byte) { sb.append(String.format("%02x", b&0xff) ); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } /** * Get Root * @return */ public String getRoot() { return this.root; } }
数据准备
我们将交易的数据,放入到List中:
List<String> tempTxList = new ArrayList<String>(); tempTxList.add("a"); tempTxList.add("b"); tempTxList.add("c"); tempTxList.add("d"); tempTxList.add("e");
实现过程
- 准备交易数据
- 计算出每个数据的hash值,从左到右逐步组成树的左右节点
- 执行循环知道最后只剩下一个数据
private List<String> getNewTxList(List<String> tempTxList) { List<String> newTxList = new ArrayList<String>(); int index = 0; while (index < tempTxList.size()) { // left String left = tempTxList.get(index); index++; // right String right = ""; if (index != tempTxList.size()) { right = tempTxList.get(index); } // sha2 hex value String sha2HexValue = getSHA2HexValue(left + right); newTxList.add(sha2HexValue); index++; }
测试
package test; import java.util.ArrayList; import java.util.List; public class App { public static void main(String [] args) { List<String> tempTxList = new ArrayList<String>(); tempTxList.add("a"); tempTxList.add("b"); tempTxList.add("c"); tempTxList.add("d"); tempTxList.add("e"); MerkleTrees merkleTrees = new MerkleTrees(tempTxList); merkleTrees.merkle_tree(); System.out.println("root : " + merkleTrees.getRoot()); } }
执行结果
本文从简单二叉树的形式实现了简单的MerkleTree,计算出TreeRoot,但是实际上的的MerkleTree不拘谨与二叉树还可能是多叉树。 -
基于区块链技术的商品溯源系统的设计与实现
2020-03-12 12:23:41基于区块链技术的商品溯源系统的设计与实现,张皓明,漆涛,随着经济的发展和生活水平的进步,消费者对商品质量的要求日益提高,商品溯源作为商品质量的保障之一,得到了广泛的关注和应用。 -
基于区块链的食品安全溯源技术研究
2021-01-13 01:17:34针对如何从技术层面保障食品安全这一目的,本文通过将区块链技术与食品溯源技术结合的方法,设计了基于区块链的食品安全溯源体系结构。其中包含场景设计、系统架构、去中心化设计和共识机制,并详细阐述了所设计体系... -
C#区块链编程PDF版 qklbc.rar
2020-05-17 12:14:24C#区块链编程详细的讲解了区块链与比特币的关系,并且阐述了关键的存储和数字生成机制,让读者了解区块链的实在,并且知道如何运用区块链编程 -
【转】200行代码实现一个区块链之一-----最简单的区块链
2018-03-24 16:54:40只用200行Go代码写一个自己的区块链!...这篇文章就是帮助你使用 Go 语言来实现一个简单的区块链,用不到 200 行代码来揭示区块链的原理!高可用架构也会持续推出更多区块链方面文章,欢迎点击上方蓝色『高可用... -
基于区块链技术的P2P电能交易平台与配电网协同仿真
2021-05-06 11:53:18为了推动能源交易公平以及区块链技术在电力交易领域的应用, 实现P2P电能交易平台与配电网高效配合, 提出一种基于区块链技术的P2P电能交易平台与配电网的协同仿真框架. 根据区块链去中心化、安全性强、可追溯的特点, ... -
JAVA区块链项目
2018-08-10 15:49:46Java实现区块链代码。 有问题联系QQ88234213 。 里面有比特Coin教程 -
简易区块链C语言实现
2020-12-30 12:30:56在CSDN的第四个任务:实现一个最简单的区块链,不带区块链网络、时间戳、merkle tree等 虽然说技术上难度不大,但是想要实现它,还真是一个不小的工程。。。 除了 SHA256 的计算部分,其余的代码都是自己实现的,写... -
JAVA区块链项目实战(示例代码)
2021-03-07 23:00:40课程介绍全国首套,基于java的区块链实战教程。目的是让更多的java编程者了解区块链,掌握区块链开发。1、区块链理论:以node.js例子区块链原理有深刻理解;2、区块链java实战:深刻理解区块链原理后能用java编写... -
C++实现区块链的源码
2021-01-26 18:43:12看了上面的算法,相信大家基本可以猜到,相对于比特币的限量的性质,对于本算法来说,难解程度的根本原因即为向量环路的...创世区块创建(部分大妈在前面有实现,而区块这一部分将会详细解答)void Make_First_Block(... -
C/C++实现区块链(中)之算法实现(原创代码,转载必究)
2018-09-10 13:05:06C/C++实现区块链(中)之算法实现(原创代码,转载必究) 上一篇文章我们讲述了区块链实现的基本算法原理,传送门https://blog.csdn.net/qq_27180763/article/details/82588136 这一节我将用C/C++技术来和大家... -
易语言简单区块链源码
2018-04-07 15:11:20是JAVA翻译过来的,区块链学习基础,原文在https://blog.csdn.net/u010093971/article/details/79358730对照着看。 JAVA的类和易语言的类还是不同的,耽误了些时间。感觉易的类与其它语言差别满 大的。翻译到建链 -
区块链以及区块链技术入门详解
2018-01-30 15:35:09区块链是目前一个比较热门的新概念,蕴含了技术与金融两层概念。从技术角度来看,这是一个牺牲一致性效率且保证最终一致性的的分布式的数据库,当然这是比较片面的。从经济学的角度来看,这种容错能力很强的点对点... -
区块链简介
2020-11-03 18:38:061. 区块链的概念 狭义上讲,区块链是一种按照时间顺序将数据区块以链条的方式组合成特定数据结构,并以密码学的方式保证其不可篡改、不可伪造的去中心化共享总账(Decentralized Shared Ledger),能够安全存储简单... -
180行python代码实现区块链+猜单词游戏
2018-08-12 17:15:40180行python代码实现区块链+猜单词游戏 依赖环境:python3.5+ 依赖第三方库:requests,Flask 网络环境:局域网 参考引用: 区块链基础知识(4)-共识机制和挖矿(谁来记账)... -
C/C++区块链实现代码优化
2018-09-12 15:35:17C/C++区块链实现代码优化 源地址为:https://blog.csdn.net/qq_27180763/article/details/82588305 #include &amp;lt;iostream&amp;gt; #include &amp;lt;stdio.h&amp;gt; #... -
史上最详细的区块链技术架构分析
2021-01-27 12:54:44数据存储主要基于Merkle树,通过区块的方式和链式结构实现,大多以KV数据库的方式实现持久化,比如比特币和以太坊采用的leveldb。账户和交易的实现与安全这个功能基于数字签名、哈希函数和非对称加密技术等多种密码... -
基于Java开发一套完整的区块链系统(附源码)
2021-01-16 10:45:00来源:https://blog.csdn.net/victory_long前言近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术... -
简单区块链Python实现
2019-11-04 16:31:39什么是区块链 区块链是一种数据结构,也是一个分布式数据库。 从技术上来看:区块是一种记录交易的数据结构,反映了一笔交易的资金流向。系统中已经达成的交易的区块连接在一起形成了一条主链,所有参与计算的节点都... -
以太坊区块链入门之实现简单DApp开发
2022-01-20 20:25:15前期准备 本dapp是采用ganache-cli的私链开发 //安装ganache-li sudo npm install -g ganache-cli //安装solidity(我刚开始用...若web3js始终安装报错,请见博主另外一篇博客https://blog.csdn.net/holy19__/article/d -
基于区块链溯源系统后端开发
2022-04-17 21:18:571.1 goSdk0_1 解决Cors跨域问题的中间件 go sdk创建客户端操作区块链的配置文件 Fabric Info,存放model结构体的文件 main函数文件 路由组执行函数的文件,主要是调用start.go文件中函数来实现操作逻辑。 底层函数的... -
区块链的技术原理
2021-09-07 11:11:37本文如图3.1所示,区块链基础架构模型可以分为六层,自底向上可分为数据层、网络层、共识层、激励层、合约层和应用层。其中数据层、网络层和共识层是区块链技术的必需的三层,其它层可以根据不同区块链系统进行取舍... -
北京大学肖臻老师《区块链技术与应用》公开课笔记5——BTC具体实现篇
2020-02-16 14:58:45北京大学肖臻老师《区块链技术与应用》公开课笔记 比特币具体实现篇,对应肖老师视频:https://www.bilibili.com/video/av37065233?p=5 全系列笔记请见:... -
区块链
2020-01-19 18:04:09比特币2.1 密码学原理2.1.1 比特币使用的哈希函数的性质2.1.2 签名2.2 数据结构2.2.1 Hash pointer2.2.2 merkle tree2.3 比特币的协议2.4 比特币系统实现2.4.1 UTXO2.4.2 比特币区块例子2.4.3 比特币交易的例子... -
区块链技术
2021-12-01 14:28:19一、什么是区块链 区块链实质是一个特殊的分布式数据库,存储于其中的数据或者信息具有“不可伪造”、“全程留痕”、“可以追溯”、“公开透明”、“集体维护”等特征。传统的分布式数据库主要是按照一定规则分成... -
北京大学肖臻老师《区块链技术与应用》ETH笔记 - 12.0 反思
2022-04-18 11:19:54首先我们必须了解智能合约里面并没有用到任何人工智能的技术,所以有人认为应该把它叫做自动合约,按照事先写好的代码,自动执行某些操作,现实世界当中,有什么自动合约的例子吗?ATM取款机可以看作物理世界上的一...