浅谈区块链(二):技术篇

上一篇文章对区块链进行了简介,如果只是考虑怎么用区块链,看完上一篇就可以了。但如果希望继续钻研区块链技术的实际落地,还必须对区块链技术加深了解,本篇将会介绍区块链的一些关键技术,可以作为一个技术方面的入门材料来看。

浅谈区块链(二):技术篇

1、哈希函数

哈希函数,又叫散列函数、散列算法,是一种从任何一种数据中创建小的数字“指纹”(也叫做摘要)的方法。给出任意内容的数据,通过哈希函数都能生成一个固定长度、固定格式的哈希值,同样内容的数据所生成的哈希值必定相同,不同内容的数据所生成的哈希值必定不同(理论上会有相同的可能性,但是概率超低,因此在应用时可以认定为不会发生)。此外哈希函数的算法是不可逆的,也就是通过所生成的哈希值没有办法推算出原文。

常用的哈希函数算法为SHA(Secure Hash Algorithm),是是由美国国家安全局研发,由美国国家标准与技术研究院(NIST)发布的一系列密码哈希函数,比特币所使用的哈希函数算法为SHA-256。

浅谈区块链(二):技术篇

区块链技术中大量应用了哈希函数的特点,主要有几个方面:

(1)快速验证数据是否一致,比如比较两个数据是否一致,不用比较完整的数据,只要比较两个数据所生成的哈希值是否一致即可;

(2)保护用户的密钥,在区块链的公钥和私钥使用都会通过哈希值进行转换后再进行对比,因此不会暴露密钥信息;

(3)防止数据篡改,区块链上的每个区块数据都会通过哈希函数生成一个唯一的哈希值,如果区块内数据被修改,则区块的哈希值将与原来的哈希值不一致,通过比较可以防止数据被后续篡改;

(4)用于POW共识算法的工作量证明,俗称挖矿,通过计算资源不停尝试找符合给定哈希值规则的数据,谁先找到谁就拥有区块的记账权。

2、P2P网络

区块链具有不确定的节点数量,但又要实现所有节点之间的相互通讯,因此需要使用P2P网络技术实现节点之间的发现和通讯。从通讯协议角度,可以根据具体区块链的实现自行选择(例如选择gRPC作为通讯协议)。实际上P2P网络最大的问题是在无中心服务器的情况下,如何发现周边的节点,目前普遍基于 DHT(Distributed Hash Table,分布式哈希表)来实现节点的发现。

DHT是P2P网络(结构化P2P)核心路由算法,主要是利用一致性hash,把节点和资源都表示成一个hash值,放入到这个大的hash环中,每个节点负责路由靠近它的资源。连入DHT网络的用户叫做节点(node),节点之间互相有路由记录,因此只要和任何一个已经在DHT网络中的节点连接上,客户端就可以寻找到更多的节点,从而连入网络。

浅谈区块链(二):技术篇

这里不详细说明DHT网络的具体算法,仅用浅显的描述说明DHT网络的大致发现原理:

(1)网络中的每个节点(客户端,具有唯一IP)都会存储着一个路由表,登记节点已知的其他节点信息(IP、所存储的资源hash);

(2)一个节点需要获取某个资源时,先查本地路由,看是否能找到资源所在节点;如果找不到资源,则依次向离自己最近的节点(在本地路由表获取)查询路由信息并更新本地路由(通过遍历可以不停增加DHT节点路由及查找到最近的资源位置);

(3)新节点在刚开始没有本地路由怎么办?一是通过别人发布的种子文件获取到初始的DHT路由信息;二是连接上自己默认设置的超级节点服务器获取初始路由。

3、链式存储结构

区块链的最为显著的特征是其存储结构,区块链上的交易数据存储在一个个区块中,每个区块头都会记录上一个区块的哈希值,通过这个哈希值将所有区块连接为一个串联的链式结构,这也是区块链的名称由来。

所有的交易数据都是记录在区块体中,但需要注意的是,整个区块是一次性写入的,也就是已经通过验证的区块数据,是不可以被修改的,不能改交易,也不能添加交易。区块的写入也不是每个节点都有权利的,必须由具备记账权的节点(矿工)负责,矿工通过区块链的共识机制竞争记账权,获取到记账权的矿工会将申请的交易打包写入最新的区块中。

4、Merkle树

在区块链网络上,并不是所有的节点都包含了全网所有的数据,存在一种SPV(Simplified Payment Verification)节点,SPV节点没有存储全网的区块链区块体数据,只存储全链区块头,这就类似于书架上没有存所有的书的内容,但是存储了所有的书的章节目录。我们的手机/pad/电脑上安装的很多钱包软件都属于SPV节点。

