区块链技术基础
什么是区块链技术?
- 运行区块链客户端的计算节点彼此可以相互通信。
- 每个节点维护一个账本。
- 每个节点的收支记录都会广播给其他节点。
- 筛选出一个节点作为一段时间的总记录。
- 其它节点接收该被选中的节点的记录,和自己账本对照后,没有问题则进行存储。
- 被选中的节点会因为这段时间付出的劳动而获得一定的报酬。
- 节点通过非对称加密的公钥来表示身份,通过加密来传递数据。
区块链的组成模块
- 区块链账本。区块链账本用来记录数据,区块分为区块头和区块体,区块头会存储上一个区块的哈希值,这样各个区块就串联起来,区块头通过梅克尔根关联记录的交易事务。如果修改链中的某个数据块,则会导致该数据块无法链入区块链账本,在其它节点中验证时会被发现,所以区块链账本可以防止对数据的篡改。
- 共识机制。一种筛选算法,可以选出特定的节点,该节点会作为大家对账的参考。
- 密码算法。其中包括,计算区块hash值得算法,计算区块中交易事务的hash值和梅克尔根的算法,创建账户、签名交易的算法等。
- 脚本系统。脚本系统驱动着节点收发数据,通过实现不同功能的脚本来实现不同的业务。
- 网络路由。在由这些节点组成的网络中,没有固定节点路由服务器,所以每个节点都起到了路由服务者和使用者的角色,通过路由进行数据的交换。
什么是挖矿
挖矿就是竞争获得区块的打包权,通过计算打包获得报酬。
什么是难度值?
难度值描述了获得打包权的门槛,计算所得结果要小于该难度值才有机会获得打包权,每段时间整个系统会更新难度值,保持10分钟就能计算出一个区块的速度。
初始难度值很大,很容易竞争获得,如下是0号区块链的难度值:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
值越大越容易满足,随着计算能力提升,为了保持每10分钟创建一个区块的速度,值会逐渐减小,也越来越难满足。初始难度值表述信息如下,bits
是上述值的压缩值,可以通过0x00FFFF*2^(8*(0x1D-3)
恢复上述值(近似值)。将0号区块的难度作为1,当前difficulty为初始难度值除以当前难度值:
"nonce": 2083236893,
"bits": "1d00ffff",
"difficulty": 1
如何获得打包权?
每笔交易都会通过广播的形式发送给其它节点,所以计算节点会拉取一段时间内缓存的交易记录,然后采用如下公式计算:
SHA256(SHA256(version + prev_ hash + merkle_ root + ntime + nbits + nonce)) < TARGET
如果计算出的值小于TARGET,也就是目标难度值,就算成功了。参数解释如下:
名称 | 含义 | 描述 |
---|---|---|
version | 区块的版本号 | 固定值 |
prev_hash | 前一个区块的hash值 | 固定值 |
merkle_root | 准备打包的交易事务hash树的根值,也就是梅克尔根值 | 可变的,由获取的交易事务决定的,获取交易事务也是有一定优先级规则的,比如根据手续费大小 |
ntime | 区块时间戳 | 要大于前11个区块的平均时间戳,不得超过当前网络时间2个小时,可能小于前一个区块的时间戳 |
nbits | 当前难度值 | 固定值 |
nonce | 随机数 | 0~2^32的数值 |
想要小于目标难度值,需要不断的尝试各种参数组合,这个过程消耗大量计算资源。一旦计算成功,就会广播新的区块,其它客户端验证通过后会写到自己的区块链账本中。
什么是挖矿?
当获得打包权后,整个区块链系统会给予该客户端账户一定的奖励,这个奖励就是打包的交易事务的第一条记录,这个奖励相当于发行新的货币。整个比特币的数目是有限的,每隔4年奖励的比特币减半,真到2140年所有的比特币将被挖完,到时挖矿的收入来源为交易的手续费。
多个节点符合条件这么办?
如果同时多个节点计算出符合条件的区块,则会一起广播,最后传播最广,处于最长链中的区块将会被保留。
比特币地址如何生成
- 随机数生成器产生一个随机数作为私钥。
- 私钥作为参数,用SECP256K1算法生成公钥,SECP256K1算法是一种椭圆曲线算法。但是无法从公钥计算出私钥。
- 计算公钥哈希值。通过SHA256和RIPEMD160计算公钥的哈希值,确保数值的唯一性。
- 将地址版本号连接到公钥哈希值,比特网主版本号为0x00,然后两次SHA256取得前四个字节作为校验值。
- 将版本号+公钥哈希值+校验值连接起来,进行BASE58编码,最后得到比特币地址。
比特币如何验证一个交易
SPV钱包的验证过程:
- 下载完整的区块链头数据,头数据中包含梅克尔根。
- 计算出想要验证交易的哈希值。
- 根据哈希值找到对应的区块头。
- 获取计算梅克尔根所需要的哈希值。
- 计算梅克尔根。
- 对照梅克尔根是否正确。
- 根据所在区块高度位置,可以确定该交易得到了多少确认。
比特币如何管理交易记录
比特币中交易事务的模型为UTXO(Unspent Transaction Output),未花费事务输出。用户拥有的UTXO相当于他的资产,UTXO只记录用户获得的比特币,一个未花费事务输出只能被使用一次。
一笔交易分为输入和输出。在A转10个比特币给B的事务中,整个模型运转如下:
- A账户有两个UTXO,分别是5个比特币和6个比特币。
- A找出自己名下满足10个比特币的UTXO,可以由多个未花费事务组成(5+6),这些UTXO作为输入。
- 输出则是B获得10个比特币的UTXO,A获得1个比特币(找零)的UTXO。
区块链技术的意义
- 数据不可篡改。
- 分布式存储,数据在多地存有备份。
- 匿名性。通过地址来标识用户,而地址是通过公钥生成,所以仅仅通过该地址无法获取其背后的真实用户。
- 价值专递。自成体系的信任机制,工作量表明比特币是有价值的,比特币可以在任何比特币节点传递。
- 自动网络共识。一个交易被其它所有节点见证,自动的达成了共识。
区块链的发展
什么是合约?
合约是大家行为的共同准则,少数人的不守约对整个系统不造成影响。
在比特币中,所有节点都遵循合约来处理每笔转账交易。比如A将100比特币转账给B,则A所在节点需要验证使用的UTXO是否属于A,并且保证里面有足够的钱给B,然后将该交易记录广播给其它所有节点,其它节点会验证A用作输入的UTXO是属于A的,且真实存在的(查看交易记录签名),并且这笔转账输入和输出是持平的,验证成功后才将该交易记录进区块链。如果部分节点没有按照上述过程转账和验证,但是整个系统最终会保证结果的正确。
密码算法
哈希计算
哈希计算的特性:
- 输入长度是任意长度
- 输出是固定长度
- 计算过程是有效率的
哈希函数为了满足密码学上的安全性,需要满足如下条件:
- 抗冲突。两个不同的输入产生了相同的输出,这就产生了冲突。为了满足安全性,哈希函数需要保证找出两个输出相同的输入是很困难的,需要付出很大的时间代价。
- 信息隐藏。获得了哈希函数的输出,不能倒推出输入。
- 难题友好性。在已知结果需要满足的条件下,很难找出输入满足该条件。
常见的哈希算法:MD5,SHA1,SHA2,SHA3。
区块链中用到的哈希计算:
- 区块链哈希。区块链中会对区块头进行哈希计算,得出该区块的哈希值。该哈希值会作为下一个区块的一部分被保存,所以该哈希值起到了一个指针的作用,将各个区块链接起来。这保证了每个区块被加入链后不可被修改。
- 梅克尔树。梅克尔根用来验证区块中交易记录是否正确。比特币中的梅克尔根是一个二叉梅克尔树,首先对交易事务的哈希值两两结对计算出新的哈希值,然后将新的哈希值两两结对计算出下一个哈希值,依次递归,只到算出最后一个哈希值,从而构成了一个哈希树。梅克尔树可以验证交易记录的完整性。
非对称加密算法
常用的非对称加密算法:
- RSA。RSA算法的公钥和私钥是一对大质数,从公钥和密文恢复明文的难度等价于分解两个大质数之积,质数越大破解难度越大。但是计算速度较慢。
- 椭圆曲线密码算法。安全性高、生成公钥方便,存储空间小。比特币中使用的是SECP256k1算法。
编码解码算法
- ASCII编码。常用的字节编码。
- Base64编码。用64个字符来表示二进制文件,所以每3个字节被表示为4个字符,不足3个字节的补x00。
- Base58编码。去掉了Base64中一些容易混淆,如0,O,I,1和容易转义的+、/。
- Base58Check。在Base58的基础上加上了校验码,比特币在生成地址时最后就采用了Base58check,可以在接收到地址时进行校验,如果计算出的校验值和接收到的校验值不同,则认为数据无效。
密码算法具体的应用
- 生成账户地址。利用公钥生成地址和作为账号,用私钥验证账号。
- 价值转移保卫。用私钥签名交易,他人用公钥验证交易是本人发出。用他人公钥加密交易数据,只有接受者才能解密数据。
- 完整性证明。通过哈系数来校验区块数据。
- 零知识证明。为了证明自己对某笔交易的所有权,只需要解码交易中部分内容,就能证明所有权,而不需要提交自己的密码来验证。
共识算法
FLP定理(信道可靠,节点失效)
在网络可靠,存在节点失败的最小化异步模型中,不存在可以解决一致性问题的确定算法。
CAP定理
分布式计算不可能同时保证一致性、可用性和分区容错性。
- 一致性。所有节点在同一时刻,所处状态相同。
- 可用性。系统可以正常被访问。
- 分区容错性。因为网络故障导致节点被划分为不可联通的几块,但系统仍能正常使用。
两军问题(信道不可靠)
A->B<-C
A和C需要联合攻击B才能取得胜利,所以双方需要约定一个确定的时间发起进攻,两方的信使都需要经过B,所以信使可能被B截获。A发送消息给C,C需要发送确认告诉A消息到达,如果不发送确认,A同样会认为消息被B截获;同样,A收到C的确认后,同样需要发送确认消息给C,否则C会认为消息被B截获。如此往复,导致A和C无法达到最终的一致。
两军问题的关键点在于两点之间的信道传输不可靠。
拜占庭将军问题(信道可靠,节点不失效,节点产生错误数据)
N个将军通过传令兵传递消息,并且需要达成一致的计划,但是这N个将军中存在叛徒,会故意发送假的消息来扰乱计划。已经证明,如果背叛的将军超过了1/3,则不可能达成一致的计划。
如何实现共识
既然保证一致性存在上述问题,那么如何实现一套实际可用的的共识算法?
激励机制:采用一定的激励机制,依据博弈论,每个节点会最大化自己的利益,最后大部分节点会依照规则行事。
随机性:拜占庭问题是每个将军通过协调达到一致,如果有一个大将军做出最后决定,那么问题就会简单很多。在去中心化的系统中,如何选出这个“大将军”呢?
- 根据计算力,PoW共识。
- 根据资源,PoS共识。
常用的共识算法:
- PoW。如,比特币。
- PoS。如,PeerCoin。
- DPoS。
- Paxos。如,ZooKeeper。
- PBFT。
- Raft。如,etcd。
以下是对部分共识算法的简单介绍。
Paxos算法
Paxos算法解决的是非拜占庭问题,存在失败节点,但没有恶意节点。
算法分为提案者、接收者。提案者发出提案,由接收者投票,超过半数则认为提案通过。
在处理多个提案者、多个接收者场景的时候,采用了“两阶段提交”的方案:准备阶段解决对哪个提案做出表决,提交阶段确认提案是否通过。
Raft算法
该算法通过选出一个“大将军”角色的方式来解决一致性问题。容错数目为(n-1)/2。
- 没有“大将军”时会发起选举,每个人进行投票,票数居多的成为“大将军”。
- 出现平票时选举失败,每人被分配一个随机的睡眠时间,睡眠者只能投票,无法被选举。第一个醒的人会发起新一轮的选举。
- 被选出的“大将军”和每个人保持心跳,一旦“大将军”失效,则需要进行新的选举。
- 由“大将军”负责下发指令,村长收到上级指令后会向所有人发送指令,等接收到超过半数的反馈后,“大将军”向上级确认数据已经接收。“大将军”接收到上级的响应后,会通知所有人数据已提交。
PBFT算法
Pbft算法的基本流程主要有以下四步,f表示错误节点数目。容错数目为n/3。
- 客户端发送请求给主节点。主节点为随机挑选出来的。
- 主节点广播请求给其它节点,节点执行 pbft 算法的三阶段共识流程。
- 节点处理完三阶段流程后,返回消息给客户端。
- 客户端收到来自f+1个节点的相同消息后,代表共识已经正确完成。
PBFT算法多应用于联盟链中,它达成共识的延时为秒级,基本满足商业要求。
PoW工作量证明算法
算法流程:
- 向所有节点广播交易;
- 每个节点收到交易信息并放入块中;
- 每一轮,获得打包权的节点广播它保留的块;
- 其它节点验证块中的交易无误后接收该区块;
- 其它节点将接收的区块的哈希值放入他们创建的区块中,以表示承认该区块的正确性。
节点以最长的链为合法的链。节点在收到一个他人的区块后可以选择拒绝,或者基于该区块继续挖矿。如果选择拒绝,则不得不自己计算出一个正确的区块,但是会导致该自己另起炉灶的链不会长于主流的链,所以自己构造的链不会得到承认;根据“不利原理”,节点会积极的接收其他人广播的区块,并且基于该区块接着挖矿。
PoW的特点:
- 完全去中心化;
- 性能消耗高,效率低;
- 达成共识的周期较长;
- 1/2的容错率。
PoS股权权益证明
PoS不像PoW,任何人都可以参与产生区块,而是事前需要投入一些利益在区块链中,投入越多则越被信任。整个流程如下:
- 加入PoS机制的成为持币人,成为验证者validator;
- 根据持币的多少挑选一个给予打包区块的权利;
- 如果没有在规定时间内计算出新的区块,则选择下一个节点给予打包权;
- 打包成功后进行广播,被大家接受后可以获得一定的利息,这个利息通过持币数量和币龄决定,每次打包成功后,会清零币龄。
DPoS
委托权益人证明机制(Delegated Proof of Stake),在PoS的基础上进行了改造,每个持币人可以选出代表来代替自己计算、验证区块链,代表因此会收到一定的酬劳,代表可以主动退出、或被淘汰。该算法减少了参与节点的数量,减少了节点响应的时间,提高了交易效率。
区块链遇到的问题
区块扩容
比特币的区块限制在1M,导致记录的交易数量很少,限制了比特币在大规模快速交易中的应用,所以提出了两种方案来解决这个问题:
- 区块扩容。将区块大小设置的大一些。
- 隔离见证。从区块中去掉见证交易合法性的签名。
由于比特币是无中心化的,让所有节点进行改造是不可能的,并且这些节点的拥有者对改造的意见也不相同。所以节点的不同选择会导致整个链分叉,从而形成两种区块链。
侧链
为了让资产可以在不同区块链之间转移而提出了侧链的概念,主、侧链之间的转移步骤如下:
- 在比特币主链上锁定一定的比特币,在侧链上激活对等的资产;
- 侧链按照自己的游戏规则交易这些资产;
- 相应的,侧链可以冻结相应的资产,将比特币归还到主链。
闪电链
为了加快交易速度,减少对主链的压力,提出了闪电网的概念。闪电网是在主链外开辟快速交易通道,临时记录一段时间的频繁交易,定期将最后结果提交到主链。
区块链存在的问题
分叉
由于部分节点采用新版本的合约,而导致和老版本的节点不兼容,导致区块链分叉为老节点产生的区块链和新节点产生的区块链,如果一直保持这种状况,则会导致整个区块链分裂为两个系统,形成“各玩各的”局面。
除了版本差异导致的分叉,还有可能是网络问题导致部分节点被孤立起来,从而这些被割裂的节点组成一个小的区块链系统,产生的区块链和主链也会产生较大差异。在某个时刻这部分节点重新加入主链,则整个系统需要耗费一些代价来弥合原来产生的分歧。
51%算力
如果一个人拥有了区块链超过一半的算力,他就拥有了大多数的打包权,那么他就可以在对交易打包时进行作弊,从而从中牟利。
拥有算力优势的人还可以拒绝一些交易记录,使得一些交易长时间无法完成。
如果拥有算力优势的人采用一些手段违反当初的约定,这会打击其他人挖矿的积极性,对整个区块链产生负面的影响。
私钥丢失
私钥丢失代表着在整个区块链中所拥有的财富丢失,目前还没有办法找回。
交易确认延迟
非所有的交易会被立刻打包进区块,一笔交易需要耗费一定的时间才能被计入区块链。交易被确认前是缓存在内存中的,打包区块需要时间进行计算,并且区块有大小限制,即使被打包进区块还要被大多数节点接受,所以一笔交易本最终确认周期较长。
有的节点会根据手续费来控制打包的顺序,所以普通的交易更难被打包进区块了。
不断膨胀的区块链
随着交易数量的日积月累,承载记账功能的区块链数据会越来越多,对这些数据的查询和存储会越来越困难。
内容参考《白话区块链》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。