主页 > imtoken官网安卓下载 > 谈谈区块链中的几个技术点
谈谈区块链中的几个技术点
作者:0x7F@知道创宇404Lab 时间:2020-01-09
原版的:
随着科技浪潮的涌动和国家政策的推动,区块链慢慢进入了我们的视野。 2020年初此时此刻,让我们回顾一下区块链的发展历程,谈谈区块链的几个技术点,为新的一年打下基础。
2017 年是数据货币爆发的一年。 其标志性事件是2017年12月比特币价格创历史新高,区块链进入大众视野; 因此,2018年被称为区块链元年,各种与区块链相关的数字货币和技术在互联网上如雨后春笋般涌现; 后来,随着区块链监管力度的加大,2019年对于区块链来说是沉寂的一年,终于通过了考验,都是有价值的区块链项目。
所以在本文中,我们将把数字货币放在一边,只从区块链的角度来谈; 该文章使用比特币 v0.19.x(提交:
0655c7a94cc9bf54d43eceed805e83f1b59e2409)源代码帮助理解。
区块链随着比特币的诞生而诞生,最早出现在比特币的白皮书中(
), 用于存储比特币交易记录; 在比特币中关于比特币的问题及回答,多条交易记录按照时间序列集中存储,形成区块,区块之间通过哈希值连接起来,形成链式结构。 我们将这种结构称为区块链。
在比特币中,多个节点通过P2P网络共同维护一条区块链,使得这种链式结构具有去中心化、不可篡改、可追溯等特点。 后续的以太坊、Hyperledger等项目也是基于这种链式结构。
这里我们抛开数字货币,以区块链为主角。 我们可以更容易理解区块链:区块链是一个基于P2P的分布式数据库,多个节点共同维护一份数据; 那么从这个角度来说,比特币区块链中存储的“交易记录”也是数据,只是数据比较特殊。
我们可以把区块链看做是一个基于P2P的分布式数据库,因为区块链和分布式数据库有着相似的目标:使用多个节点共同维护一份数据。
但是我们只是把它理解为一种“存储”的操作,而忽略了它们自身的应用场景。 默认情况下,所有节点都是可信的、可靠的、无延迟通信等。在实际环境中,我们需要考虑以上因素,所以区块链不能等同于分布式存储数据库。
我们使用该表来比较区块链和分布式数据库:
区块链分布式数据库
架构分布式分布式
价值主张 数字信任系统 高性能存储和访问
网络通信点对点客户端服务器
管理模式 集中管理 分散管理
数据结构链式索引等
节点关系 怀疑与约束 信任与协作
Consensus共识算法主从复制
数据持久性数据不可变可修改和非持久性
低性能
了解了区块链和分布式存储数据库的异同之后,我们可以知道,分布式存储数据库和区块链都需要解决分布式问题; 而区块链也需要解决其特有的问题。 所以我们以分布式存储数据库为基础,帮助我们理解区块链涉及的技术点。
1. FLP不可能原理 针对分布式系统中的不确定性,Fischer、Lynch和Patterson三位科学家在1985年发表论文提出FLP不可能原理:在一个可靠的网络中,但允许节点失效(即使只有一个)在最小化异步模型系统中,不存在可以解决一致性问题的确定性算法。
所以理论上一致性问题没有完美的解决方案,但是在工程应用中,我们可以选择牺牲一些特性来换取可行的解决方案。
2. CAP原则那么我们应该如何选择价格来换取这个可行方案呢? 2000年,Eric Brewer教授在ACM组织的一次研讨会上提出CAP原则:分布式系统不可能同时保证以下三个特性:一致性(Consistency)、可用性(Availability)和分区容错性(Partition) ,在设计中往往需要弱化对某个特性的保证。
根据CAP原则,我们可以根据不同的需求选择三种特征。 例如,访问分布式网站的静态内容可以接受延迟的数据更新,这削弱了一致性; 而在区块链中,即使以牺牲性能为代价,也只能保证一个被识别的数据,这削弱了可用性。
3. 拜占庭容错 在分布式数据库中,节点相互信任,忠诚。 他们可能离线或宕机,但他们绝不会发送错误信息; 所以我们可以信任任何一个节点,分布式数据库往往采用“主从复制”来实现一致性,即选择一个节点作为主节点,其他节点从这个节点复制数据。 如果节点出现故障,则重新选择一个新的主节点。
在区块链中,节点自由加入和退出,可能会出现恶意节点:节点可能离线、宕机、发送错误消息,破坏数据的一致性; 这通常被认为是拜占庭将军的问题。
这是 1980 年代提出的假设性问题。 它描述:“一群拜占庭将军各率一支军队一起围攻一座城市。由于每支军队都在城市的不同方向,他们只能通过使者进行沟通;军队的行动策略仅限于进攻或撤退部分军队进攻,部分军队撤退,可能会造成灾难性的后果,因此,所有将军必须通过投票达成一致的策略;每个将军都会通过信使将自己的投票信息通知其他将军,让每个将军都知道结果根据自己的投票结果和其他所有将领传来的信息来决定行动策略。”
上图中,叛军发送错误的投票信息导致的不一致问题被称为“拜占庭错误”,而能够处理拜占庭错误的方法被称为“拜占庭容错”。 那么在区块链中是如何解决的呢?
PBFT算法 PBFT(Practical Byzantine Fault Tolerance)算法主要是为了解决拜占庭错误而提出的。 它的算法核心是三个阶段:pre-prepare stage(预准备阶段)、prepare stage(准备阶段)、commit stage(提交阶段),我们通过下图来理解算法。
其中,C代表请求客户端,0123代表服务节点,3个节点故障,f代表故障节点个数。
C 向节点0发起请求,节点0将请求广播给其他服务节点。 节点收到预准备消息后,可以选择接受或拒绝该消息。 收到消息后,将准备消息广播给其他服务节点。 当一个节点在prepare阶段并且收到2f条prepare消息后,进入commit阶段,将commit消息广播给其他服务节点。 当一个节点处于提交阶段,收到2f+1条提交消息(包括自己),当C客户端收到f+1条回复消息后,表示共识已经完成
PBFT 的节点数必须满足 N >= 3f+1 的关系。 只要节点中故障节点的数量不超过1/3,就可以完成共识确定一致性。 由于 PBFT 算法的特点和性能问题,常用于小型联盟链。
PoW算法 PoW(Proof of Work)算法在比特币中使用,即工作量证明算法。 其算法的核心是通过复杂的数学计算来竞争加入区块的机会,结合“劣势原则”,只认可最长链为合法链的规则来完成节点共识。
在比特币中,PoW 的工作原理如下:
用户发起交易,节点将交易广播给所有节点。 节点收到交易包,放入区块。 某个节点计算哈希结果并获得添加区块的机会,将2中的区块添加到区块链中。 节点收到新的区块信息后,会验证该区块的合法性关于比特币的问题及回答,合法后加入区块链末尾,进入下一轮竞争
通过PoW算法,比特币可以允许全网50%的节点出错,仍然能够完成共识。
PoW 算法位于区块生成模块(挖矿)中。 我们先来看看比特币的启动过程。 Bitcoin程序的入口位于bitcoind.cpp下,通过这样一条调用链启动Bitcoin中的各种服务:
main->AppInit->AppInitMain
这包括 RPC 服务。 在比特币中,我们需要使用bitcoin-cli通过RPC服务开始挖掘,最后到
rpc/mining.cpp/generateBlocks 这个块生成主要逻辑:
其中pow.cpp/CheckProofOfWork函数对PoW算法进行验证,主要判断区块哈希值是否小于当前nonce值下的难度值:
其他的,但由于PoW算法性能不佳,浪费了大量算力,人们提出了新的共识算法,如PoS(权益证明)、DPoS(委托利益相关者证明机制)等; 从一半的区块链项目来看,PoW 仍然是使用最广泛的共识算法。
了解了共识算法后,我们就可以保证数据的一致性,那么这些数据是如何存储在区块链中的呢?
Merkle 树 在比特币中,Merkle 树用于组织和存储区块中的交易信息。 它是一棵基于散列的二叉树(或多叉树),其结构如下:
叶子节点存储数据 非叶子节点存储其子节点内容的哈希值
使用 Merkle 树的优点是:
快速比对大量数据,比较根节点的哈希值就知道两组数据是否相同
快速定位修改,子节点的任何变化都会传递给根节点,从根节点往下查找就可以找到修改的节点。
Merkle 树是在比特币中实现的,Merkle 树的生成是挖矿步骤中的一个子步骤,它遵循上面的区块生成过程。
在miner.cpp/IncrementExtraNonce函数中,调用这个函数
consensus/merkle.cpp/BlockMerkleRoot 函数构建默克尔树:
在一个区块中,哈希链不仅包括打包成默克尔树的交易信息,还包括区块高度、随机数、时间等信息,其中父区块的哈希值将每个区块链接起来形成一条链结构,如下:
在比特币中,一个区块由区块头和 Merkle 交易树组成。 块头数据结构定义在primitives/block.h中,如下:
那么在区块链中,节点之间如何传递数据呢? 与采用主从复制同步数据的分布式数据库服务器-客户端网络结构相比,区块链是一种点对点的网络结构。 节点在获取数据的同时需要向其他节点提供数据。
我们直接看一下p2p协议在比特币中的实现。
在比特币中,默认在8333端口建立了一个tcp监听器,并启动了p2p服务。 在bitcoind启动过程的init.cpp/AppInitMain中,初始化并启动网络:
[init.cpp/AppInitMain()] 1.node.connman->Start 启动节点入口,网络初始化和建立 [net.cpp/Start()] 2.InitBinds 建立网络监听 3.AddOneShot 添加种子节点 4.&TraceThread...... 启动五个网络处理线程
p2p网络处理流程负责这五个线程:
负责p2p协议处理的线程是ThreadMessageHandler线程。 下面主要看这部分的流程; 在本线程中尝试接收各个节点的数据,接收到数据后的调用过程如下:
[net_processing.cpp] ProcessMessages->ProcessMessage
判断ProcessMessages中的协议格式,比特币中的p2p协议格式如下:
然后输入 ProcessMessage 进行实际的消息处理流程。 该函数中的主要逻辑是多个if-else语句根据命令进入不同消息的处理流程。 支持的消息是:
每个命令都有不同的消息格式和处理逻辑。 这样,比特币打通了节点之间的通道。
通过这篇文章,我们在脱离数字货币的情况下,从分布式数据库的角度谈了区块链的几个技术点,了解了区块链与传统分布式的异同,也了解了区块链。 链中的基本概念和原则。
区块链的去中心化、不可篡改的特点为我们提供了无限的想象空间,但目前还没有公开完整的区块链项目,希望这一天早点到来。
参考:
1.《区块链技术指南》
2.《白话区块链》
3.《区块链原理、设计与应用》
4.
5.
6.
7.
8.
9.
10. %E6%8B%9C%E5%8D%A0%E5%BA%AD%E5%B0%86%E5%86%9B%E9%97%AE%E9%A2%98
11.