但是SPV节点需要进行交易时,需要能快速验证交易数据真实性(也就是存储在全节点上区块体数据的真实性),可以通过Merkle树实现。

Merkle树的生成方式如上图所示,假设区块体有7笔交易数据,分别用Ta – Tg表示,生成步骤从图的下方向上,说明如下:

(1)先对每笔交易生成对应的哈希值,分别表示为Ha – Hg;

(2)对Ha – Hg按顺序每两个拼接成一个字符串并生成哈希值,分别表示为Hab、Hcd、……等;注意由于交易数为单数,最后一个交易Hg自己和自己拼接产生哈希值,表示为Hgg;

(3)同理对Hab、Hcd、……等按顺序每两个拼接起来生成哈希值,分布表示为Habcd、Hefgg;

(4)最后将Habcd、Hefgg拼接起来生成哈希 值,就是Merkle树根Habcdefgg。

对于SPV节点,由于只有区块头数据,当遇到需要校验Td数据的真实性时,可以按下图所示进行校验:

SPV节点的处理步骤如下:

(1)将要验证的Td生成Hd;

(2)从网络上的某个全节点获取Hc、Hab、Hefgg的哈希值(由全节点计算得出);

(3)按Merkle树的生成规则,组合Hc、Hd、Hab、Heffg,生成校验数据的Merkle树根哈希值;

(4)将校验Merkle树根值与区块头的Merkle树根值比较,如果一致则说明交易真实。

通过Merkle树的方式,可以大幅减少SPV节点和全节点的传输数据量(无需传输实际的交易数据),快速实现交易真实性的校验。

5、共识机制

所谓“共识机制”,就是区块链网络通过特殊节点的投票,在很短的时间内完成对交易的验证和确认;当出现意见不一致时,在没有中心控制的情况下,若干个节点参与决策达成共识,即在互相没有信任基础的个体之间如何建立信任关系。在没有中心节点的情况下,区块链依赖共识机制来确认某个节点的记账权,只有有记账权的节点才可以在链上写入新的区块。

区块链共识机制主要有以下几种:PoW工作量证明、PoS股权证明、DPoS授权股权证明、Paxos、PBFT(实用拜占庭容错算法)、dBFT、DAG(有向无环图)。不同的区块链应用根据需要可以选择使用不同的共识机制,以比特币为例,其共识机制采用的是PoW工作量证明的模式,我们来简单介绍一下这个机制。

工作量证明机制(PoW, Proof of work )的概念是提供一份证明,用来确认你做过一定量的工作,通过对工作的结果进行认证来证明完成了相应的工作量。对于比特币来说,就是通过计算机的算力来争夺下一个区块的记账权,如果最先计算到匹配任务哈希值,就能得到记账权并完成记账,这时系统会奖励一定数量的比特币给记账方,这个过程也俗称挖矿。

我们以比特币的一个区块确认过程来简单说明一下该共识机制:

(1)用户向一个或几个矿工节点发起一笔交易的请求;矿工们立即确认收到了这笔交易(一般在毫秒级别左右);

(2)这笔交易被广播到了全网(视参与节点数,可能广播时间会有几秒的时长);

(3)矿工将收到的交易打包进自己的区块中,开始进行挖矿(争夺记账权),大致说明如下:

  • 设置区块头的Nonce值为1
  • 计算区块头的哈希值:sha256(区块头)
  • 判断是否满足难度要求(哈希值的前n位是否为0,n就是难度系数),如果满足则代表获取到记账权;如果不满足则将Nonce值加1,循环计算区块头哈希值和判断的过程

以下为一个满足难度系统为8的哈希值示例:

00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09

(4)挖到矿的矿工将区块写入自己的节点,并向全网广播,由全网节点进行验证和确认;

(5)当有51%的节点确认后,该区块正式生效。

6、区块链的分叉

区块链中当出现同时写两个块(比如两个矿工同时挖到矿),或因为协议版本升级导致节点版本不一致的情况,都有可能产生两个或多个块的上一节点为同一个节点的情况,这就是链的分叉。当区块链出现分叉的时候,一般都会选择后续链路长的作为正式的链,而放弃链路短的链。

(1)因为节点判断机制或版本不一致,两个节点都认为自己要写入的块是有效的,导致块C后同时写入了D和E两个块;

浅谈区块链(二):技术篇

(2)D和E会分别向自己临近的节点进行广播:“我是新生成的区块!把我记录进去!” 在此基础上,D和E块后面都有可能开始生成新的区块;

浅谈区块链(二):技术篇

