精华内容
下载资源
问答
  • 区块链是一种分散的数字分类帐,可以在全球数千台计算机上保存,可以在区块链金融市场交易所交易。...区块链技术以经济高效和...每层分别完成一项核心功能,并运用了一些技术来保证整个区块链系统的正常运作,各层之间互

    区块链是一种分散的数字分类帐,可以在全球数千台计算机上保存,可以在区块链金融市场交易所交易。这些是以抑制其后续修改的方式注册的。区块链技术以经济高效和透明的方式提高了安全性并加速了信息交换。它还免除了第三方的主要作用是在交易中提供信任

    和认证要素(如公证人和银行)。区块链开发技术应用在金融交易市场引发的能量是无与伦比的。

    区块链的基础架构,可分为六个层面:从底层向上依次为:数据层、网络层、共识层、激励层、合约层、应用层。每层分别完成一项核心功能,并运用了一些技术来保证整个区块链系统的正常运作,各层之间互相配合互相支撑,实现一个去中心化的信任机制,这也是区块链的魅力所在。

    但通过诸多资料总结,认为还有一个底层结构:加密层,也是区块链技术的基石,提供了整个区块链系统的安全性、匿名性的保证。但加密层中一些加密技术,实在烧脑,为了便于非专业人士的理解,还是以大多数的数据中将加密层融合在数据层中,进行简单介

    绍,或关注后续文章。

    区块链的层级架构

    1.数据层:包含了底层数据区块以及基础数据、基本算法等。

    数据层主要描述区块链技术的物理形式,是区块链上从创世区块起始的链式结构,每个区块包含了区块上的随机数、时间戳、公私钥数据等,是整个区块链技术中最底层的数据结构。

    2.网络层:包括分布式组网机制、数据传播机制和数据验证机制等

    网络层的主要目的是实现区块链网络中节点之间的信息交流。网络层主要通过P2P技术实现分布式网络的机制,网络层包括 P2P 组网机制、数据传播机制和数据验证机制,因此区块链本质上是一个P2P(点对点)网络,具备自动组网的机制,节点之间通过维护一

    个共同的区块链结构来保持通信。每一个节点既接收信息,也产生信息。

    3.共识层:主要包含共识算法以及共识机制,

    负责点对点模式的有效识别认证;共识层能让高度分散的节点在去中心化的区块链网络中高效地针对区块数据的有效性达成共识,是区块链的核心技术之一,也是区块链社群的治理机制。区块链中比较常用的共识机制主要有:工作量证明、权益证明和股份授权证

    明三种。

    数据层、网络层、共识层是构建区块链技术的必要元素,也是核心层,缺少任何一层都不能称之为真正意义上的区块链技术。

    4.激励层:主要包括经济激励的发行制度和分配制度。

    激励层的主要功能是提供一定的激励措施,鼓励节点参与区块链的安全验证工作。

    激励机制在公有链中是必需的。在联盟链中,所有节点都是已经经过组织认证的节点,不需要额外的激励,这些节点也会自发地维护整个系统的安全和稳定。

    在公有链中,节点不需要进行认证,可以随时加入、随时退出这个网络,记账需要消耗CPU、存储、带宽等资源,所以需要有一定的激励机制来确保矿工在记账的过程中能有收益,以此来保证整个区块链系统朝着良性循环的方向发展。

    以比特币为例,它的奖励机制有两种:1.在比特币总量达到2100万枚之前,新区块产生后系统奖励的比特币和每笔交易扣除的比特币(手续费)。2.当比特币总量达到2100万枚时,新产生的区块将不再生成比特币,这时奖励机制主要是每笔交易中扣除的手续

    费。

    5.合约层:主要包括各种脚本、代码、算法机制及智能合约。

    合约层是区块链可编程的基础。负责规定交易方式和流程细节:区块链可以开发理解为是去中心化不可篡改的账本,程序代码也是数据,也可以存到账本里。智能合约是存储在区块链中的一段不可篡改的程序,可以自动化地执行一些预先定义好的规则和条款,响

    应接收到的信息。合约发布之后,其运行和维护就交给全网的矿工去达成共识,是区块链去信任的基础。

    6.应用层:负责实现生活的各类应用场景。包含了各种应用场景和案例。

    比如搭建在以太坊、EOS上的各类区块链技术应用,即部署在应用层,并在现实生活场景中落地,来丰富整个区块链的生态。而未来的可编程金融和可编程社会也将会是搭建在应用层。

    激励层、合约层和应用层不是每个区块链应用的必要因素,一些区块链应用并不完整包含此三层结构。
     

    展开全文
  • 区块链系统开发.doc

    2020-12-15 09:31:13
    区块链系统开发找江经理微I537428855O电区块链系统开发区块链系统怎么样开发区块链系统哪里好开发区块链系统平台哪家强区块链模式赚钱吗 经商的难题在于解决竞争问题市场经济下各行各业都趋于过剩交通运输信息系统的...
  • 中心化交易所模式中有哪些模式: 区块链结合的应用涉及哪些...区块链交易所作为各种数字资产币的“中转站”,整个区块链生态中不可或缺的一部分,未来的发展趋势必然是全方位的,区块链交易所未来发展趋势是怎样的呢?
  • 区块链技术是当今新兴的一项技术,但这么说也不太妥当,因为十年前比特币的出现这项技术也随之诞生,...下面路普达(loopodo)小编就带大家来看一下,区块链系统开发的几大核心技术。 一、哈希算法 哈希算法是...

    区块链技术是当今新兴的一项技术,但这么说也不太妥当,因为十年前比特币的出现这项技术也随之诞生,但说其是当下很火热的技术是没问题的。区块链技术经过10年来的不断更新,终于在近两年都有了相关的应用落地,且进入了区块链3.0时代,未来的3-5年,相信会有更多的领域需要区块链系统来支撑。下面路普达(loopodo)小编就带大家来看一下,区块链系统开发的几大核心技术。

     

    一、哈希算法

    哈希算法是区块链系统开发中用的最多的一种算法,哈希函数(Hash Function),也称为散列函数或杂凑函数,哈希函数可将任意长度的资料经由Hash算法转换为一组固定长度的代码,原理是基于一种密码学上的单向哈希函数,这种函数很容易被验证,但是却很难破解。通常业界使用y =h (x)的方式进行表示,该哈希函数实现对x进行运算计算出一个哈希值y。

    二、 非对称加密算法

    非对称加密算法是一种密钥的保密方法,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法

    三、共识机制

    所谓“共识机制”,是通过特殊节点的投票,在很短的时间内完成对交易的验证和确认;对一笔交易,如果利益不相干的若干个节点能够达成共识,我们就可以认为全网对此也能够达成共识。

    现今区块链的共识机制可分为四大类:工作量证明机制(PoW)、权益证明机制(PoS)、股份授权证明机制(DPoS)和Pool验证池。

    四、智能合约

    智能合约就是传统合约的数字化网络化版本。它们是区块链上运行的计算机程序,可以满足在源代码中写入的条件时自行执行。智能合约一旦编写好就可以被用户信赖,合约条款就不会被改变,因此合约是不可更改的,并且任何人也不能修改。

    开发发人员会为智能合约编写代码,这样就是用于交易和两方乃至多方之间的任何交换行为。代码里会包含一些触发合约自动执行的条件。一旦完成编写,智能合约就会自动被上传到网络上。数据上传到所有设备上以后,用户就可以与执行程序代码的结果达成协议。

    五、分布式存储

    分布式存储是通过网络使用企业中的每台机器上的磁盘空间,并将这些分散的存储资源构成一个虚拟的存储设备,数据分散的存储在企业的各个角落。海量的数据按照结构化程度来分,可以大致分为结构化数据,非结构化数据,半结构化数据。

    区块链网络科技专注区块链系统开发,12年互联网系统软件开发经验

    我司承接区块链系统开发,以太坊开发,区块链交易系统开发、虚拟币平台开发,币币交易系统开发、数字货币钱包系统开发

    展开全文
  • 专注将区块链支付应用于全球跨境支付体系中,本文重点描述区块链技术开发应用于跨境支付领域前景展望全球经济发展的动力——金融服务产业,也是去中心化程度高的产业之一。金融交易双方的信息不对称导致无法建立有效...
  • 我个人从2016年就开始在做区块链系统开发的相关工作,最近身边很多朋友都在找我,想让我给他们讲讲区块链技术开发的相关知识,介于此,索性我就手撸了一套简单的java区块链系统,并写了一份详细的开发教程,发布到...


    Tips: 有需要资料或者讨论技术问题的,可以一起交流
    在这里插入图片描述

    文末有本文完整源码链接


    前言

    近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术进行研究,从各大招聘网站的区块链职位来看,薪资待遇都很不错,月薪30K到80K的都有,这对于我们程序员来说也是一种机遇,说明学习区块链技术刻不容缓。

    我个人从2016年就开始在做区块链系统开发的相关工作,最近身边很多朋友都在找我,想让我给他们讲讲区块链技术开发的相关知识,介于此,索性我就手撸了一套简单的java区块链系统,并写了一份详细的开发教程,发布到博客,希望能够对热爱区块链技术的小伙伴学习入门有所帮助。

    这套区块链系统代码非常简洁清晰,对于新手来说非常好理解,旨在告诉大家其实区块链技术并没有那么高深复杂。系统中除了springboot框架外,其他基本都是纯原生开发,就连P2P网络也是用的java socket来实现的。

    image.png

    一、区块链技术理论基础

    1、基本概念

    (1)区块链

    从技术层面来看,区块链是由包含交易信息的区块按照时间顺序从后向前有序链接起来的数据结构。

    从应用层面来说,区块链是一个分布式的共享账本和数据库,具有去中心化、不可篡改、全程留痕、集体维护、公开透明等特点。基于这些特点,区块链技术可以开发出自带信任体系特征的系统,实现多个主体之间的协作信任与一致行动。

    区块是区块链中的最小组成单位,主要有包含元数据的区块头和存放一条或者多条交易信息的区块体两部分组成,每个区块都记录着当前区块的哈希和上一个区块的哈希,通过两个哈希值的关联,让所有的区块以链式结构串起来,就形成了一个完整的区块链。

    区块链中的第一个区块被称作为创世区块,无需关联上一个区块。以BTC网络为例,每个区块主要包含如下信息字段:

    • 区块大小:用字节表示的区块数据大小
    • 区块头:组成区块头的包括以下几个字段:
      1. 区块头hash值
      2. 父区块头hash值
      3. 时间戳:区块产生的近似时间
      4. Merkle根:该区块中交易的merkle树根的哈希值
      5. 难度目标:该区块工作量证明算法的难度目标
      6. Nonce:用于工作量证明算法的计数器
    • 交易计数器:交易的数量
    • 交易:记录在区块里的交易信息

    区块链结构的简易模型,如下图所示:
    区块链模型.jpg
    区块中的交易集合记录的是一些特定的信息,在BTC网络中主要记录的是交易信息,在其他区块链网络中可以按照业务逻辑来保存相应的业务数据,如审计信息、版权信息、票据信息等,这也是区块链经常用来当做共享账本的原因。

    打个比方,可以把区块链当做一个用来记账的笔记本,一个区块就相当于一页纸,上面记录了某一时间段內所有的账务信息,从第一页到最后一页,按照页码顺序排列起来就是一个完整的账本。

    (2)区块链网络

    实际的区块链系统由多个区块链节点组成,每个节点都运行着相同一套区块链主干网络的副本,且各个节点间通过P2P网络进行交互,并最终形成一个完整的区块链网络系统。

    P2P网络具有可靠性、去中心化,以及开放性,各个节点之间交互运作、协同处理,每个节点在对外提供服务的同时也使用网络中其他节点所提供的服务。当某一个区块链节点产生新的区块时,会通过广播的方式告诉其他节点,其他节点通过网络接收到该区块信息时,会对这个区块信息进行验证,当有一定数量的节点都验证通过后,各个节点会把该区块更新到各自现有的区块链上,最终使得整个区块链网络中的各个节点信息保持一致,这也是区块链去中心化、可信任特性的体现。

    区块链网络简易模型,如下图所示:
    区块链网络.jpg

    2、区块链分类

    (1)公有链

    公有区块链(Public Block Chains)是指:世界上任何个体或者团体都可以发送交易,且交易能够获得该区块链的有效确认,任何人都可以参与使用和维护该区块链,信息公开透明。公有区块链是最早的区块链,例如BTC、以太坊等虚拟数字货币均基于公有区块链。不过目前公有链实际应用价值不大,并没有产生特别合适的应用场景。

    (2)联盟链

    行业区块链(Consortium Block Chains):由某个群体内部指定多个预选的节点为记账人,每个块的生成由所有的预选节点共同决定(预选节点参与共识过程),其他接入节点可以参与交易,但有权限限制,信息受保护,如银联组织。目前联盟链是各个区块链技术团队主要研究的对象,由于联盟链拥有区块链技术的大部分特征,并且在权限管理、数据安全、监管方面更有优势,是企业优先考虑的区块链技术方案。

    市面上也有一些比较主流的联盟链技术框架,让开发维护联盟链更加便捷。国内一些大的软件厂商也都有自己的企业区块链技术解决方案,例如蚂蚁金服区块链平台,腾讯的TrustSQL平台,东软的SaCa EchoTrust区块链应用平台以及京东区块链防伪追溯平台等等。

    (3)私有链

    私有区块链(Private Block Chains):仅仅使用区块链的总账技术进行记账,可以是一个公司,也可以是个人,独享该区块链的写入权限,利用区块链的不易篡改特性,把区块链作为账本数据库来使用。

    3、关键技术与特性

    (1)共识机制

    共识机制被称作为区块链系统的灵魂,是区块链系统信任体系的基础。区块链系统作为一个多节点的分布式账本系统,当有新的信息需要记录时,哪个节点来负责记账,记账奖励发放给哪个节点,哪些节点负责验证记账结果,如何让各个节点达成最终一致,将记账结果被网络中所有节点以同样的顺序复制并记录下来,就是共识机制要做的事情。

    而按照百度百科上的说法:

    所谓“共识机制”是通过特殊节点的投票,在很短的时间内完成对交易的验证和确认,对一笔交易,如果利益不相干的若干个节点能够达成共识,我们就可以认为全网对此也能够达成共识。再通俗一点来讲,如果中国一名微博大V、美国一名虚拟币玩家、一名非洲留学生和一名欧洲旅行者互不相识,但他们都一致认为你是个好人,那么基本上就可以断定你这人还不坏。

    目前,较为主流的共识算法有PoW、PoS、DPoS、PBFT等,在实际使用时,每种算法都有各自的优点和缺点。在应用于不同场景时,区块链项目将会采用不同的共识机制和算法。

    (2)去中心化

    去中心化,是互联网发展过程中形成的社会关系形态和内容产生形态,是相对于“中心化”而言的新型网络内容生产过程。在一个分布有众多节点的区块链系统中,每个节点都具有高度自治的特征。任何一个节点都可能成为阶段性的中心,但不具备强制性的中心控制功能。节点与节点之间的影响,会通过网络而形成关联关系。这种开放式、扁平化、平等性的系统现象或结构,我们称之为去中心化。

    去中心化的系统具有容错力高、抗攻击力强的特征。中心化的系统一旦中心出现问题,整个系统都会崩溃,但是区块链系统中的任何一个节点出现问题,并不会对整个区块链网络产生太大的影响。

    另外,去中介化并不代表着不接受监管,“去中心化”去的是中央控制方和中介方,而不是监管方。监管节点可以方便地接入任何一个区块链网络。并且由于区块链的公开透明特性,监管机构反而可以更加方便地监控整个系统的交易数据。

    (3)智能合约

    从技术层面讲,智能合约是一段部署在在区块链上的程序代码,当满足程序设定的条件时,它便会在区块链上运行,并得到相应的结果。这种情况有点类似于微信的小程序,区块链提供虚拟机和脚本语言,用户根据脚本语言的语法开发带有一定业务逻辑的程序,部署在区块链上,当满足执行的条件时,智能合约便会被区块链虚拟机解释并运行。

    典型的应用便是以太坊平台的智能合约,在这个平台里可以支持用户通过简单的几行代码就能实现他们想要的合约,实现无需人为监督的、不可篡改、自动化运行的合约,买卖房子不需要再找中介、借钱不需要再找公证人……人们可以随时随地根据自身需求发起合约,它的执行不依赖某个人和组织,所有的信任完全基于以太坊区块链平台本身。

    (4)不可篡改性

    大部分人习惯称它为不可篡改性,但是从技术层面来说,我个人觉得叫做不可逆转性更贴切,既然是一个计算机系统,增删改查是基本的功能属性,只不过区块链系统删除和修改操作比较特殊一点。

    区块链是由每个区块的哈希值串连起来的链式结构,而区块的哈希值=SHA256(“当前区块内容+上一个区块的哈希值”),任何一个区块的内容发生修改,都会引起哈希值的变化,而哈希值的变化也会引起子区块哈希值发生变化,进而引起整个区块链的改变。

    因此任何人想要修改区块的数据几乎是不可能的,除非他把整个区块链中从创世区块到最新的区块的所有哈希值全部重新修改一遍,并且修改完之后,还得广播告诉网络中的其他所有节点,让其他所有节点接受修改。

    不过按照目前计算机的算力,想要在短时间内从区块链头部到尾部全部修改一遍,是一件非常困难的事,并且即使修改完了,其他节点也不会接受修改,因为凭一己之力,没有能够让所有节点达成共识的条件。

    4、流行的区块链框架与应用

    (1)公有链应用:BTC网络

    区块链1.0产品,对于比特币,中本聪是这样定义的:是一种完全通过点对点技术实现的电子现金系统,它使得在线支付能够直接由一方发起并支付给另外一方,中间不需要通过任何的金融机构。

    与所有的货币不同,比特币不依靠特定货币机构发行,它依据特定算法,通过大量的计算产生,比特币经济使用整个P2P网络中众多节点构成的分布式数据库来确认并记录所有的交易行为,并使用密码学的设计来确保货币流通各个环节安全性。之后人们根据比特币网络技术整理出了区块链技术体系,去解决信任的问题,而比特币网络原理也成为了区块链技术初学者的经典教材。

    (2)公有链应用:以太坊网络

    区块链2.0产品的代表,以太坊是一个为去中心化应用(Dapp)而生的开源区块链平台,拥有着大部分区块链技术的特征,但与其它区块链不同的是,以太坊是可编程的,开发者可以用它来构建不同的应用程序,通过其专用加密货币以太币(简称“ETH”)提供去中心化的以太虚拟机(Ethereum Virtual Machine)来处理点对点合约(就是一些脚本程序代码)。如果把比特币网络看作是一套分布式的数据库,而以太坊则更进一步,它可以看作是一台分布式的计算机:区块链是计算机的ROM,合约是程序,而以太坊的矿工们则负责计算,担任CPU的角色。

    image.png
    以太坊的概念首次在2013至2014年间由程序员Vitalik Buterin受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”。虽然以太坊作为平台可以在其上开发新的应用,但是由于以太坊的运行和BTC网络一样,采用的是Token机制,且平台性能不足,经常出现网络拥堵的情况,平台用来学习开发与测试区块链技术还可以,用于实际生产的话不太现实。

    (3)联盟链开发框架:Hyperledger Fabric

    Hyperledger Fabric 也叫超级账本,它是 IBM 贡献给 Linux 基金会的商用分布式账本,是面向企业应用的全球最大的分布式开源项目。像其他区块链技术一样,它也有一个账本,可以使用智能合约。Fabric的智能合约可以有多种架构,它可以用主流语言编程,例如Go、Java和Javascript,此外也可以使用Solidity。

    至今,Fabric已获得了阿里巴巴、AWS、Azure、百度、谷歌、华为、IBM、甲骨文、腾讯等互联网巨头的支持。许多企业的区块链平台都把Fabric作为底层框架来使用,例如甲骨文。不过由于IBM对区块链的定义强调了区块链的分布式和不可变两个元素,对共识机制进行了削弱,采用了Kafka和zookeeper的“排序服务”实现共识,因此部分业内人士也称超级账本是“伪区块链”,但是即便如此,也抵挡不了企业对超级账本的喜爱,目前Fabric 2.0版本已经正式发布。

    (4)小结

    目前公有链在实际应用中并没有太多的业务场景落地,大部分都是以挖矿为主题或者线上宠物饲养的游戏为主,并且由于数字货币的匿名性,有些不法分子利用这一特点,将数字货币用于洗钱、暗网买卖等违法行为,是各个国家的打击对象,我国政策法规也严厉禁止,因此对于技术人员来说,公有链可以作为研究学习的对象,其他方面暂时没有太多实际意义。

    目前大部分区块链企业的研究方向主要是针对企业的联盟链和私有链,并且国家层面也在大力支持区块链技术的发展,特别是区块链底层核心技术的研发,倡导把区块链作为核心技术自主创新的重要突破口,明确主攻方向,加大投入力度,着力攻克一批关键核心技术,加快推动区块链技术和产业创新发展。不过现在市面上主流的区块链平台大部分还是以国外公司主导的为主,国内区块链底层核心技术的发展,还需要技术人员的加倍努力。

    二、区块链技术Java实现

    1、区块链技术架构

    区块链技术架构图.jpg
    目前主流的区块链技术架构主要分为五层,数据层是最底层的技术,主要实现了数据存储、账户信息、交易信息等模块,数据存储主要基于Merkle树,通过区块的方式和链式结构实现,而账户和交易基于数字签名、哈希函数和非对称加密技术等多种密码学算法和技术,来保证区块链中数据的安全性。

    网络层主要实现网络节点的连接和通讯,又称点对点技术,各个区块链节点通过网络进行通信。共识层是通过共识算法,让网络中的各个节点对全网所有的区块数据真实性正确性达成一致,防止出现拜占庭攻击、51攻击等区块链共识算法攻击。

    激励层主要是实现区块链代币的发行和分配机制,是公有链的范畴,我们不做分析。应用层一般把区块链系统作为一个平台,在平台之上实现一些去中心化的应用程序或者智能合约,平台提供运行这些应用的虚拟机。

    接下来我们基于Java语言来开发一套小型的区块链系统,来实现数据层、网络层、共识层的一些功能,用简单的代码来直观抽象的概念,以便加深对以上区块链技术基础理论的理解。

    2、基于java的区块链开发实战

    (1)开发环境

    开发工具VSCode
    开发语言Java
    JDK版本JDK1.8或者OpenJDK11
    开发框架SpringBoot2.2.1
    工程管理Maven3.6
    测试工具Postman

    (2)区块链基本模型构建

    区块是区块链系统的最小单元,第一步我们先实现最简单的区块结构,新建Block.java类,主要包含以下几个字段:
    Block.java

    /**
     * 区块结构
     * 
     * @author Jared Jia
     *
     */
    public class Block implements Serializable {
    
    	private static final long serialVersionUID = 1L;
    	/**
    	 * 区块索引号(区块高度)
    	 */
    	private int index;
    	/**
    	 * 当前区块的hash值,区块唯一标识
    	 */
    	private String hash;
    	/**
    	 * 前一个区块的hash值
    	 */
    	private String previousHash;
    	/**
    	 * 生成区块的时间戳
    	 */
    	private long timestamp;
    	/**
    	 * 工作量证明,计算正确hash值的次数
    	 */
    	private int nonce;
    	/**
    	 * 当前区块存储的业务数据集合(例如转账交易信息、票据信息、合同信息等)
    	 */
    	private List<Transaction> transactions;
      
      /*** 省略get set方法****/
      }
    

    区块链是由区块按照区块哈希前后顺序串联起来的数据结构,哈希值通过散列算法对区块进行二次哈希计算而得到的数字摘要信息(不了解散列函数的,可以先百度了解一下SHA算法),用于保证区块的信息安全以及整条区块链的有效性。因此第二步我们新增计算区块Hash值的方法,采用SHA256算法,通过java实现:
    CryptoUtil.java

    /**
     * 密码学工具类
     * 
     * @author Jared Jia
     *
     */
    public class CryptoUtil {
    
    	/**
    	 * SHA256散列函数
    	 * @param str
    	 * @return
    	 */
    	public static String SHA256(String str) {
    		MessageDigest messageDigest;
    		String encodeStr = "";
    		try {
    			messageDigest = MessageDigest.getInstance("SHA-256");
    			messageDigest.update(str.getBytes("UTF-8"));
    			encodeStr = byte2Hex(messageDigest.digest());
    		} catch (Exception e) {
    			System.out.println("getSHA256 is error" + e.getMessage());
    		}
    		return encodeStr;
    	}
    	
    	private static String byte2Hex(byte[] bytes) {
    		StringBuilder builder = new StringBuilder();
    		String temp;
    		for (int i = 0; i < bytes.length; i++) {
    			temp = Integer.toHexString(bytes[i] & 0xFF);
    			if (temp.length() == 1) {
    				builder.append("0");
    			}
    			builder.append(temp);
    		}
    		return builder.toString();
    	}
    }
    

    第三步,创建一个链式结构对象,按照先后顺序来保存区块对象,从来形成一个有序的区块链表,考虑到线程安全问题,采用CopyOnWriteArrayList来实现,为了方便测试,暂且把区块链结构保存在本地缓存中,实际的区块链网络最终会实现持久层的功能,把区块链数据保存至数据库中,例如BTC核心网络采用的是K-V数据库LevelDB:
    BlockCache.java

    public class BlockCache {
    
    	/**
    	 * 当前节点的区块链结构
    	 */
    	private List<Block> blockChain = new CopyOnWriteArrayList<Block>();
      
      public List<Block> getBlockChain() {
    		return blockChain;
    	}
    
    	public void setBlockChain(List<Block> blockChain) {
    		this.blockChain = blockChain;
    	}
     }
    

    第四步,有了区块链结构后,需要新增向区块链中添加区块的方法,同时每次添加区块的时候,我们需要验证新区块的有效性,例如Hash值是否正确,新区块中上一区块的Hash属性的值,与上一区块的Hash值是否相等。

    另外,区块链中必须有个创世区块,我们直接通过硬编码实现:
    BlockService.java

    /**
     * 区块链核心服务
     * 
     * @author Jared Jia
     *
     */
    @Service
    public class BlockService {
    
    	@Autowired
    	BlockCache blockCache;
      
    	/**
    	 * 创建创世区块
    	 * @return
    	 */
    	public String createGenesisBlock() {
    		Block genesisBlock = new Block();
    		//设置创世区块高度为1
    		genesisBlock.setIndex(1);
    		genesisBlock.setTimestamp(System.currentTimeMillis());
    		genesisBlock.setNonce(1);
    		//封装业务数据
    		List<Transaction> tsaList = new ArrayList<Transaction>();
    		Transaction tsa = new Transaction();
    		tsa.setId("1");
    		tsa.setBusinessInfo("这是创世区块");
    		tsaList.add(tsa);
    		Transaction tsa2 = new Transaction();
    		tsa2.setId("2");
    		tsa2.setBusinessInfo("区块链高度为:1");
    		tsaList.add(tsa2);		
    		genesisBlock.setTransactions(tsaList);
    		//设置创世区块的hash值
    		genesisBlock.setHash(calculateHash("",tsaList,1));
    		//添加到已打包保存的业务数据集合中
    		blockCache.getPackedTransactions().addAll(tsaList);
    		//添加到区块链中
    		blockCache.getBlockChain().add(genesisBlock);
    		return JSON.toJSONString(genesisBlock);
    	}
    	
    	/**
    	 * 创建新区块
    	 * @param nonce
    	 * @param previousHash
    	 * @param hash
    	 * @param blockTxs
    	 * @return
    	 */
    	public Block createNewBlock(int nonce, String previousHash, String hash, List<Transaction> blockTxs) {
    		Block block = new Block();
    		block.setIndex(blockCache.getBlockChain().size() + 1);
    		//时间戳
    		block.setTimestamp(System.currentTimeMillis());
    		block.setTransactions(blockTxs);
    		//工作量证明,计算正确hash值的次数
    		block.setNonce(nonce);
    		//上一区块的哈希
    		block.setPreviousHash(previousHash);
    		//当前区块的哈希
    		block.setHash(hash);
    		if (addBlock(block)) {
    			return block;
    		}
    		return null;
    	}
    
    	/**
    	 * 添加新区块到当前节点的区块链中
    	 * 
    	 * @param newBlock
    	 */
    	public boolean addBlock(Block newBlock) {
    		//先对新区块的合法性进行校验
    		if (isValidNewBlock(newBlock, blockCache.getLatestBlock())) {
    			blockCache.getBlockChain().add(newBlock);
    			// 新区块的业务数据需要加入到已打包的业务数据集合里去
    			blockCache.getPackedTransactions().addAll(newBlock.getTransactions());
    			return true;
    		}
    		return false;
    	}
    	
    	/**
    	 * 验证新区块是否有效
    	 * 
    	 * @param newBlock
    	 * @param previousBlock
    	 * @return
    	 */
    	public boolean isValidNewBlock(Block newBlock, Block previousBlock) {
    		if (!previousBlock.getHash().equals(newBlock.getPreviousHash())) {
    			System.out.println("新区块的前一个区块hash验证不通过");
    			return false;
    		} else {
    			// 验证新区块hash值的正确性
    			String hash = calculateHash(newBlock.getPreviousHash(), newBlock.getTransactions(), newBlock.getNonce());
    			if (!hash.equals(newBlock.getHash())) {
    				System.out.println("新区块的hash无效: " + hash + " " + newBlock.getHash());
    				return false;
    			}
    			if (!isValidHash(newBlock.getHash())) {
    				return false;
    			}
    		}
    
    		return true;
    	}
     }
    

    以上关键代码实现之后,我们就构建了一个非常简单的区块链模型,包含一个基本的区块模型和一个区块链模型,并且能够生成新的区块并添加到区块链中,接下来我们进行测试。

    第五步,我们编写一个Controller类进行调用:
    BlockController.java

    @Controller
    public class BlockController {
    
    	@Resource
    	BlockService blockService;
    	
    	@Autowired
    	BlockCache blockCache;
    	
    	/**
    	 * 查看当前节点区块链数据
    	 * @return
    	 */
    	@GetMapping("/scan")
    	@ResponseBody
    	public String scanBlock() {
    		return JSON.toJSONString(blockCache.getBlockChain());
    	}
      
      /**
    	 * 创建创世区块
    	 * @return
    	 */
    	@GetMapping("/create")
    	@ResponseBody
    	public String createFirstBlock() {
    		blockService.createGenesisBlock();
    		return JSON.toJSONString(blockCache.getBlockChain());
    	}
     }
    

    第六步,系统测试
    首先系统启动后,先查看区块链中的数据,可以看到当前系统中的区块链为空:
    image.png
    然后我们调用创建创世区块的方法,查看返回结果:
    image.png

    我们把生成的创世区块添加到本地区块链中后,转换成JSON字符串返回,可以看到当前区块链中存储的有一个区块对象,至此我们已经实现了一个简单的区块链。实际的区块链系统模型要复杂的多,需要根据不同的业务场景扩展相应的字段,但是基本特征都是一样的。

    (3)共识机制实现

    在上章节中,我们实现了一个简单的区块链结构,并且能够生成并添加新的区块,但是问题来了,实际的区块链系统是一个多节点、分布式、去中心化的网络,每个节点通过网络交互,实时同步保存着同样的整条区块链数据,那么我们生成的区块,如何才能被其他节点认可,并同步添加到其他所有节点上呢,这个时候我们就需要一套规则,让所有网络节点的参与者达成能够达成共识,接纳并保存新的区块,也就是所谓的“共识机制”。

    理论基础部分已经提到了,共识机制有很多种,各有各的优势与缺点,接下来我们就用java代码来模拟实现我们最为熟知的一种机制:工作量证明(Proof of Work),顾名思义就是对工作量的证明,在基于POW机制构建的区块链网络中,节点通过计算随机哈希散列的数值争夺记账权,求得正确的数值并生成区块的能力是节点算力的具体表现,计算的过程一般被形象地称为“挖矿”。

    简单来说就是,区块链系统设定一套计算规则或者说是一套计算题,在新区块生成前,各个节点都投入到这道题的求解计算中,哪个节点先计算出结果,并得到其它节点的验证和认可,这个节点就会获得新区块的记账权,并获得系统相应的奖励,共识结束。

    典型的PoW共识机制应用就是BTC网络,在BTC网络中,共识计算的目标是找到满足某个特定要求的区块Hash(哈希值)。这个区块哈希值就是工作结果的一个证明,计算工作的目的就是为了寻找到这个证明值,上一章节中,测试时我们已经见过这个Hash值:

    [
        {
            "hash": "25931395e736653212f0258824df4222ae739ec2d5897310258b0857d4d3870c",
            "index": 1,
            "nonce": 1,
            "timestamp": 1580970554734,
            "transactions": [
                {
                    "businessInfo": "这是创世区块",
                    "id": "1"
                }
            ]
        }
    ]
    

    BTC网络PoW使用的Hashcash算法,大致逻辑如下:

    1. 获取某种公开可知的数据data(BTC网络中,指的是区块头);
    2. 添加一个计数器nonce,初始值设置为0;
    3. 计算data与nonce拼接字符串的哈希值;
    4. 检查上一步的哈希值是否满足某个条件,满足则停止计算,不满足则nonce加1,然后重复第3步和第4步,直到满足这个特定的条件为止。

    接下来我们用Java代码实现这个算法,设定满足的特定条件为,Hash值前4位都是0,则计算成功(实际区块链网络中的特定条件要求更高,对计算的运算能力要求也高,并且系统随着计算难度动态调整满足的特定条件,来保证区块生成的速度)。

    第一步,我们新建一个共识机制服务类,添加一个“挖矿”方法,计算成功后,获取记账权,调用添加区块的方法,把区块添加到区块链中:
    PowService.java

    /**
     * 共识机制
     * 采用POW即工作量证明实现共识
     * @author Administrator
     *
     */
    @Service
    public class PowService {
    
    	@Autowired
    	BlockCache blockCache;
    	
    	@Autowired
    	BlockService blockService;
    	
    	/**
    	 * 通过“挖矿”进行工作量证明,实现节点间的共识
    	 * 
    	 * @return
    	 */
    	public Block mine(){
    		
    		// 封装业务数据集合,记录区块产生的节点信息,临时硬编码实现
    		List<Transaction> tsaList = new ArrayList<Transaction>();
    		Transaction tsa1 = new Transaction();
    		tsa1.setId("1");
    		tsa1.setBusinessInfo("这是IP为:"+CommonUtil.getLocalIp()+",端口号为:"+blockCache.getP2pport()+"的节点挖矿生成的区块");
    		tsaList.add(tsa1);
    		Transaction tsa2 = new Transaction();
    		tsa2.setId("2");
    		tsa2.setBusinessInfo("区块链高度为:"+(blockCache.getLatestBlock().getIndex()+1));
    		tsaList.add(tsa2);
    		
    		// 定义每次哈希函数的结果 
    		String newBlockHash = "";
    		int nonce = 0;
    		long start = System.currentTimeMillis();
    		System.out.println("开始挖矿");
    		while (true) {
    			// 计算新区块hash值
    			newBlockHash = blockService.calculateHash(blockCache.getLatestBlock().getHash(), tsaList, nonce);
    			// 校验hash值
    			if (blockService.isValidHash(newBlockHash)) {
    				System.out.println("挖矿完成,正确的hash值:" + newBlockHash);
    				System.out.println("挖矿耗费时间:" + (System.currentTimeMillis() - start) + "ms");
    				break;
    			}
    			System.out.println("第"+(nonce+1)+"次尝试计算的hash值:" + newBlockHash);
    			nonce++;
    		}
    		// 创建新的区块
    		Block block = blockService.createNewBlock(nonce, blockCache.getLatestBlock().getHash(), newBlockHash, tsaList);
    		return block;
    	}
    	
      /**
    	 * 验证hash值是否满足系统条件
    	 * 暂定前4位是0则满足条件
    	 * @param hash
    	 * @return
    	 */
    	public boolean isValidHash(String hash) {
    		//System.out.println("难度系数:"+blockCache.getDifficulty());
    		return hash.startsWith("0000");
    	}
    }
    

    第二步,编写测试共识机制服务的Controller类方法:
    BlockController.java

    /**
    	 * 工作量证明PoW
    	 * 挖矿生成新的区块 
    	 */
    	@GetMapping("/mine")
    	@ResponseBody
    	public String createNewBlock() {
    		powService.mine();
    		return JSON.toJSONString(blockCache.getBlockChain());
    	}
    

    第三步,启动系统,进行测试。
    首先执行http://localhost:8080/create方法,生成创世区块。
    其次调用http://localhost:8080/mine方法进行工作量计算证明,生成新的区块,并添加到本地区块链中:
    image.png

    我们来看一下,系统后台计算的过程,此次计算共花费1048ms计算出满足条件的Hash值,共计算4850次:
    image.png

    至此,我们实现了一个简单的工作量证明机制,并在当前区块链系统节点上运行,完成了正确结果的计算,生成了一个新的区块。

    接下来我们将会开发一个P2P网络,实现多个节点的同时运行,当一个节点挖矿完成后,通过P2P网络广播给其他节点,其他节点验证通过后,会把新产生的区块添加到自己的区块链上,进而保证整个区块链网络所有节点的数据一致性。

    (4)P2P网络开发

    前面我们已经实现了一个基本的区块链系统,并且实现了PoW工作量证明共识机制,通过挖矿计算出正确的结果同时生成一个新的区块添加到区块链中,但是这些都是基于单节点的运行,实际的区块链是有多个节点同时运行的分布式网络系统,所有节点同时计算抢夺记账权,共同维护一条完整的区块链。

    接下来我们基于Java的WebSocket实现一个Peer-to-Peer网络,实现多个节点间的相互通信,通过本章节,我们将要实现以下功能:

      - 创建一个基于java的p2p网络
      - 运行多个节点,且多个节点通过p2p网络自动同步区块信息
      - 一个节点挖矿生成新的区块后,自动广播给其他所有节点
      - 每个节点在接收到其他节点发送的区块内容后,进行验证,验证通过添加到本地区块链上
      - 在自我节点查看整个区块链内容
    

    开发测试本章节的功能,我们最好准备两台电脑或者虚拟机,再或者Docker集群环境也可以,便于多节点的运行测试。如果只有一台电脑也可以,各个节点运行的端口号设置为不相同即可。

    第一步,开发思路整理
    目前我们已经实现了单节点的区块生成,那么我们接下来只需要实现各个节点的消息同步即可。

    • 首先,通过java代码实现p2p网络的server端和client端,每个节点既是服务端也是客户端。

    • 然后,一个节点启动时,会寻找区块链网络上的有效节点,并建立socket连接(BTC网络可以通过使用“DNS”种子方式获取BTC有效节点,DNS种子提供比特币节点的IP地址列表),我们直接把节点列表配置到application.yml文件中。

    • 接着,从连接上的节点获取最新的区块信息,如果当前节点首次运行,则获取整个区块链信息,并替换到本地。

    • 之后,各个节点同时挖矿计算,哪个节点先计算完成,就把生成的新区块全网广播给其他所有节点(实际的区块链网络一直在计算,我们为了便于测试,手动触发一个节点挖矿产生区块,然后全网广播给其他所有节点)。

    • 最后,当一个节点收到广播内容后,对接收到的新区块进行验证,验证通过后添加到本地区块链上,验证的首要条件是新区块的高度必须比本地的区块链高度要高。

    第二步,先实现P2P网络server端
    新建一个P2PServer类,并添加一个初始化server端的方法:
    P2PServer.java

    /**
     * p2p服务端
     * 
     * @author Jared Jia
     *
     */
    @Component
    public class P2PServer {
    
    	@Autowired
    	P2PService p2pService;
    
    	public void initP2PServer(int port) {
    		WebSocketServer socketServer = new WebSocketServer(new InetSocketAddress(port)) {
    
    			/**
    			 * 连接建立后触发
    			 */
    			@Override
    			public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
    				p2pService.getSockets().add(webSocket);
    			}
    
    			/**
    			 * 连接关闭后触发
    			 */
    			@Override
    			public void onClose(WebSocket webSocket, int i, String s, boolean b) {
    				p2pService.getSockets().remove(webSocket);
    				System.out.println("connection closed to address:" + webSocket.getRemoteSocketAddress());
    			}
    
    			/**
    			 * 接收到客户端消息时触发
    			 */
    			@Override
    			public void onMessage(WebSocket webSocket, String msg) {
    				//作为服务端,业务逻辑处理
    				p2pService.handleMessage(webSocket, msg, p2pService.getSockets());
    			}
    
    			/**
    			 * 发生错误时触发
    			 */
    			@Override
    			public void onError(WebSocket webSocket, Exception e) {
    				p2pService.getSockets().remove(webSocket);
    				System.out.println("connection failed to address:" + webSocket.getRemoteSocketAddress());
    			}
    
    			@Override
    			public void onStart() {
    
    			}
    
    		};
    		socketServer.start();
    		System.out.println("listening websocket p2p port on: " + port);
    	}
    }
    
    

    第三步,实现P2P网络client端
    P2PClient.java

    /**
     * p2p客户端
     * 
     * @author Jared Jia
     *
     */
    @Component
    public class P2PClient {
    	
    	@Autowired
    	P2PService p2pService;
    
    	public void connectToPeer(String addr) {
    		try {
    			final WebSocketClient socketClient = new WebSocketClient(new URI(addr)) {
    				@Override
    				public void onOpen(ServerHandshake serverHandshake) {
    					//客户端发送请求,查询最新区块
    					p2pService.write(this, p2pService.queryLatestBlockMsg());
    					p2pService.getSockets().add(this);
    				}
    
    				/**
    				 * 接收到消息时触发
    				 * @param msg
    				 */
    				@Override
    				public void onMessage(String msg) {
    					p2pService.handleMessage(this, msg, p2pService.getSockets());
    				}
    
    				@Override
    				public void onClose(int i, String msg, boolean b) {
    					p2pService.getSockets().remove(this);
    					System.out.println("connection closed");
    				}
    
    				@Override
    				public void onError(Exception e) {
    					p2pService.getSockets().remove(this);
    					System.out.println("connection failed");
    				}
    			};
    			socketClient.connect();
    		} catch (URISyntaxException e) {
    			System.out.println("p2p connect is error:" + e.getMessage());
    		}
    	}
    }
    

    第四步,定义P2P网络同步的消息模型
    同步的消息模型,我们定义为四类,分别是:
    BlockConstant.java

      // 查询最新的区块
    	public final static int QUERY_LATEST_BLOCK = 1;
    
    	// 返回最新的区块
    	public final static int RESPONSE_LATEST_BLOCK = 2;
    
    	// 查询整个区块链
    	public final static int QUERY_BLOCKCHAIN = 3;
    
    	// 返回整个区块链
    	public final static int RESPONSE_BLOCKCHAIN = 4;
    

    定义一个各个节点间传递的消息模型:
    Message.java

    /**
     * p2p通讯消息
     *
     * @author Jared Jia
     * 
     */
    public class Message implements Serializable {
    	
    		private static final long serialVersionUID = 1L;
        /**
         * 消息类型
         */
        private int type;
        /**
         * 消息内容
         */
        private String data;
        
        /****set get方法省略****/
        
      }
    

    **
    第五步,实现向其他节点广播的方法

    新建一个p2p网络服务类,向外发送消息,或者处理当前节点收到其他节点发送的请求。
    P2PService.java

    /**
    	 * 全网广播消息
    	 * @param message
    	 */
    	public void broatcast(String message) {
    		List<WebSocket> socketsList = this.getSockets();
    		if (CollectionUtils.isEmpty(socketsList)) {
    			return;
    		}
    		System.out.println("======全网广播消息开始:");
    		for (WebSocket socket : socketsList) {
    			this.write(socket, message);
    		}
    		System.out.println("======全网广播消息结束");
    	}
    

    第六步,开发消息处理路由

    第五步中已经实现了向外发送消息,本步骤实现接收消息。
    首先设计一个服务端和客户端共用的消息路由,来分发消息给对应的处理单元。
    P2PService.java

    /**
    	 * 客户端和服务端共用的消息处理方法
    	 * @param webSocket
    	 * @param msg
    	 * @param sockets
    	 */
    	public void handleMessage(WebSocket webSocket, String msg, List<WebSocket> sockets) {
    		try {
    			Message message = JSON.parseObject(msg, Message.class);
    			System.out.println("接收到IP地址为:" +webSocket.getRemoteSocketAddress().getAddress().toString()
    					+",端口号为:"+ webSocket.getRemoteSocketAddress().getPort() + "的p2p消息:"
    			        + JSON.toJSONString(message));
    			switch (message.getType()) {
    			//客户端请求查询最新的区块:1
    			case BlockConstant.QUERY_LATEST_BLOCK:
    				write(webSocket, responseLatestBlockMsg());//服务端调用方法返回最新区块:2
    				break;
    			//接收到服务端返回的最新区块:2
    			case BlockConstant.RESPONSE_LATEST_BLOCK:
    				handleBlockResponse(message.getData(), sockets);
    				break;
    			//客户端请求查询整个区块链:3
    			case BlockConstant.QUERY_BLOCKCHAIN:
    				write(webSocket, responseBlockChainMsg());//服务端调用方法返回最新区块:4
    				break;
    			//直接接收到其他节点发送的整条区块链信息:4
    			case BlockConstant.RESPONSE_BLOCKCHAIN:
    				handleBlockChainResponse(message.getData(), sockets);
    				break;
    			}
    		} catch (Exception e) {
    			System.out.println("处理IP地址为:" +webSocket.getRemoteSocketAddress().getAddress().toString()
    				+",端口号为:"+ webSocket.getRemoteSocketAddress().getPort() + "的p2p消息错误:" 
    				+ e.getMessage());
    		}
    	}
    

    第七步,开发消息处理单元

    有了消息路由之后,接着编写不同的处理单元,处理其他节点发送来的区块或者区块链信息,总体原则是:先校验其他节点发送来的区块或者区块链的有效性,然后判断它们的高度比当前节点的区块链高度要高,如果高则替换本地的区块链,或者把新区块添加到本地区块链上。
    P2PService.java

    /**
    	 * 处理其它节点发送过来的区块信息
    	 * @param blockData
    	 * @param sockets
    	 */
    	public synchronized void handleBlockResponse(String blockData, List<WebSocket> sockets) {
    		//反序列化得到其它节点的最新区块信息
    		Block latestBlockReceived = JSON.parseObject(blockData, Block.class);
    		//当前节点的最新区块
    		Block latestBlock = blockCache.getLatestBlock();
    		
    		if (latestBlockReceived != null) {
    			if(latestBlock != null) {
    				//如果接收到的区块高度比本地区块高度大的多
    				if(latestBlockReceived.getIndex() > latestBlock.getIndex() + 1) {
    					broatcast(queryBlockChainMsg());
    					System.out.println("重新查询所有节点上的整条区块链");
    				}else if (latestBlockReceived.getIndex() > latestBlock.getIndex() && 
    						latestBlock.getHash().equals(latestBlockReceived.getPreviousHash())) {
    					if (blockService.addBlock(latestBlockReceived)) {
    						broatcast(responseLatestBlockMsg());
    					}
    					System.out.println("将新接收到的区块加入到本地的区块链");
    				}
    			}else if(latestBlock == null) {
    				broatcast(queryBlockChainMsg());
    				System.out.println("重新查询所有节点上的整条区块链");
    			}
    		}
    	}
    	
    	/**
    	 * 处理其它节点发送过来的区块链信息
    	 * @param blockData
    	 * @param sockets
    	 */
    	public synchronized void handleBlockChainResponse(String blockData, List<WebSocket> sockets) {
    		//反序列化得到其它节点的整条区块链信息
    		List<Block> receiveBlockchain = JSON.parseArray(blockData, Block.class);
    		if(!CollectionUtils.isEmpty(receiveBlockchain) && blockService.isValidChain(receiveBlockchain)) {
    			//根据区块索引先对区块进行排序
    			Collections.sort(receiveBlockchain, new Comparator<Block>() {
    				public int compare(Block block1, Block block2) {
    					return block1.getIndex() - block2.getIndex();
    				}
    			});
    			
    			//其它节点的最新区块
    			Block latestBlockReceived = receiveBlockchain.get(receiveBlockchain.size() - 1);
    			//当前节点的最新区块
    			Block latestBlock = blockCache.getLatestBlock();
    			
    			if(latestBlock == null) {
    				//替换本地的区块链
    				blockService.replaceChain(receiveBlockchain);
    			}else {
    				//其它节点区块链如果比当前节点的长,则处理当前节点的区块链
    				if (latestBlockReceived.getIndex() > latestBlock.getIndex()) {
    					if (latestBlock.getHash().equals(latestBlockReceived.getPreviousHash())) {
    						if (blockService.addBlock(latestBlockReceived)) {
    							broatcast(responseLatestBlockMsg());
    						}
    						System.out.println("将新接收到的区块加入到本地的区块链");
    					} else {
    						// 用长链替换本地的短链
    						blockService.replaceChain(receiveBlockchain);
    					}
    				}
    			}
    		}
    	}
    

    3、完整系统运行与测试

    第一步,打包生成测试用的可执行jar包
    准备两台机器(虚拟机或者Docker集群都行),同时运行两个节点,节点信息如下:

    Node1Node2
    IP地址192.168.0.104192.168.0.112
    http端口号80808090
    websocket服务端口号70017002
    websocket服务地址ws://192.168.0.104:7001ws://192.168.0.112:7002

    通过mvn package -Dmaven.test.skip=true命令对工程进行打包,生成可直接运行的jar包,打包前对工程进行配置,配置信息如下图:
    节点Node1打包:
    image.png

    节点Node2打包:
    image.png

    分别打包之后,生成两个节点的可执行jar包,如下:
    image.png

    把两个jar包分别放在对应IP的windows机器上,打开命令行模式,进入jar所在文件夹,分别执行以下命令运行两个节点:
    java -jar dce-blockchain-node1.jar
    java -jar dce-blockchain-node2.jar

    启动节点2的时候,可以看到后台日志,已经连接上节点1,如下图所示:
    image.png

    第二步,对两个节点进行测试

    首先,两个节点启动后,用postman分别执行http://192.168.0.104:8080/scanhttp://192.168.0.112:8090/scan请求,可以看到两个节点的区块链内容都为空。

    然后,在节点1上分别执行http://192.168.0.104:8080/createhttp://192.168.0.104:8080/mine请求,来生成创世区块,以及通过挖矿产生第二个区块,执行后查看节点1的区块链信息如下:
    执行http://192.168.0.104:8080/scan结果:

    [
        {
            "hash": "5303d2990c139992bdb5a22aa1dac4f2719755304e45bac03ca4a1f1688c909e",
            "index": 1,
            "nonce": 1,
            "timestamp": 1581064647736,
            "transactions": [
                {
                    "businessInfo": "这是创世区块",
                    "id": "1"
                },
                {
                    "businessInfo": "区块链高度为:1",
                    "id": "2"
                }
            ]
        },
        {
            "hash": "0000de5eea0c20c2e7d06220bc023886e88dd8784eaa2fd2d1d6c5e581061d85",
            "index": 2,
            "nonce": 4850,
            "previousHash": "5303d2990c139992bdb5a22aa1dac4f2719755304e45bac03ca4a1f1688c909e",
            "timestamp": 1581064655139,
            "transactions": [
                {
                    "businessInfo": "这是IP为:192.168.0.104,端口号为:7001的节点挖矿生成的区块",
                    "id": "1"
                },
                {
                    "businessInfo": "区块链高度为:2",
                    "id": "2"
                }
            ]
        }
    ]
    

    最后,我们来验证节点2是否已经完成了节点1生成的区块链信息的网络同步,Postman执行http://192.168.0.112:8090/scan请求,查看返回结果:
    image.png 从结果可以看到,区块链网络节点2已经接收到节点1发送的区块链信息,系统日志如下:
    image.png

    反过来,我们在节点2上再执行一次挖矿操作,可以看到节点1上,已经接收到节点2挖矿新产生的区块信息,并添加到节点1的区块链上:
    image.png

    至此,我们已经实现了一个完整的小型区块链网络,并实现各个节点间的通信,多个节点共同维护同一个区块链信息。

    结语:
    区块链系统非常庞大,涉及方方面面的技术,本人所演示的代码主要对区块链基础的一些概念进行了诠释,感兴趣的同学,还可以在此基础上继续开发,来实现例如持久层、消息的加密解密、系统账户模型、预言机、侧链技术以及智能合约等区块链系统功能。


    写给每个区块链技术人员:
    目前市面上流行的企业级区块链框架,例如超级账本Fabric都是国外人员在主导,而我们国内除了几家大厂外,其他很多区块链公司基本都是把人家的东西拿过来进行二次封装,然后对外声称自己公司已经掌握了区块链核心技术,并对企业提供服务,这是一种不好的现象。大家可以想想我们现在用的开发语言、框架有几个真正是国产的,我们再联想一下前段时间中兴、华为被人家核心技术卡脖子事件,就知道我们要做的事情有很多,我们需要去除浮躁,静下心来好好研究底层核心技术,这样才能实现真正的“弯道超车”!

    三、源代码

    1、本文完整源代码地址

    https://gitee.com/luckytuan/dce-blockchain

    2、参考书籍

    《精通比特币》
    《2018年中国区块链产业白皮书》
    《超级账本Hyperledger白皮书》

    展开全文
  • 基于Java开发一套完整的区块链系统(附源码)

    千次阅读 多人点赞 2021-01-16 10:45:00
    来源:https://blog.csdn.net/victory_long前言近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术...

    来源:https://blog.csdn.net/victory_long



    前言

    近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术进行研究,从各大招聘网站的区块链职位来看,薪资待遇都很不错,月薪30K到80K的都有,这对于我们程序员来说也是一种机遇,说明学习区块链技术刻不容缓。

    我个人从2016年就开始在做区块链系统开发的相关工作,最近身边很多朋友都在找我,想让我给他们讲讲区块链技术开发的相关知识,介于此,索性我就手撸了一套简单的java区块链系统,并写了一份详细的开发教程,发布到博客,希望能够对热爱区块链技术的小伙伴学习入门有所帮助。

    这套区块链系统代码非常简洁清晰,对于新手来说非常好理解,旨在告诉大家其实区块链技术并没有那么高深复杂。系统中除了springboot框架外,其他基本都是纯原生开发,就连P2P网络也是用的java socket来实现的。

    文末有本文完整源码链接。

    一、区块链技术理论基础

    1、基本概念

    (1)区块链

    从技术层面来看,区块链是由包含交易信息的区块按照时间顺序从后向前有序链接起来的数据结构。

    从应用层面来说,区块链是一个分布式的共享账本和数据库,具有去中心化、不可篡改、全程留痕、集体维护、公开透明等特点。基于这些特点,区块链技术可以开发出自带信任体系特征的系统,实现多个主体之间的协作信任与一致行动。

    区块是区块链中的最小组成单位,主要有包含元数据的区块头和存放一条或者多条交易信息的区块体两部分组成,每个区块都记录着当前区块的哈希和上一个区块的哈希,通过两个哈希值的关联,让所有的区块以链式结构串起来,就形成了一个完整的区块链。

    区块链中的第一个区块被称作为创世区块,无需关联上一个区块。以BTC网络为例,每个区块主要包含如下信息字段:

    • 区块大小:用字节表示的区块数据大小

    • 区块头:组成区块头的包括以下几个字段:
      1. 区块头hash值
      2. 父区块头hash值
      3. 时间戳:区块产生的近似时间
      4. Merkle根:该区块中交易的merkle树根的哈希值
      5. 难度目标:该区块工作量证明算法的难度目标
      6. Nonce:用于工作量证明算法的计数器

    • 交易计数器:交易的数量

    • 交易:记录在区块里的交易信息

    区块链结构的简易模型,如下图所示:

    区块中的交易集合记录的是一些特定的信息,在BTC网络中主要记录的是交易信息,在其他区块链网络中可以按照业务逻辑来保存相应的业务数据,如审计信息、版权信息、票据信息等,这也是区块链经常用来当做共享账本的原因。

    打个比方,可以把区块链当做一个用来记账的笔记本,一个区块就相当于一页纸,上面记录了某一时间段內所有的账务信息,从第一页到最后一页,按照页码顺序排列起来就是一个完整的账本。

    (2)区块链网络

    实际的区块链系统由多个区块链节点组成,每个节点都运行着相同一套区块链主干网络的副本,且各个节点间通过P2P网络进行交互,并最终形成一个完整的区块链网络系统。

    P2P网络具有可靠性、去中心化,以及开放性,各个节点之间交互运作、协同处理,每个节点在对外提供服务的同时也使用网络中其他节点所提供的服务。当某一个区块链节点产生新的区块时,会通过广播的方式告诉其他节点,其他节点通过网络接收到该区块信息时,会对这个区块信息进行验证,当有一定数量的节点都验证通过后,各个节点会把该区块更新到各自现有的区块链上,最终使得整个区块链网络中的各个节点信息保持一致,这也是区块链去中心化、可信任特性的体现。

    区块链网络简易模型,如下图所示:

    2、区块链分类

    (1)公有链

    公有区块链(Public Block Chains)是指:世界上任何个体或者团体都可以发送交易,且交易能够获得该区块链的有效确认,任何人都可以参与使用和维护该区块链,信息公开透明。公有区块链是最早的区块链,例如BTC、以太坊等虚拟数字货币均基于公有区块链。不过目前公有链实际应用价值不大,并没有产生特别合适的应用场景。

    (2)联盟链

    行业区块链(Consortium Block Chains):由某个群体内部指定多个预选的节点为记账人,每个块的生成由所有的预选节点共同决定(预选节点参与共识过程),其他接入节点可以参与交易,但有权限限制,信息受保护,如银联组织。目前联盟链是各个区块链技术团队主要研究的对象,由于联盟链拥有区块链技术的大部分特征,并且在权限管理、数据安全、监管方面更有优势,是企业优先考虑的区块链技术方案。

    市面上也有一些比较主流的联盟链技术框架,让开发维护联盟链更加便捷。国内一些大的软件厂商也都有自己的企业区块链技术解决方案,例如蚂蚁金服区块链平台,腾讯的TrustSQL平台,东软的SaCa EchoTrust区块链应用平台以及京东区块链防伪追溯平台等等。

    (3)私有链

    私有区块链(Private Block Chains):仅仅使用区块链的总账技术进行记账,可以是一个公司,也可以是个人,独享该区块链的写入权限,利用区块链的不易篡改特性,把区块链作为账本数据库来使用。

    3、关键技术与特性

    (1)共识机制

    共识机制被称作为区块链系统的灵魂,是区块链系统信任体系的基础。区块链系统作为一个多节点的分布式账本系统,当有新的信息需要记录时,哪个节点来负责记账,记账奖励发放给哪个节点,哪些节点负责验证记账结果,如何让各个节点达成最终一致,将记账结果被网络中所有节点以同样的顺序复制并记录下来,就是共识机制要做的事情。

    而按照百度百科上的说法:

    所谓“共识机制”是通过特殊节点的投票,在很短的时间内完成对交易的验证和确认,对一笔交易,如果利益不相干的若干个节点能够达成共识,我们就可以认为全网对此也能够达成共识。再通俗一点来讲,如果中国一名微博大V、美国一名虚拟币玩家、一名非洲留学生和一名欧洲旅行者互不相识,但他们都一致认为你是个好人,那么基本上就可以断定你这人还不坏。

    目前,较为主流的共识算法有PoW、PoS、DPoS、PBFT等,在实际使用时,每种算法都有各自的优点和缺点。在应用于不同场景时,区块链项目将会采用不同的共识机制和算法。

    (2)去中心化

    去中心化,是互联网发展过程中形成的社会关系形态和内容产生形态,是相对于“中心化”而言的新型网络内容生产过程。在一个分布有众多节点的区块链系统中,每个节点都具有高度自治的特征。任何一个节点都可能成为阶段性的中心,但不具备强制性的中心控制功能。节点与节点之间的影响,会通过网络而形成关联关系。这种开放式、扁平化、平等性的系统现象或结构,我们称之为去中心化。

    去中心化的系统具有容错力高、抗攻击力强的特征。中心化的系统一旦中心出现问题,整个系统都会崩溃,但是区块链系统中的任何一个节点出现问题,并不会对整个区块链网络产生太大的影响。

    另外,去中介化并不代表着不接受监管,“去中心化”去的是中央控制方和中介方,而不是监管方。监管节点可以方便地接入任何一个区块链网络。并且由于区块链的公开透明特性,监管机构反而可以更加方便地监控整个系统的交易数据。

    (3)智能合约

    从技术层面讲,智能合约是一段部署在在区块链上的程序代码,当满足程序设定的条件时,它便会在区块链上运行,并得到相应的结果。这种情况有点类似于微信的小程序,区块链提供虚拟机和脚本语言,用户根据脚本语言的语法开发带有一定业务逻辑的程序,部署在区块链上,当满足执行的条件时,智能合约便会被区块链虚拟机解释并运行。

    典型的应用便是以太坊平台的智能合约,在这个平台里可以支持用户通过简单的几行代码就能实现他们想要的合约,实现无需人为监督的、不可篡改、自动化运行的合约,买卖房子不需要再找中介、借钱不需要再找公证人……人们可以随时随地根据自身需求发起合约,它的执行不依赖某个人和组织,所有的信任完全基于以太坊区块链平台本身。

    (4)不可篡改性

    大部分人习惯称它为不可篡改性,但是从技术层面来说,我个人觉得叫做不可逆转性更贴切,既然是一个计算机系统,增删改查是基本的功能属性,只不过区块链系统删除和修改操作比较特殊一点。

    区块链是由每个区块的哈希值串连起来的链式结构,而区块的哈希值=SHA256(“当前区块内容+上一个区块的哈希值”),任何一个区块的内容发生修改,都会引起哈希值的变化,而哈希值的变化也会引起子区块哈希值发生变化,进而引起整个区块链的改变。

    因此任何人想要修改区块的数据几乎是不可能的,除非他把整个区块链中从创世区块到最新的区块的所有哈希值全部重新修改一遍,并且修改完之后,还得广播告诉网络中的其他所有节点,让其他所有节点接受修改。

    不过按照目前计算机的算力,想要在短时间内从区块链头部到尾部全部修改一遍,是一件非常困难的事,并且即使修改完了,其他节点也不会接受修改,因为凭一己之力,没有能够让所有节点达成共识的条件。

    4、流行的区块链框架与应用

    (1)公有链应用:BTC网络

    区块链1.0产品,对于比特币,中本聪是这样定义的:是一种完全通过点对点技术实现的电子现金系统,它使得在线支付能够直接由一方发起并支付给另外一方,中间不需要通过任何的金融机构。

    与所有的货币不同,比特币不依靠特定货币机构发行,它依据特定算法,通过大量的计算产生,比特币经济使用整个P2P网络中众多节点构成的分布式数据库来确认并记录所有的交易行为,并使用密码学的设计来确保货币流通各个环节安全性。之后人们根据比特币网络技术整理出了区块链技术体系,去解决信任的问题,而比特币网络原理也成为了区块链技术初学者的经典教材。

    (2)公有链应用:以太坊网络

    区块链2.0产品的代表,以太坊是一个为去中心化应用(Dapp)而生的开源区块链平台,拥有着大部分区块链技术的特征,但与其它区块链不同的是,以太坊是可编程的,开发者可以用它来构建不同的应用程序,通过其专用加密货币以太币(简称“ETH”)提供去中心化的以太虚拟机(Ethereum Virtual Machine)来处理点对点合约(就是一些脚本程序代码)。如果把比特币网络看作是一套分布式的数据库,而以太坊则更进一步,它可以看作是一台分布式的计算机:区块链是计算机的ROM,合约是程序,而以太坊的矿工们则负责计算,担任CPU的角色。


    以太坊的概念首次在2013至2014年间由程序员Vitalik Buterin受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”。虽然以太坊作为平台可以在其上开发新的应用,但是由于以太坊的运行和BTC网络一样,采用的是Token机制,且平台性能不足,经常出现网络拥堵的情况,平台用来学习开发与测试区块链技术还可以,用于实际生产的话不太现实。

    (3)联盟链开发框架:Hyperledger Fabric

    Hyperledger Fabric 也叫超级账本,它是 IBM 贡献给 Linux 基金会的商用分布式账本,是面向企业应用的全球最大的分布式开源项目。像其他区块链技术一样,它也有一个账本,可以使用智能合约。Fabric的智能合约可以有多种架构,它可以用主流语言编程,例如Go、Java和Javascript,此外也可以使用Solidity。

    至今,Fabric已获得了阿里巴巴、AWS、Azure、百度、谷歌、华为、IBM、甲骨文、腾讯等互联网巨头的支持。许多企业的区块链平台都把Fabric作为底层框架来使用,例如甲骨文。不过由于IBM对区块链的定义强调了区块链的分布式和不可变两个元素,对共识机制进行了削弱,采用了Kafka和zookeeper的“排序服务”实现共识,因此部分业内人士也称超级账本是“伪区块链”,但是即便如此,也抵挡不了企业对超级账本的喜爱,目前Fabric 2.0版本已经正式发布。

    (4)小结

    目前公有链在实际应用中并没有太多的业务场景落地,大部分都是以挖矿为主题或者线上宠物饲养的游戏为主,并且由于数字货币的匿名性,有些不法分子利用这一特点,将数字货币用于洗钱、暗网买卖等违法行为,是各个国家的打击对象,我国政策法规也严厉禁止,因此对于技术人员来说,公有链可以作为研究学习的对象,其他方面暂时没有太多实际意义。

    目前大部分区块链企业的研究方向主要是针对企业的联盟链和私有链,并且国家层面也在大力支持区块链技术的发展,特别是区块链底层核心技术的研发,倡导把区块链作为核心技术自主创新的重要突破口,明确主攻方向,加大投入力度,着力攻克一批关键核心技术,加快推动区块链技术和产业创新发展。不过现在市面上主流的区块链平台大部分还是以国外公司主导的为主,国内区块链底层核心技术的发展,还需要技术人员的加倍努力。

    二、区块链技术Java实现

    1、区块链技术架构


    目前主流的区块链技术架构主要分为五层,数据层是最底层的技术,主要实现了数据存储、账户信息、交易信息等模块,数据存储主要基于Merkle树,通过区块的方式和链式结构实现,而账户和交易基于数字签名、哈希函数和非对称加密技术等多种密码学算法和技术,来保证区块链中数据的安全性。

    网络层主要实现网络节点的连接和通讯,又称点对点技术,各个区块链节点通过网络进行通信。共识层是通过共识算法,让网络中的各个节点对全网所有的区块数据真实性正确性达成一致,防止出现拜占庭攻击、51攻击等区块链共识算法攻击。

    激励层主要是实现区块链代币的发行和分配机制,是公有链的范畴,我们不做分析。应用层一般把区块链系统作为一个平台,在平台之上实现一些去中心化的应用程序或者智能合约,平台提供运行这些应用的虚拟机。

    接下来我们基于Java语言来开发一套小型的区块链系统,来实现数据层、网络层、共识层的一些功能,用简单的代码来直观抽象的概念,以便加深对以上区块链技术基础理论的理解。

    2、基于java的区块链开发实战

    (1)开发环境

    开发工具VSCode
    开发语言Java
    JDK版本JDK1.8或者OpenJDK11
    开发框架SpringBoot2.2.1
    工程管理Maven3.6
    测试工具Postman

    (2)区块链基本模型构建

    区块是区块链系统的最小单元,第一步我们先实现最简单的区块结构,新建Block.java类,主要包含以下几个字段:
    Block.java

    /**
     * 区块结构
     * 
     * @author Jared Jia
     *
     */
    public class Block implements Serializable {
    
    
      private static final long serialVersionUID = 1L;
      /**
       * 区块索引号(区块高度)
       */
      private int index;
      /**
       * 当前区块的hash值,区块唯一标识
       */
      private String hash;
      /**
       * 前一个区块的hash值
       */
      private String previousHash;
      /**
       * 生成区块的时间戳
       */
      private long timestamp;
      /**
       * 工作量证明,计算正确hash值的次数
       */
      private int nonce;
      /**
       * 当前区块存储的业务数据集合(例如转账交易信息、票据信息、合同信息等)
       */
      private List<Transaction> transactions;
      
      /*** 省略get set方法****/
      }
    

    区块链是由区块按照区块哈希前后顺序串联起来的数据结构,哈希值通过散列算法对区块进行二次哈希计算而得到的数字摘要信息(不了解散列函数的,可以先百度了解一下SHA算法),用于保证区块的信息安全以及整条区块链的有效性。因此第二步我们新增计算区块Hash值的方法,采用SHA256算法,通过java实现:
    CryptoUtil.java

    /**
     * 密码学工具类
     * 
     * @author Jared Jia
     *
     */
    public class CryptoUtil {
    
    
      /**
       * SHA256散列函数
       * @param str
       * @return
       */
      public static String SHA256(String str) {
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
          messageDigest = MessageDigest.getInstance("SHA-256");
          messageDigest.update(str.getBytes("UTF-8"));
          encodeStr = byte2Hex(messageDigest.digest());
        } catch (Exception e) {
          System.out.println("getSHA256 is error" + e.getMessage());
        }
        return encodeStr;
      }
      
      private static String byte2Hex(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        String temp;
        for (int i = 0; i < bytes.length; i++) {
          temp = Integer.toHexString(bytes[i] & 0xFF);
          if (temp.length() == 1) {
            builder.append("0");
          }
          builder.append(temp);
        }
        return builder.toString();
      }
    }
    

    第三步,创建一个链式结构对象,按照先后顺序来保存区块对象,从来形成一个有序的区块链表,考虑到线程安全问题,采用CopyOnWriteArrayList来实现,为了方便测试,暂且把区块链结构保存在本地缓存中,实际的区块链网络最终会实现持久层的功能,把区块链数据保存至数据库中,例如BTC核心网络采用的是K-V数据库LevelDB:
    BlockCache.java

    public class BlockCache {
    
    
      /**
       * 当前节点的区块链结构
       */
      private List<Block> blockChain = new CopyOnWriteArrayList<Block>();
      
      public List<Block> getBlockChain() {
        return blockChain;
      }
    
    
      public void setBlockChain(List<Block> blockChain) {
        this.blockChain = blockChain;
      }
     }
    

    第四步,有了区块链结构后,需要新增向区块链中添加区块的方法,同时每次添加区块的时候,我们需要验证新区块的有效性,例如Hash值是否正确,新区块中上一区块的Hash属性的值,与上一区块的Hash值是否相等。

    另外,区块链中必须有个创世区块,我们直接通过硬编码实现:
    BlockService.java

    /**
     * 区块链核心服务
     * 
     * @author Jared Jia
     *
     */
    @Service
    public class BlockService {
    
    
      @Autowired
      BlockCache blockCache;
      
      /**
       * 创建创世区块
       * @return
       */
      public String createGenesisBlock() {
        Block genesisBlock = new Block();
        //设置创世区块高度为1
        genesisBlock.setIndex(1);
        genesisBlock.setTimestamp(System.currentTimeMillis());
        genesisBlock.setNonce(1);
        //封装业务数据
        List<Transaction> tsaList = new ArrayList<Transaction>();
        Transaction tsa = new Transaction();
        tsa.setId("1");
        tsa.setBusinessInfo("这是创世区块");
        tsaList.add(tsa);
        Transaction tsa2 = new Transaction();
        tsa2.setId("2");
        tsa2.setBusinessInfo("区块链高度为:1");
        tsaList.add(tsa2);    
        genesisBlock.setTransactions(tsaList);
        //设置创世区块的hash值
        genesisBlock.setHash(calculateHash("",tsaList,1));
        //添加到已打包保存的业务数据集合中
        blockCache.getPackedTransactions().addAll(tsaList);
        //添加到区块链中
        blockCache.getBlockChain().add(genesisBlock);
        return JSON.toJSONString(genesisBlock);
      }
      
      /**
       * 创建新区块
       * @param nonce
       * @param previousHash
       * @param hash
       * @param blockTxs
       * @return
       */
      public Block createNewBlock(int nonce, String previousHash, String hash, List<Transaction> blockTxs) {
        Block block = new Block();
        block.setIndex(blockCache.getBlockChain().size() + 1);
        //时间戳
        block.setTimestamp(System.currentTimeMillis());
        block.setTransactions(blockTxs);
        //工作量证明,计算正确hash值的次数
        block.setNonce(nonce);
        //上一区块的哈希
        block.setPreviousHash(previousHash);
        //当前区块的哈希
        block.setHash(hash);
        if (addBlock(block)) {
          return block;
        }
        return null;
      }
    
    
      /**
       * 添加新区块到当前节点的区块链中
       * 
       * @param newBlock
       */
      public boolean addBlock(Block newBlock) {
        //先对新区块的合法性进行校验
        if (isValidNewBlock(newBlock, blockCache.getLatestBlock())) {
          blockCache.getBlockChain().add(newBlock);
          // 新区块的业务数据需要加入到已打包的业务数据集合里去
          blockCache.getPackedTransactions().addAll(newBlock.getTransactions());
          return true;
        }
        return false;
      }
      
      /**
       * 验证新区块是否有效
       * 
       * @param newBlock
       * @param previousBlock
       * @return
       */
      public boolean isValidNewBlock(Block newBlock, Block previousBlock) {
        if (!previousBlock.getHash().equals(newBlock.getPreviousHash())) {
          System.out.println("新区块的前一个区块hash验证不通过");
          return false;
        } else {
          // 验证新区块hash值的正确性
          String hash = calculateHash(newBlock.getPreviousHash(), newBlock.getTransactions(), newBlock.getNonce());
          if (!hash.equals(newBlock.getHash())) {
            System.out.println("新区块的hash无效: " + hash + " " + newBlock.getHash());
            return false;
          }
          if (!isValidHash(newBlock.getHash())) {
            return false;
          }
        }
    
    
        return true;
      }
     }
    

    以上关键代码实现之后,我们就构建了一个非常简单的区块链模型,包含一个基本的区块模型和一个区块链模型,并且能够生成新的区块并添加到区块链中,接下来我们进行测试。

    第五步,我们编写一个Controller类进行调用:
    BlockController.java

    @Controller
    public class BlockController {
    
    
      @Resource
      BlockService blockService;
      
      @Autowired
      BlockCache blockCache;
      
      /**
       * 查看当前节点区块链数据
       * @return
       */
      @GetMapping("/scan")
      @ResponseBody
      public String scanBlock() {
        return JSON.toJSONString(blockCache.getBlockChain());
      }
      
      /**
       * 创建创世区块
       * @return
       */
      @GetMapping("/create")
      @ResponseBody
      public String createFirstBlock() {
        blockService.createGenesisBlock();
        return JSON.toJSONString(blockCache.getBlockChain());
      }
     }
    

    第六步,系统测试
    首先系统启动后,先查看区块链中的数据,可以看到当前系统中的区块链为空:

    然后我们调用创建创世区块的方法,查看返回结果:

    我们把生成的创世区块添加到本地区块链中后,转换成JSON字符串返回,可以看到当前区块链中存储的有一个区块对象,至此我们已经实现了一个简单的区块链。实际的区块链系统模型要复杂的多,需要根据不同的业务场景扩展相应的字段,但是基本特征都是一样的。

    (3)共识机制实现

    在上章节中,我们实现了一个简单的区块链结构,并且能够生成并添加新的区块,但是问题来了,实际的区块链系统是一个多节点、分布式、去中心化的网络,每个节点通过网络交互,实时同步保存着同样的整条区块链数据,那么我们生成的区块,如何才能被其他节点认可,并同步添加到其他所有节点上呢,这个时候我们就需要一套规则,让所有网络节点的参与者达成能够达成共识,接纳并保存新的区块,也就是所谓的“共识机制”。

    理论基础部分已经提到了,共识机制有很多种,各有各的优势与缺点,接下来我们就用java代码来模拟实现我们最为熟知的一种机制:工作量证明(Proof of Work),顾名思义就是对工作量的证明,在基于POW机制构建的区块链网络中,节点通过计算随机哈希散列的数值争夺记账权,求得正确的数值并生成区块的能力是节点算力的具体表现,计算的过程一般被形象地称为“挖矿”。

    简单来说就是,区块链系统设定一套计算规则或者说是一套计算题,在新区块生成前,各个节点都投入到这道题的求解计算中,哪个节点先计算出结果,并得到其它节点的验证和认可,这个节点就会获得新区块的记账权,并获得系统相应的奖励,共识结束。

    典型的PoW共识机制应用就是BTC网络,在BTC网络中,共识计算的目标是找到满足某个特定要求的区块Hash(哈希值)。这个区块哈希值就是工作结果的一个证明,计算工作的目的就是为了寻找到这个证明值,上一章节中,测试时我们已经见过这个Hash值:

    [
        {
            "hash": "25931395e736653212f0258824df4222ae739ec2d5897310258b0857d4d3870c",
            "index": 1,
            "nonce": 1,
            "timestamp": 1580970554734,
            "transactions": [
                {
                    "businessInfo": "这是创世区块",
                    "id": "1"
                }
            ]
        }
    ]
    

    BTC网络PoW使用的Hashcash算法,大致逻辑如下:

    1. 获取某种公开可知的数据data(BTC网络中,指的是区块头);

    2. 添加一个计数器nonce,初始值设置为0;

    3. 计算data与nonce拼接字符串的哈希值;

    4. 检查上一步的哈希值是否满足某个条件,满足则停止计算,不满足则nonce加1,然后重复第3步和第4步,直到满足这个特定的条件为止。

    接下来我们用Java代码实现这个算法,设定满足的特定条件为,Hash值前4位都是0,则计算成功(实际区块链网络中的特定条件要求更高,对计算的运算能力要求也高,并且系统随着计算难度动态调整满足的特定条件,来保证区块生成的速度)。

    第一步,我们新建一个共识机制服务类,添加一个“挖矿”方法,计算成功后,获取记账权,调用添加区块的方法,把区块添加到区块链中:
    PowService.java

    /**
     * 共识机制
     * 采用POW即工作量证明实现共识
     * @author Administrator
     *
     */
    @Service
    public class PowService {
    
    
      @Autowired
      BlockCache blockCache;
      
      @Autowired
      BlockService blockService;
      
      /**
       * 通过“挖矿”进行工作量证明,实现节点间的共识
       * 
       * @return
       */
      public Block mine(){
        
        // 封装业务数据集合,记录区块产生的节点信息,临时硬编码实现
        List<Transaction> tsaList = new ArrayList<Transaction>();
        Transaction tsa1 = new Transaction();
        tsa1.setId("1");
        tsa1.setBusinessInfo("这是IP为:"+CommonUtil.getLocalIp()+",端口号为:"+blockCache.getP2pport()+"的节点挖矿生成的区块");
        tsaList.add(tsa1);
        Transaction tsa2 = new Transaction();
        tsa2.setId("2");
        tsa2.setBusinessInfo("区块链高度为:"+(blockCache.getLatestBlock().getIndex()+1));
        tsaList.add(tsa2);
        
        // 定义每次哈希函数的结果 
        String newBlockHash = "";
        int nonce = 0;
        long start = System.currentTimeMillis();
        System.out.println("开始挖矿");
        while (true) {
          // 计算新区块hash值
          newBlockHash = blockService.calculateHash(blockCache.getLatestBlock().getHash(), tsaList, nonce);
          // 校验hash值
          if (blockService.isValidHash(newBlockHash)) {
            System.out.println("挖矿完成,正确的hash值:" + newBlockHash);
            System.out.println("挖矿耗费时间:" + (System.currentTimeMillis() - start) + "ms");
            break;
          }
          System.out.println("第"+(nonce+1)+"次尝试计算的hash值:" + newBlockHash);
          nonce++;
        }
        // 创建新的区块
        Block block = blockService.createNewBlock(nonce, blockCache.getLatestBlock().getHash(), newBlockHash, tsaList);
        return block;
      }
      
      /**
       * 验证hash值是否满足系统条件
       * 暂定前4位是0则满足条件
       * @param hash
       * @return
       */
      public boolean isValidHash(String hash) {
        //System.out.println("难度系数:"+blockCache.getDifficulty());
        return hash.startsWith("0000");
      }
    }
    

    第二步,编写测试共识机制服务的Controller类方法:
    BlockController.java

    /**
       * 工作量证明PoW
       * 挖矿生成新的区块 
       */
      @GetMapping("/mine")
      @ResponseBody
      public String createNewBlock() {
        powService.mine();
        return JSON.toJSONString(blockCache.getBlockChain());
      }
    

    第三步,启动系统,进行测试。
    首先执行http://localhost:8080/create方法,生成创世区块。
    其次调用http://localhost:8080/mine方法进行工作量计算证明,生成新的区块,并添加到本地区块链中:

    我们来看一下,系统后台计算的过程,此次计算共花费1048ms计算出满足条件的Hash值,共计算4850次:

    至此,我们实现了一个简单的工作量证明机制,并在当前区块链系统节点上运行,完成了正确结果的计算,生成了一个新的区块。

    接下来我们将会开发一个P2P网络,实现多个节点的同时运行,当一个节点挖矿完成后,通过P2P网络广播给其他节点,其他节点验证通过后,会把新产生的区块添加到自己的区块链上,进而保证整个区块链网络所有节点的数据一致性。

    (4)P2P网络开发

    前面我们已经实现了一个基本的区块链系统,并且实现了PoW工作量证明共识机制,通过挖矿计算出正确的结果同时生成一个新的区块添加到区块链中,但是这些都是基于单节点的运行,实际的区块链是有多个节点同时运行的分布式网络系统,所有节点同时计算抢夺记账权,共同维护一条完整的区块链。

    接下来我们基于Java的WebSocket实现一个Peer-to-Peer网络,实现多个节点间的相互通信,通过本章节,我们将要实现以下功能:

      - 创建一个基于java的p2p网络
      - 运行多个节点,且多个节点通过p2p网络自动同步区块信息
      - 一个节点挖矿生成新的区块后,自动广播给其他所有节点
      - 每个节点在接收到其他节点发送的区块内容后,进行验证,验证通过添加到本地区块链上
      - 在自我节点查看整个区块链内容
    

    开发测试本章节的功能,我们最好准备两台电脑或者虚拟机,再或者Docker集群环境也可以,便于多节点的运行测试。如果只有一台电脑也可以,各个节点运行的端口号设置为不相同即可。

    第一步,开发思路整理
    目前我们已经实现了单节点的区块生成,那么我们接下来只需要实现各个节点的消息同步即可。

    • 首先,通过java代码实现p2p网络的server端和client端,每个节点既是服务端也是客户端。

    • 然后,一个节点启动时,会寻找区块链网络上的有效节点,并建立socket连接(BTC网络可以通过使用“DNS”种子方式获取BTC有效节点,DNS种子提供比特币节点的IP地址列表),我们直接把节点列表配置到application.yml文件中。

    • 接着,从连接上的节点获取最新的区块信息,如果当前节点首次运行,则获取整个区块链信息,并替换到本地。

    • 之后,各个节点同时挖矿计算,哪个节点先计算完成,就把生成的新区块全网广播给其他所有节点(实际的区块链网络一直在计算,我们为了便于测试,手动触发一个节点挖矿产生区块,然后全网广播给其他所有节点)。

    • 最后,当一个节点收到广播内容后,对接收到的新区块进行验证,验证通过后添加到本地区块链上,验证的首要条件是新区块的高度必须比本地的区块链高度要高。

    第二步,先实现P2P网络server端
    新建一个P2PServer类,并添加一个初始化server端的方法:
    P2PServer.java

    /**
     * p2p服务端
     * 
     * @author Jared Jia
     *
     */
    @Component
    public class P2PServer {
    
    
      @Autowired
      P2PService p2pService;
    
    
      public void initP2PServer(int port) {
        WebSocketServer socketServer = new WebSocketServer(new InetSocketAddress(port)) {
    
    
          /**
           * 连接建立后触发
           */
          @Override
          public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
            p2pService.getSockets().add(webSocket);
          }
    
    
          /**
           * 连接关闭后触发
           */
          @Override
          public void onClose(WebSocket webSocket, int i, String s, boolean b) {
            p2pService.getSockets().remove(webSocket);
            System.out.println("connection closed to address:" + webSocket.getRemoteSocketAddress());
          }
    
    
          /**
           * 接收到客户端消息时触发
           */
          @Override
          public void onMessage(WebSocket webSocket, String msg) {
            //作为服务端,业务逻辑处理
            p2pService.handleMessage(webSocket, msg, p2pService.getSockets());
          }
    
    
          /**
           * 发生错误时触发
           */
          @Override
          public void onError(WebSocket webSocket, Exception e) {
            p2pService.getSockets().remove(webSocket);
            System.out.println("connection failed to address:" + webSocket.getRemoteSocketAddress());
          }
    
    
          @Override
          public void onStart() {
    
    
          }
    
    
        };
        socketServer.start();
        System.out.println("listening websocket p2p port on: " + port);
      }
    }
    
    
    

    第三步,实现P2P网络client端
    P2PClient.java

    /**
     * p2p客户端
     * 
     * @author Jared Jia
     *
     */
    @Component
    public class P2PClient {
      
      @Autowired
      P2PService p2pService;
    
    
      public void connectToPeer(String addr) {
        try {
          final WebSocketClient socketClient = new WebSocketClient(new URI(addr)) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
              //客户端发送请求,查询最新区块
              p2pService.write(this, p2pService.queryLatestBlockMsg());
              p2pService.getSockets().add(this);
            }
    
    
            /**
             * 接收到消息时触发
             * @param msg
             */
            @Override
            public void onMessage(String msg) {
              p2pService.handleMessage(this, msg, p2pService.getSockets());
            }
    
    
            @Override
            public void onClose(int i, String msg, boolean b) {
              p2pService.getSockets().remove(this);
              System.out.println("connection closed");
            }
    
    
            @Override
            public void onError(Exception e) {
              p2pService.getSockets().remove(this);
              System.out.println("connection failed");
            }
          };
          socketClient.connect();
        } catch (URISyntaxException e) {
          System.out.println("p2p connect is error:" + e.getMessage());
        }
      }
    }
    

    第四步,定义P2P网络同步的消息模型
    同步的消息模型,我们定义为四类,分别是:
    BlockConstant.java

      // 查询最新的区块
      public final static int QUERY_LATEST_BLOCK = 1;
    
    
      // 返回最新的区块
      public final static int RESPONSE_LATEST_BLOCK = 2;
    
    
      // 查询整个区块链
      public final static int QUERY_BLOCKCHAIN = 3;
    
    
      // 返回整个区块链
      public final static int RESPONSE_BLOCKCHAIN = 4;
    

    定义一个各个节点间传递的消息模型:
    Message.java

    /**
     * p2p通讯消息
     *
     * @author Jared Jia
     * 
     */
    public class Message implements Serializable {
      
        private static final long serialVersionUID = 1L;
        /**
         * 消息类型
         */
        private int type;
        /**
         * 消息内容
         */
        private String data;
        
        /****set get方法省略****/
        
      }
    

    第五步,实现向其他节点广播的方法

    新建一个p2p网络服务类,向外发送消息,或者处理当前节点收到其他节点发送的请求。
    P2PService.java

    /**
       * 全网广播消息
       * @param message
       */
      public void broatcast(String message) {
        List<WebSocket> socketsList = this.getSockets();
        if (CollectionUtils.isEmpty(socketsList)) {
          return;
        }
        System.out.println("======全网广播消息开始:");
        for (WebSocket socket : socketsList) {
          this.write(socket, message);
        }
        System.out.println("======全网广播消息结束");
      }
    

    第六步,开发消息处理路由

    第五步中已经实现了向外发送消息,本步骤实现接收消息。
    首先设计一个服务端和客户端共用的消息路由,来分发消息给对应的处理单元。
    P2PService.java

    /**
       * 客户端和服务端共用的消息处理方法
       * @param webSocket
       * @param msg
       * @param sockets
       */
      public void handleMessage(WebSocket webSocket, String msg, List<WebSocket> sockets) {
        try {
          Message message = JSON.parseObject(msg, Message.class);
          System.out.println("接收到IP地址为:" +webSocket.getRemoteSocketAddress().getAddress().toString()
              +",端口号为:"+ webSocket.getRemoteSocketAddress().getPort() + "的p2p消息:"
                  + JSON.toJSONString(message));
          switch (message.getType()) {
          //客户端请求查询最新的区块:1
          case BlockConstant.QUERY_LATEST_BLOCK:
            write(webSocket, responseLatestBlockMsg());//服务端调用方法返回最新区块:2
            break;
          //接收到服务端返回的最新区块:2
          case BlockConstant.RESPONSE_LATEST_BLOCK:
            handleBlockResponse(message.getData(), sockets);
            break;
          //客户端请求查询整个区块链:3
          case BlockConstant.QUERY_BLOCKCHAIN:
            write(webSocket, responseBlockChainMsg());//服务端调用方法返回最新区块:4
            break;
          //直接接收到其他节点发送的整条区块链信息:4
          case BlockConstant.RESPONSE_BLOCKCHAIN:
            handleBlockChainResponse(message.getData(), sockets);
            break;
          }
        } catch (Exception e) {
          System.out.println("处理IP地址为:" +webSocket.getRemoteSocketAddress().getAddress().toString()
            +",端口号为:"+ webSocket.getRemoteSocketAddress().getPort() + "的p2p消息错误:" 
            + e.getMessage());
        }
      }
    

    第七步,开发消息处理单元

    有了消息路由之后,接着编写不同的处理单元,处理其他节点发送来的区块或者区块链信息,总体原则是:先校验其他节点发送来的区块或者区块链的有效性,然后判断它们的高度比当前节点的区块链高度要高,如果高则替换本地的区块链,或者把新区块添加到本地区块链上。
    P2PService.java

    /**
       * 处理其它节点发送过来的区块信息
       * @param blockData
       * @param sockets
       */
      public synchronized void handleBlockResponse(String blockData, List<WebSocket> sockets) {
        //反序列化得到其它节点的最新区块信息
        Block latestBlockReceived = JSON.parseObject(blockData, Block.class);
        //当前节点的最新区块
        Block latestBlock = blockCache.getLatestBlock();
        
        if (latestBlockReceived != null) {
          if(latestBlock != null) {
            //如果接收到的区块高度比本地区块高度大的多
            if(latestBlockReceived.getIndex() > latestBlock.getIndex() + 1) {
              broatcast(queryBlockChainMsg());
              System.out.println("重新查询所有节点上的整条区块链");
            }else if (latestBlockReceived.getIndex() > latestBlock.getIndex() && 
                latestBlock.getHash().equals(latestBlockReceived.getPreviousHash())) {
              if (blockService.addBlock(latestBlockReceived)) {
                broatcast(responseLatestBlockMsg());
              }
              System.out.println("将新接收到的区块加入到本地的区块链");
            }
          }else if(latestBlock == null) {
            broatcast(queryBlockChainMsg());
            System.out.println("重新查询所有节点上的整条区块链");
          }
        }
      }
      
      /**
       * 处理其它节点发送过来的区块链信息
       * @param blockData
       * @param sockets
       */
      public synchronized void handleBlockChainResponse(String blockData, List<WebSocket> sockets) {
        //反序列化得到其它节点的整条区块链信息
        List<Block> receiveBlockchain = JSON.parseArray(blockData, Block.class);
        if(!CollectionUtils.isEmpty(receiveBlockchain) && blockService.isValidChain(receiveBlockchain)) {
          //根据区块索引先对区块进行排序
          Collections.sort(receiveBlockchain, new Comparator<Block>() {
            public int compare(Block block1, Block block2) {
              return block1.getIndex() - block2.getIndex();
            }
          });
          
          //其它节点的最新区块
          Block latestBlockReceived = receiveBlockchain.get(receiveBlockchain.size() - 1);
          //当前节点的最新区块
          Block latestBlock = blockCache.getLatestBlock();
          
          if(latestBlock == null) {
            //替换本地的区块链
            blockService.replaceChain(receiveBlockchain);
          }else {
            //其它节点区块链如果比当前节点的长,则处理当前节点的区块链
            if (latestBlockReceived.getIndex() > latestBlock.getIndex()) {
              if (latestBlock.getHash().equals(latestBlockReceived.getPreviousHash())) {
                if (blockService.addBlock(latestBlockReceived)) {
                  broatcast(responseLatestBlockMsg());
                }
                System.out.println("将新接收到的区块加入到本地的区块链");
              } else {
                // 用长链替换本地的短链
                blockService.replaceChain(receiveBlockchain);
              }
            }
          }
        }
      }
    

    3、完整系统运行与测试

    第一步,打包生成测试用的可执行jar包
    准备两台机器(虚拟机或者Docker集群都行),同时运行两个节点,节点信息如下:

    通过mvn package -Dmaven.test.skip=true命令对工程进行打包,生成可直接运行的jar包,打包前对工程进行配置,配置信息如下图:

    节点Node1打包:

    节点Node2打包:

    分别打包之后,生成两个节点的可执行jar包,如下:

    把两个jar包分别放在对应IP的windows机器上,打开命令行模式,进入jar所在文件夹,分别执行以下命令运行两个节点:
    java -jar dce-blockchain-node1.jar
    java -jar dce-blockchain-node2.jar

    启动节点2的时候,可以看到后台日志,已经连接上节点1,如下图所示:

    第二步,对两个节点进行测试

    首先,两个节点启动后,用postman分别执行http://192.168.0.104:8080/scan和http://192.168.0.112:8090/scan请求,可以看到两个节点的区块链内容都为空。

    然后,在节点1上分别执行http://192.168.0.104:8080/create和http://192.168.0.104:8080/mine请求,来生成创世区块,以及通过挖矿产生第二个区块,执行后查看节点1的区块链信息如下:
    执行http://192.168.0.104:8080/scan结果:

    [
        {
            "hash": "5303d2990c139992bdb5a22aa1dac4f2719755304e45bac03ca4a1f1688c909e",
            "index": 1,
            "nonce": 1,
            "timestamp": 1581064647736,
            "transactions": [
                {
                    "businessInfo": "这是创世区块",
                    "id": "1"
                },
                {
                    "businessInfo": "区块链高度为:1",
                    "id": "2"
                }
            ]
        },
        {
            "hash": "0000de5eea0c20c2e7d06220bc023886e88dd8784eaa2fd2d1d6c5e581061d85",
            "index": 2,
            "nonce": 4850,
            "previousHash": "5303d2990c139992bdb5a22aa1dac4f2719755304e45bac03ca4a1f1688c909e",
            "timestamp": 1581064655139,
            "transactions": [
                {
                    "businessInfo": "这是IP为:192.168.0.104,端口号为:7001的节点挖矿生成的区块",
                    "id": "1"
                },
                {
                    "businessInfo": "区块链高度为:2",
                    "id": "2"
                }
            ]
        }
    ]
    

    最后,我们来验证节点2是否已经完成了节点1生成的区块链信息的网络同步,Postman执行http://192.168.0.112:8090/scan请求,查看返回结果:
     从结果可以看到,区块链网络节点2已经接收到节点1发送的区块链信息,系统日志如下:

    反过来,我们在节点2上再执行一次挖矿操作,可以看到节点1上,已经接收到节点2挖矿新产生的区块信息,并添加到节点1的区块链上:

    至此,我们已经实现了一个完整的小型区块链网络,并实现各个节点间的通信,多个节点共同维护同一个区块链信息。

    结语:
    区块链系统非常庞大,涉及方方面面的技术,本人所演示的代码主要对区块链基础的一些概念进行了诠释,感兴趣的同学,还可以在此基础上继续开发,来实现例如持久层、消息的加密解密、系统账户模型、预言机、侧链技术以及智能合约等区块链系统功能。


    写给每个区块链技术人员:
    目前市面上流行的企业级区块链框架,例如超级账本Fabric都是国外人员在主导,而我们国内除了几家大厂外,其他很多区块链公司基本都是把人家的东西拿过来进行二次封装,然后对外声称自己公司已经掌握了区块链核心技术,并对企业提供服务,这是一种不好的现象。大家可以想想我们现在用的开发语言、框架有几个真正是国产的,我们再联想一下前段时间中兴、华为被人家核心技术卡脖子事件,就知道我们要做的事情有很多,我们需要去除浮躁,静下心来好好研究底层核心技术,这样才能实现真正的“弯道超车”!

    三、源代码

    本文完整源代码地址:

    https://gitee.com/luckytuan/dce-blockchain

    PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

    推荐好文

    强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!
    
    分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
    能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!
    
    
    
    
    展开全文
  • 参考《区块链技术 架构与发展》、《区块链以及区块链技术总结》、《区块链技术原理、应用领域及挑战》,对当下区块链系统架构进行细致梳理与补充,区块链技术入门友好。
  • 区块链交易平台系统开发

    万次阅读 2018-02-27 11:18:58
    区块链交易平台系统开发原理:“区块链使用强大的加密技术来维护虚拟安全,通过整体计算机的复杂数学运算机制来验证,删除与存储,区块与之前的区块相互关联,因此形成区块链。”区块链分为三大类:公有链,私有链,...
  • 大量招聘区块链系统开发正式员工和实习生,详情见大图,简历速速砸来。可以发送简历到图中的邮箱。
  • 区块链交易平台系统开发原理:“区块链使用强大的加密技术来维护虚拟安全,通过整体计算机的复杂数学运算机制来验证,删除与存储,区块与之前的区块相互关联,因此形成区块链。” 区块链分为三大类:公有链,私有链...
  • 1. 分布式存储:分布式存储是一种数据存储技术,通过网络...非对称加密和授权技术:存储在区块链上的交易信息是公开的,但是账户身份信息高度加密,只有在数据拥有者授权的情况下才能访问到,从而保证了数据的安全和...
  • 区块链开发详解

    千次阅读 2020-05-19 11:23:35
    开发业务层区块链应用 Hyperledger fabric目前支持java,nodejs,go和python语言的sdk,供用户选择用不同的语言开发上层应用,使用相应的sdk调用部署在区块链上的链码。以下示例中我们选择使用go语言开发业务层应用...
  • 在介绍区块链电商之前,纵观近几...区块链电商系统开发方案(I 3 9微1 O 6 2电9 2 3 8),区块链电商系统软件,区块链电商系统源码,区块链电商系统APP,区块链电商系统平台,区块链电商系统公众号,区块链电商系统AP...
  • 大量招聘区块链系统开发实习生(包含前后端),详情见大图,简历速速砸来。可以发送简历到图中的邮箱。 
  • 本篇文章着眼于入门实践,根据蚂蚁BAAS的官方帮助文档和辉哥的实践,按照一课讲透一个知识点或者功能的逻辑,把蚂蚁BAAS系统深入浅出的做了分析和输出,希望能为大家熟悉蚂蚁区块链系统提供帮助,少走弯路。...
  • 区块链技术开发探索区块链系统未来应用的作用 了解区块链做一个敏锐的先知先觉者发现新时代的机遇区块链技术已经 席卷全球每个人似乎都渴望更多地了解该技术及其在不同领域和领域的各种 应用虽然每个人都熟悉这项...
  • 编写一个简单的区块链系统

    千次阅读 2019-02-24 21:04:11
    使用Python构建一个简单的区块链系统 基于区块链核心原理编写的简单实现。原理讲解 确定区块结构 { &amp;quot;index&amp;quot;: 区块索引, &amp;quot;previous_Hash&amp;quot;: 前一个区块的...
  • 文件内包含百度云链接,永久有效 最新整理区块链技术视频包含开发工具,源码,视频教程,从小白到大神,系统性学习,分享给大家学习。 主要包含:公链开发视频目录、从零构建以太坊(Ethereum)智能合约到项目实战视频...
  • 对初学者,首先要了解以太坊开发相关的基本概念。   学习以太坊开发的一般前序知识要求,最好对以下技术已经有一些基本了解: 一种面向对象的开发语言,例如:Python,Ruby,Java… 前端开发语言:...
  • 区块链是涉及多方的开放系统,早期的应用又与虚拟加密货币相关,由此使得区块链系统所内含的和面对的风险得以暴露,同时各种安全措施也得以被及时使用和验证。但区块链在真实世界的大规模应用尚未展开,因此区块链所...
  • 区块链:交易系统开发指南.pdf
  • 区块链的应用系统开发方法及区块链建模进行研究,提出了账户 区块链(account blockchain,简称ABC)和交易区块链(trading blockchain,简称TBC)的双链设计模型.对智能合约进行 深入剖析,提出了链上代码并行执行模型...
  • Java区块链投票系统开发实战分享

    千次阅读 2021-05-27 09:52:51
    基于Java语言以及目前市面上流行的Springboot+Mybatis等框架开发区块链投票系统,可用于企业集团、政府机构、组织联盟内的投票平台,系统分为三层架构,分别是自研区块链作为底层、投票系统作为业务层、前端操作...
  • 整体上,分为三个步骤,安装相关软件,初始化系统,建立集群,以及最后一步,挖矿。 我们采用的是以太坊,相对其他区块链,这是一个成熟的环境。 虽然近期有硬分支的事件,对企业应用来说,功能上还算是比较完善的...
  • 经过前面文章介绍,已经搭建以太坊的区块链环境,但是没有一个界面能查看到区块链的块数等信息,不是很直观,本篇搭建以太坊区块链浏览器。 下载区块链浏览器代码 uiran@cuiran:~/ethereum$ git clone ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 52,437
精华内容 20,974
关键字:

区块链系统开发