(3)很快会有一个区块N先后收到D和E的广播,发现D和E拥有同样的时间戳,那么区块N就会判断,选择其中一个为有效区块,另外一个为无效区块:此时D区块的基础上已经产生了3个新区块,但是E区块基础上只产生了1个新区块,此时区块N就会向其他节点广播:“D跟E虽然是同时生成的,但是D基础上的链更长,所以D有效E无效。”

以比特币为例,新节点总是采用最长的那条区块链。如果区块链有分叉,将看哪个分支在分叉点后面,先达到6个新区块(称为”六次确认”)。按照10分钟一个区块计算,一小时就可以确认。

浅谈区块链(二):技术篇

注:根据这种分叉确认规则,一笔交易无法实时确认是否真正完成及有效,后续有可能收到交易无效的广播通知。

7、UTXO数据格式(Unspent Transaction Output)

区块链中的区块体存储的是具体的交易数据,区块体的数据存储结构应根据实际的业务场景进行设计,包括是否明文存储、交易验证信息等。不过在数字货币的应用中,一般不会采取传统的“账号+余额”的数据结构设计。

以比特币为例说明,区块体中只存储交易数据,无需存储账户余额。交易所及钱包里显示的比特币实际上是UTXO,全称为Unspent Transaction Output,翻译过来就是未被花费的交易输出。在比特币区块链账本上记录了一笔一笔的交易,每一笔交易都有若干个交易输入(转账者),也就是资金来源,同时也有若干个交易输出(收款者),也就是资金去向。每一笔交易都要花费一笔输入,产生一笔输出,而产生的这笔输出,就是UTXO。

浅谈区块链(二):技术篇

上图是UTXO的数据格式示例,其中:

(1)#vin是交易输入数组,传入要消费的“未被花费交易输出”,关键字段说明如下:

  • hash:该笔“未被花费交易输出”所对应的输入所在交易(TxPrev)的hash id
  • n:该笔输出在TxPrev的#vout中的索引位置(第几个,从0开始)
  • scriptSig: 解锁脚本,包含付款人用私钥对本次交易数据的签名(Sign)和付款人公钥(Pubkey)

(2)#vout是交易输出数组,传入具体交易输出信息,关键字段说明如下:

  • nValue: 交易输出金额
  • scriptPubkey: 锁定脚本,包含命令(OP_DUP等)和收款人的公钥哈希(<PubKHash(B)>,实际上就是收款人地址)

比特币并不是基于账户的方案,而是基于UTXO方案。这个和传统银行账户的思维完全不一样。张三拥有10个btc,其实就是当前区块链账本中,有若干笔交易的输出(UTXO)收款人都是张三的地址且并未使用(未成为其他交易的输入),而这些UXTO的总额为10。这个地址一共收了多少UTXO,则是要通过比特币钱包代为跟踪计算,所以钱包里显示的余额其实是有多少价值btc的输出指向你的地址。

以下是一个比特币交易的示例,可以帮助理解UTXO的处理机制:

浅谈区块链(二):技术篇

(1)第一个交易#1001号是张三挖矿所得的coinbase交易,coinbase交易就是挖矿交易,当矿机找到一个合格的区块后,它就获得一个特权,能创造一个coinbase交易,并且把交易输出写上自己的地址,张三通过挖矿获得了12.5个btc,即价值12.5个btc的UTXO指向的是他的地址;

(2)第二个交易张三转账2.5个btc给李四,张三就发起了#2001号交易,资金的输入为#1001(1),而在本次交易输出的UTXO中,把2.5个btc的收款人地址为李四。但是这笔交易必须把上一个UTXO全部消耗,所以还剩下的10btc的交易输出的收款地址为张三自己。

注意:在比特币交易中 UTXO 就是基本单位,一个UTXO一旦被创建就不可被继续分割,它只能当作是下一笔交易的输入被花费掉,花费后产生新的UTXO。

(3)第三个交易张三和李四一起转给王五5个btc,张三或李四发起#3001号交易,输入来源有两个部分,一个是#2001(1)和#2001(2),输出为王五的收款地址。并且张三还剩下的7.5个btc输出到自己的地址。后续王五如果需要花费他的5个btc,输入就需要为#3001(1)。

后记:上面介绍的是区块链比较关键的技术原理,了解了这些原理,你应该就可以装成区块链的伪专家,忽悠一下小白,或者和真正的区块链专家进行简单对话。区块链中的每项技术还有大量设计在文章里没有具体说明,不过本人对区块链的认识也就局限于此,有志于从事区块链行业的朋友可以继续深入研究。

相关阅读:

浅谈区块链(一):应用篇

业界动态

从爆款打造,谈如何设计页面来驱动用户转化?

2021-3-17 10:38:47

业界动态

做项目如何带团队?年入200万的人是如何带团队的?

2021-3-17 10:41:05

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索