Category Archives: 区块链

详解以太坊的工作原理

这篇文章主要讲解以太坊的基本原理,对技术感兴趣的朋友可以看看。

翻译作者: 许莉
原文地址:How does Ethereum work, anyway?

简介

不管你们知不知道以太坊(Ethereum blockchain)是什么,但是你们大概都听说过以太坊。最近在新闻里出现过很多次,包括一些专业杂志的封面,但是如果你们对以太坊到底是什么没有一个基本的了解的话,看这些文章就会感觉跟看天书一样。 所以,什么是以太坊?本质上,就是一个保存数字交易永久记录的公共数据库。重要的是,这个数据库不需要任何中央权威机构来维持和保护它。相反的它以一个“无信任”的交易系统来运行—一个个体在不需要信任任何第三方或对方的情况下进行点对点交易的架构。

eth

依然感到很困惑?这就是这篇文章存在的理由。我的目标是在技术层面来解释以太坊的工作原理,但是不会出现很复杂的数学问题或看起来很可怕的公式。即使你不是一个程序员,我希望你看完之后最起码对技术有个更好的认识。如果有些部分技术性太强不好理解,这是非常正常的,真的没有必要完全理解每一个小细节。我建议只要宏观的理解一下事物就行了。

这篇文章中的很多议点都是以太坊黄皮书中讨论过的概念的细分。我添加了我自己的解释和图表使理解以太坊更加简单一点。那些足够勇敢的人可以挑战一下技术,去阅读一下以太坊的黄皮书。

好了, 让我们开始吧!

 

区块链定义

 

区块链就是一个具有共享状态的密码性安全交易的单机(cryptographically secure transactional singleton machine with shared-state)。[1]这有点长,是吧?让我们将它分开来看:

  1. “密码性安全(Cryptographically secure)”是指用一个很难被解开的复杂数学机制算法来保证数字货币生产的安全性。将它想象成类似于防火墙的这种。它们使得欺骗系统近乎是一个不可能的事情(比如:构造一笔假的交易,消除一笔交易等等)。
  2. “交易的单机(Transactional singleton machine)”是指只有一个权威的机器实例为系统中产生的交易负责任。换句话说,只有一个全球真相是大家所相信的。
  3. “具有共享状态(With shared-state)”是指在这台机器上存储的状态是共享的,对每个人都是开放的。

以太坊实现了区块链的这个范例。

 

以太坊模型说明

 

以太坊的本质就是一个基于交易的状态机(transaction-based state machine)。在计算机科学中,一个 状态机 是指可以读取一系列的输入,然后根据这些输入,会转换成一个新的状态出来的东西。
p1

根据以太坊的状态机,我们从创世纪状态(genesis state)开始。这差不多类似于一片空白的石板,在网络中还没有任何交易的产生状态。当交易被执行后,这个创世纪状态就会转变成最终状态。在任何时刻,这个最终状态都代表着以太坊当前的状态。
p2

以太坊的状态有百万个交易。这些交易都被“组团”到一个区块中。一个区块包含了一系列的交易,每个区块都与它的前一个区块链接起来。
p3

为了让一个状态转换成下一个状态,交易必须是有效的。为了让一个交易被认为是有效的,它必须要经过一个验证过程,此过程也就是挖矿。挖矿就是一组节点(即电脑)用它们的计算资源来创建一个包含有效交易的区块出来。

任何在网络上宣称自己是矿工的节点都可以尝试创建和验证区块。世界各地的很多矿工都在同一时间创建和验证区块。每个矿工在提交一个区块到区块链上的时候都会提供一个数学机制的“证明”,这个证明就像一个保证:如果这个证明存在,那么这个区块一定是有效的。

为了让一个区块添加到主链上,一个矿工必须要比其他矿工更快的提供出这个“证明”。通过矿工提供的一个数学机制的“证明”来证实每个区块的过程称之为工作量证明(proof of work)。

证实了一个新区块的矿工都会被奖励一定价值的奖赏。奖赏是什么?以太坊使用一种内在数字代币—以太币(Ether)作为奖赏。每次矿工证明了一个新区块,那么就会产生一个新的以太币并被奖励给矿工。

你也许会在想:什么能确保每个人都只在区块的同一条链上呢?我们怎么能确定不会存在一部分矿工创建一个他们自己的链呢?

前面,我们定义了区块链就是一个具有共享状态的交易单机。使用这个定义,我们可以知道正确的当前状态是一个全球真相,所有人都必须要接受它。拥有多个状态(或多个链)会摧毁这个系统,因为它在哪个是正确状态的问题上不可能得到统一结果。如果链分叉了,你有可能在一条链上拥有10个币,一条链上拥有20个币,另一条链上拥有40个币。在这种场景下,是没有办法确定哪个链才是最”有效的“。

不论什么时候只要多个路径产生了,一个”分叉“就会出现。我们通常都想避免分叉,因为它们会破坏系统,强制人们去选择哪条链是他们相信的链。
p4

为了确定哪个路径才是最有效的以及防止多条链的产生,以太坊使用了一个叫做“GHOST协议(GHOST protocol.)”的数学机制。

GHOST = Greedy Heaviest Observed Subtree

简单来说,GHOST协议就是让我们必须选择一个在其上完成计算最多的路径。一个方法确定路径就是使用最近一个区块(叶子区块)的区块号,区块号代表着当前路径上总的区块数(不包含创世纪区块)。区块号越大,路径就会越长,就说明越多的挖矿算力被消耗在此路径上以达到叶子区块。使用这种推理就可以允许我们赞同当前状态的权威版本。
p5

现在你大概对区块链是什么有个理性的认识,让我们在再深入了地解一下以太坊系统主要组成部分:

  1. 账户(accounts)
  2. 状态(state)
  3. 损耗和费用(gas and fees)
  4. 交易(transactions)
  5. 区块(blocks)
  6. 交易执行(transaction execution)
  7. 挖矿(mining)
  8. 工作量证明(proof of work)

在开始之前需要注意的是:每当我说某某的hash, 我指的都是KECCAK-256 hash, 以太坊就是使用这个hash算法。

 

账户

 

以太坊的全局“共享状态”是有很多小对象(账户)来组成的,这些账户可以通过消息传递架构来与对方进行交互。每个账户都有一个与之关联的状态(state)和一个20字节的地址(address)。在以太坊中一个地址是160位的标识符,用来识别账户的。

这是两种类型的账户:

  1. 外部拥有的账户,被私钥控制且没有任何代码与之关联
  2. 合约账户,被它们的合约代码控制且有代码与之关联

p6

外部拥有账户与合约账户的比较

理解外部拥有账户和合约账户的基本区别是很重要的。一个外部拥有账户可以通过创建和用自己的私钥来对交易进行签名,来发送消息给另一个外部拥有账户或合约账户。在两个外部拥有账户之间传送的消息只是一个简单的价值转移。但是从外部拥有账户到合约账户的消息会激活合约账户的代码,允许它执行各种动作。(比如转移代币,写入内部存储,挖出一个新代币,执行一些运算,创建一个新的合约等等)。

不像外部拥有账户,合约账户不可以自己发起一个交易。相反,合约账户只有在接收到一个交易之后(从一个外部拥有账户或另一个合约账户接),为了响应此交易而触发一个交易。我们将会在“交易和消息”部分来了解关于合约与合约之间的通信。
p7

因此,在以太坊上任何的动作,总是被外部控制账户触发的交易所发动的。
p8

账户状态

账户状态有四个组成部分,不论账户类型是什么,都存在这四个组成部分:

  1. nonce:如果账户是一个外部拥有账户,nonce代表从此账户地址发送的交易序号。如果账户是一个合约账户,nonce代表此账户创建的合约序号
  2. balance: 此地址拥有Wei的数量。1Ether=10^18Wei
  3. storageRoot: Merkle Patricia树的根节点Hash值(我们后面在解释Merkle树)。Merkle树会将此账户存储内容的Hash值进行编码,默认是空值
  4. codeHash:此账户EVM(以太坊虚拟机,后面细说)代码的hash值。对于合约账户,就是被Hash的代码并作为codeHash保存。对于外部拥有账户,codeHash域是一个空字符串的Hash值

p9

世界状态

好了,我们知道了以太坊的全局状态就是由账户地址和账户状态的一个映射组成。这个映射被保存在一个叫做Merkle Patricia树的数据结构中

Merkle Tree(也被叫做Merkle trie)是一种由一系列节点组成的二叉树,这些节点包括:

  1. 在树底的包含了源数据的大量叶子节点
  2. 一系列的中间的节点,这些节点是两个子节点的Hash值
  3. 一个根节点,同样是两个子节点的Hash值,代表着整棵树

p10

树底的数据是通过分开我们想要保存到chunks的数据产生的,然后将chunks分成buckets,再然后再获取每个bucket的hash值并一直重复直到最后只剩下一个Hash:根Hash。
p11

这棵树要求存在里面的值(value)都有一个对应的key。从树的根节点开始,key会告诉你顺着哪个子节点可以获得对应的值,这个值存在叶子节点。在以太坊中,key/value是地址和与地址相关联的账户之间状态的映射,包括每个账户的balance, nonce, codeHash和storageRoot(storageRoot自己就是一颗树)。
p12

同样的树结构也用来存储交易和收据。更具体的说,每个块都有一个头(header),保存了三个不同Merkle trie结构的根节点的Hash,包括:

  1. 状态树
  2. 交易树
  3. 收据树

p13

在Merkle tries中存储所有信息的高效性在以太坊中的“轻客户端”和“轻节点”相当的有用。记住区块链就是一群节点来维持的。广泛的说,有两种节点类型:全节点和轻节点。

全节点通过下载整条链来进行同步,从创世纪块到当前块,执行其中包含的所有交易。通常,矿工会存储全节点,因为他们在挖矿过程中需要全节点。也有可能下载一个全节点而不用执行所有的交易。无论如何,一个全节点包含了整个链。

不过除非一个节点需要执行所有的交易或轻松访问历史数据,不然没必要保存整条链。这就是轻节点概念的来源。比起下载和存储整个链以及执行其中所有的交易,轻节点仅仅下载链的头,从创世纪块到当前块的头,不执行任何的交易或检索任何相关联的状态。由于轻节点可以访问块的头,而头中包含了3个tries的Hash,所有轻节点依然可以很容易生成和接收关于交易、事件、余额等可验证的答案。

这个可以行的通是因为在Merkle树中hash值是向上传播的—如果一个恶意用户试图用一个假交易来交换Merkle树底的交易,这个会改变它上面节点的hash值,而它上面节点的值的改变也会导致上上一个节点Hash值的改变,以此类推,一直到树的根节点。
p14

任何节点想要验证一些数据都可以通过Merkle证明来进行验证,Merkle 证明的组成:

  1. 一块需要验证的数据
  2. 树的根节点Hash
  3. 一个“分支”(从 chunk到根这个路径上所有的hash值)

p15

任何可以读取证明的人都可以验证分支的hash是连贯的,因此给出的块在树中实际的位置就是在此处。

总之,使用Merkle Patricia树的好处就是该结构的根节点加密取决于存储在树中的数据,而且根据点的hash还可以作为该数据的安全标识。由于块的头包含了状态、交易、收据树的根hash,所有任何节点都可以验证以太坊的一小部分状态而不用保存整个状态,这整个状态的的大小可能是非常大的。

Gas和费用

在以太坊中一个比较重要的概念就是费用(fees),由以太坊网络上的交易而产生的每一次计算,都会产生费用—没有免费的午餐。这个费用是以称之为”gas”的来支付。

gas就是用来衡量在一个具体计算中要求的费用单位。gas price就是你愿意在每个gas上花费Ether的数量,以“gwei”进行衡量。“Wei”是Ether的最小单位,1Ether表示10^18Wei. 1gwei是1,000,000,000 Wei。

对每个交易,发送者设置gas limit和gas price。gas limit和gas price就代表着发送者愿意为执行交易支付的Wei的最大值。

例如,假设发送者设置gas limit为50,000,gas price为20gwei。这就表示发送者愿意最多支付50,000*20gwei = 1,000,000,000,000,000 Wei = 0.001 Ether来执行此交易。
p16

记住gas limit代表用户愿意花费在gas上的钱的最大值。如果在他们的账户余额中有足够的Ether来支付这个最大值费用,那么就没问题。在交易结束时任何未使用的gas都会被返回给发送者,以原始费率兑换。
p17

在发送者没有提供足够的gas来执行交易,那么交易执行就会出现“gas不足”然后被认为是无效的。在这种情况下,交易处理就会被终止以及所有已改变的状态将会被恢复,最后我们就又回到了交易之前的状态—完完全全的之前状态就像这笔交易从来没有发生。因为机器在耗尽gas之前还是为计算做出了努力,
所以理论上,将不会有任何的gas被返回给发送者。
p18

这些gas的钱到底去了哪里?发送者在gas上花费的所有钱都发送给了“受益人”地址,通常情况下就是矿工的地址。因为矿工为了计算和验证交易做出了努力,所以矿工接收gas的费用作为奖励。
p19

通常,发送者愿意支付更高的gas price,矿工从这笔交易总就能获得更多的价值。因此,矿工也就更加愿意选择这笔交易。这样的话,矿工可以自由的选择一笔交易自己愿意验证或忽略。为了引导发送者应该设置gas price为多少,矿工可以选择建议一个最小的gas值他们愿意执行一个交易。

存储也有费用

gas不仅仅是用来支付计算这一步的费用,而且也用来支付存储的费用。存储的总费用与所使用的32位字节的最小倍数成比例。

存储费用有一些比较细微的方面。比如,由于增加了的存储增加了所有节点上的以太坊状态数据库的大小,所以激励保持数据存储量小。为了这个原因,如果一个交易的执行有一步是清除一个存储实体,那么为执行这个操作的费用就会被放弃,并且由于释放存储空间的退款就会被返回给发送者。

费用的作用是什么?

以太坊可以运作的一个重要方面就是每个网络执行的操作同时也被全节点所影响。然而,计算的操作在以太坊虚拟机上是非常昂贵的。因此,以太坊智能合约最好是用来执行最简单的任务,比如运行一个简单的业务逻辑或者验证签名和其他密码对象,而不是用于复杂的操作,比如文件存储,电子邮件,或机器学习,这些会给网络造成压力。施加费用防止用户使网络超负荷。

以太坊是一个图灵完备语言(短而言之,图灵机器就是一个可以模拟任何电脑算法的机器。对于图灵机器不太熟悉的人可以看看这个 和这个 )。这就允许有循环,并使以太坊受到停机问题 的影响,这个问题让你无法确定程序是否无限制的运行。如果没有费用的话,恶意的执行者通过执行一个包含无限循环的交易就可以很容易的让网络瘫痪而不会产生任何反响。因此,费用保护网络不受蓄意攻击。

你也许会想,“为什么我们还需要为存储付费?”其实就像计算一样,以太坊网络上的存储是整个网络都必须要负担的成本。

交易和消息

之前说过以太坊是一个基于交易的状态机。换句话说,在两个不同账户之间发生的交易才让以太坊全球状态从一个状态转换成另一个状态。

最基本的概念,一个交易就是被外部拥有账户生成的加密签名的一段指令,序列化,然后提交给区块链。

有两种类型的交易:消息通信和合约创建(也就是交易产生一个新的以太坊合约)。

不管什么类型的交易,都包含:

  1. nonce:发送者发送交易数的计数
  2. gasPrice:发送者愿意支付执行交易所需的每个gas的Wei数量
  3. gasLimit:发送者愿意为执行交易支付gas数量的最大值。这个数量被设置之后在任何计算完成之前就会被提前扣掉
  4. to:接收者的地址。在合约创建交易中,合约账户的地址还没有存在,所以值先空着
  5. value:从发送者转移到接收者的Wei数量。在合约创建交易中,value作为新建合约账户的开始余额
  6. v,r,s:用于产生标识交易发生着的签名
  7. init(只有在合约创建交易中存在):用来初始化新合约账户的EVM代码片段。init值会执行一次,然后就会被丢弃。当init第一次执行的时候,它返回一个账户代码体,也就是永久与合约账户关联的一段代码。
  8. data(可选域,只有在消息通信中存在):消息通话中的输入数据(也就是参数)。例如,如果智能合约就是一个域名注册服务,那么调用合约可能就会期待输入域例如域名和IP地址

p20

在“账户”这个章节中我们学到交易—消息通信和合约创建交易两者都总是被外部拥有账户触发并提交到区块链的。换种思维思考就是,交易是外部世界和以太坊内部状态的桥梁。
p21

但是这也并不代表一个合约与另一个合约无法通信。在以太坊状态全局范围内的合约可以与在相同范围内的合约进行通信。他们是通过“消息”或者“内部交易”进行通信的。我们可以认为消息或内部交易类似于交易,不过与交易有着最大的不同点—它们不是由外部拥有账户产生的。相反,他们是被合约产生的。它们是虚拟对象,与交易不同,没有被序列化而且只存在与以太坊执行环境。

当一个合约发送一个内部交易给另一个合约,存在于接收者合约账户相关联的代码就会被执行。
p22

一个重要需要注意的事情是内部交易或者消息不包含gasLimit。因为gas limit是由原始交易的外部创建者决定的(也就是外部拥有账户)。外部拥有账户设置的gas limit必须要高到足够将交易完成,包括由于此交易而长生的任何”子执行”,例如合约到合约的消息。如果,在一个交易或者信息链中,其中一个消息执行使gas已不足,那么这个消息的执行会被还原,包括任何被此执行触发的子消息。不过,父执行没必要被还原。

区块

所有的交易都被组成一个”块”。一个区块链包含了一系列这样的链在一起区块。

在以太坊中,一个区块包含:

  1. 区块头
  2. 关于包含在此区块中交易集的信息
  3. 与当前块的ommers相关的一系列其他区块头

Ommers解释

“ommer”到底是什么? ommer就是一个区块的父区块与当前区块父区块的父区块是相同的。让我们快速了解一下ommers是用来干嘛的,并且为什么一个区块需要为ommers包含区块头。

由于以太坊的构造,它的区块生产时间(大概15秒左右)比其他的区块链例如Bitcoin(大概10分钟左右)要快很多。这使得交易的处理更快。但是,更短的区块生产时间的一个缺点就是:更多的竞争区块会被矿工发现。这些竞争区块同样也被称为“孤区块”(也就是被挖出来但是不会被添加到主链上的区块)。

Ommers的目的就是为了帮助奖励矿工纳入这些孤区块。矿工包含的ommers必须是有效的,也就是ommers必须在父区块的第6个子区块之内或更小范围内。在第6个子区块之后,陈旧的孤区块将不会再被引用(因为包含老旧的交易会使事情变得复杂一点)。

Ommer区块会收到比全区块少一点的奖励。不管怎样,依然存在激励来让矿工们纳入孤区块并能从中获得一些报酬。

区块头

让我们再回到区块的问题上。我们前面提到每个区块都有一个“区块头”,但这究竟是什么?

区块头是一个区块的一部分,包含了:

  1. parentHash:父区块头的Hash值(这也是使得区块变成区块链的原因)
  2. ommerHash:当前区块ommers列表的Hash值
  3. beneficiary:接收挖此区块费用的账户地址
  4. stateRoot:状态树根节点的Hash值(回忆一下我们之前所说的保存在头中的状态树以及它使得轻客户端认证任何关于状态的事情都变得非常简单)
  5. transactionsRoot:包含此区块所列的所有交易的树的根节点Hash值
  6. receiptsRoot:包含此区块所列的所有交易收据的树的根节点Hash值
  7. logsBloom:由日志信息组成的一个Bloom过滤器 (数据结构)
  8. difficulty: 此区块的难度级别
  9. number:当前区块的计数(创世纪块的区块序号为0,对于每个后续区块,区块序号都增加1)
  10. gasLimit:每个区块的当前gas limit
  11. gasUsed: 此区块中交易所用的总gas量
  12. timestamp:此区块成立时的unix的时间戳
  13. extraData:与此区块相关的附加数据
  14. mixHash:一个Hash值,当与nonce组合时,证明此区块已经执行了足够的计算
  15. nonce:一个Hash值,当与mixHash组合时,证明此区块已经执行了足够的计算

p23

注意每个区块是如何包含三个树结构的,三个树结构分别对应:

  1. 状态(stateRoot)
  2. 交易(transactionsRoot)
  3. 收据(receiptsRoot)

这三个树结构就是我们前面讨论的Merkle Patricia树。

另外,上面描述的有几个术语值得说明一下,下面来看一下。

日志

以太坊允许日志可以跟踪各种交易和信息。一个合约可以通过定义“事件”来显示的生成日志。

一个日志的实体包含:

  1. 记录器的账户地址
  2. 代表本次交易执行的各种事件的一系列主题以及与这些事件相关的任何数据

日志被保存在bloom过滤器 中,过滤器高效的保存了无尽的日志数据。

交易收据

自于被包含在交易收据中的日志信息存储在头中。就像你在商店买东西时收到的收据一样,以太坊为每笔交易都产生一个收据。像你期望的那样,每个收据包含关于交易的特定信息。这些收据包含着:

  1. 区块序号
  2. 区块Hash
  3. 交易Hash
  4. 当前交易使用了的gas
  5. 在当前交易执行完之后当前块使用的累计gas
  6. 执行当前交易时创建的日志
  7. 等等

区块难度

区块的难度是被用来在验证区块时加强一致性。创世纪区块的难度是131,072,有一个特殊的公式用来计算之后的每个块的难度。如果某个区块比前一个区块验证的更快,以太坊协议就会增加区块的难度。

区块的难度影响nonce,它是在挖矿时必须要使用proof-of-work算法来计算的一个hash值。

区块难度和nonce之间的关系用数学形式表达就是:
p24
Hd代表的是难度。

找到符合难度阈值的nonce唯一方法就是使用proof-of-work算法来列举所有的可能性。找到解决方案预期时间与难度成正比—难度越高,找到nonce就越困难,因此验证一个区块也就越难,这又相应地增加了验证新块所需的时间。所以,通过调整区块难度,协议可以调整验证区块所需的时间。

另一方面,如果验证时间变的越来越慢,协议就会降低难度。这样的话,验证时间自我调节以保持恒定的速率—平均每15s一个块。

交易执行

我们已经到了以太坊协议最复杂的部分:交易的执行。假设你发送了一笔交易给以太坊网络处理,将以太坊状态转换成包含你的交易这个过程到底发生了什么?
p25

首先,为了可以被执行所有的交易必须都要符合最基础的一系列要求,包括:

  • 交易必须是正确格式化的RLP。”RLP”代表Recursive Length Prefix,它是一种数据格式,用来编码二进制数据嵌套数组。以太坊就是使用RLP格式序列化对象。
  • 有效的交易签名。
  • 有效的交易序号。回忆一下账户中的nonce就是从此账户发送出去交易的计数。如果有效,那么交易序号一定等于发送账户中的nonce。
  • 交易的gas limit 一定要等于或者大于交易使用的intrinsic gas,intrinsic gas包括:
    ——-1.执行交易预订费用为21,000gas
    ——-2.随交易发送的数据的gas费用(每字节数据或代码为0的费用为4gas,每个非零字节的数据或代码费用为68gas)
    ——-3.如果交易是合约创建交易,还需要额外的32,000gas
    p26
  • 发送账户余额必须有足够的Ether来支付”前期”gas费用。前期gas费用的计算比较简单:首先,交易的gas limit乘以交易的gas价格得到最大的gas费用。然后,这个最大gas费用被加到从发送方传送给接收方的总值。
    p27

如何交易符合上面所说的所有要求,那么我们进行下面步骤。

第一步,我们从发送者的余额中扣除执行的前期费用,并为当前交易将发送者账户中的nonce增加1。此时,我们可以计算剩余的gas,将交易的总gas减去使用的intrinsic gas。
p28

第二步,开始执行交易。在交易执行的整个过程中,以太坊保持跟踪“子状态”。子状态是记录在交易中生成的信息的一种方式,当交易完成时会立即需要这些信息。具体来说,它包含:

  1. 自毁集:在交易完成之后会被丢弃的账户集(如果存在的话)
  2. 日志系列:虚拟机的代码执行的归档和可检索的检查点
  3. 退款余额:交易完成之后需要退还给发送账户的总额。回忆一下我们之前提到的以太坊中的存储需要付费,发送者要是清理了内存就会有退款。以太坊使用退款计数进行跟踪退款余额。退款计数从0开始并且每当合约删除了一些存储中的东西都会进行增加。

第三步,交易所需的各种计算开始被处理。

当交易所需的步骤全部处理完成,并假设没有无效状态,通过确定退还给发送者的未使用的gas量,最终的状态也被确定。除了未使用的gas,发送者还会得到上面所说的“退款余额”中退还的一些津贴。

一旦发送者得到退款之后:

  1. gas的Ether就会矿工
  2. 交易使用的gas会被添加到区块的gas计数中(计数一直记录当前区块中所有交易使用的gas总量,这对于验证区块时是非常有用的)
  3. 所有在自毁集中的账户(如果存在的话)都会被删除

最后,我们就有了一个新的状态以及交易创建的一系列日志。

现在我们已经介绍了交易执行的基本知识,让我们再看看合约创建交易和消息通信的一些区别。

合约创建(Contract creation)

回忆一下在以太坊中,有两种账户类型:合约账户和外部拥有账户。当我们说一个交易是“合约创建”,是指交易的目的是创建一个新的合约账户。

为了创建一个新的合约账户,我们使用一个特殊的公式来声明新账户的地址。然后我们使用下面的方法来初始化一个账户:

  1. 设置nonce为0
  2. 如果发送者通过交易发送了一定量的Ether作为value,那么设置账户的余额为value
  3. 将存储设置为0
  4. 设置合约的codeHash为一个空字符串的Hash值

一旦我们完成了账户的初始化,使用交易发送过来的init code(查看”交易和信息”章节来复习一下init code),实际上就创造了一个账户。init code的执行过程是各种各样的。取决于合约的构造器,可能是更新账户的存储,也可能是创建另一个合约账户,或者发起另一个消息通信等等。

当初始化合约的代码被执行之后,会使用gas。交易不允许使用的gas超过剩余gas。如果它使用的gas超过剩余gas,那么就会发生gas不足异(OOG)常并退出。如果一个交易由于gas不足异常而退出,那么状态会立刻恢复到交易前的一个点。发送者也不会获得在gas用完之前所花费的gas。

不过,如果发送者随着交易发送了Ether,即使合约创建失败Ether也会被退回来。

如果初始化代码成功的执行完成,最后的合约创建的花费会被支付。这些是存储成本,与创建的合约代码大小成正比(再一次,没有免费的午餐)。如果没有足够的剩余gas来支付最后的花费,那么交易就会再次宣布gas不足异常并中断退出。

如果所有的都正常进行没有任何异常出现,那么任何剩余的未使用gas都会被退回给原始的交易发送者,现在改变的状态才被允许永久保存。

消息通信(Message calls)

消息通信的执行与合约创建比较类似,只不过有一点点区别。

由于没有新账户被创建,所以消息通信的执行不包含任何的init code。不过,它可以包含输入数据,如果交易发送者提供了此数据的话。一旦执行,消息通信同样会有一个额外的组件来包含输出数据,如果后续执行需要此数据的话就组件就会被使用。

就像合约创建一样,如果消息通信执行退出是因为gas不足或交易无效(例如栈溢出,无效跳转目的地或无效指令),那么已使用的gas是不会被退回给原始触发者的。相反,所有剩余的未使用gas也会被消耗掉,并且状态会被立刻重置为余额转移之前的那个点。

没有任何方法停止或恢复交易的执行而不让系统消耗你提供的所有gas,直到最新的以太坊更新。例如,假设你编写了一个合约,当调用者没有授权来执行这些交易的时候抛出一个错误。在以太坊的前一个版本中,剩余的gas也会被消耗掉,并且没有任何gas退回给发送者。但是拜占庭更新包括了一个新的“恢复”代码,允许合约停止执行并且恢复状态改变而不消耗剩余的gas,此代码还拥有返回交易失败原因的能力。如果一个交易是由于恢复而退出,那么未使用的gas就会被返回给发送者。

执行模式

到目前为止,我们了解了从开始到结束执行的交易必须经历的一系列的步骤。现在,我们来看看交易究竟是如何在虚拟机(VM)中执行的。

协议实际操作交易处理的部分是以太坊自己的虚拟机,称之为以太坊虚拟机(EVM)。

像之前定义的那样,EVM是图灵完备虚拟机器。EVM存在而典型图灵完备机器不存在的唯一限制就是EVM本质上是被gas束缚。因此,可以完成的计算总量本质上是被提供的gas总量限制的。
p29

此外,EVM具有基于堆栈的架构。堆栈机器 就是使用后进先出来保存临时值的计算机。

EVM中每个堆栈项的大小为256位,堆栈有一个最大的大小,为1024位。

EVM有内存,项目按照可寻址字节数组来存储。内存是易失性的,也就是数据是不持久的。

EVM也有一个存储器。不像内存,存储器是非易失性的,并作为系统状态的一部分进行维护。EVM分开保存程序代码,在虚拟ROM 中只能通过特殊指令来访问。这样的话,EVM就与典型的冯·诺依曼架构 不同,此架构将程序的代码存储在内存或存储器中。
p30

EVM同样有属于它自己的语言:“EVM字节码”,当一个程序员比如你或我写一个在以太坊上运行的智能合约时,我们通常都是用高级语言例如Solidity来编写代码。然后我们可以将它编译成EVM可以理解的EVM字节码。

好了,现在来说执行。

在执行特定的计算之前,处理器会确定下面所说的信息是有效和是否可获取:

  1. 系统状态
  2. 用于计算的剩余gas
  3. 拥有执行代码的账户地址
  4. 原始触发此次执行的交易发送者的地址
  5. 触发代码执行的账户地址(可能与原始发送者不同)
  6. 触发此次执行的交易gas价格
  7. 此次执行的输入数据
  8. Value(单位为Wei)作为当前执行的一部分传递给该账户
  9. 待执行的机器码
  10. 当前区块的区块头
  11. 当前消息通信或合约创建堆栈的深度

执行刚开始时,内存和堆栈都是空的,程序计数器为0。

1
PC: 0 STACK: [] MEM: [], STORAGE: {}

然后EVM开始递归的执行交易,为每个循环计算系统状态和机器状态。系统状态也就是以太坊的全局状态(global state)。机器状态包含:

  1. 可获取的gas
  2. 程序计数器
  3. 内存的内容
  4. 内存中字的活跃数
  5. 堆栈的内容

堆栈中的项从系列的最左边被删除或者添加。

每个循环,剩余的gas都会被减少相应的量,程序计数器也会增加。
在每个循环的结束,都有三种可能性:

  1. 机器到达异常状态(例如 gas不足,无效指令,堆栈项不足,堆栈项会溢出1024,无效的JUMP/JUMPI目的地等等)因此停止,并丢弃任何的更改
  2. 进入后续处理下一个循环
  3. 机器到达了受控停止(到达执行过程的终点)

假设执行没有遇到异常状态,达到一个“可控的”或正常的停止,机器就会产生一个合成状态,执行之后的剩余gas、产生的子状态、以及组合输出。

呼。我们终于过了一遍以太坊最难的部分了。如果你不能完全理解这个部分,也没关系。除非你在理解非常深层次的东西,否则你真的没有必要去理解执行的每个细节。

一个块是如何完成的?

最后,让我们看看一个包含许多交易的块是如何完成的。

当我们说“完成”,取决于此块是新的还是已存在的,可以指两个不同的事情。如果是个新块,就是指挖这个块所需的处理。如果是已存在的块,就是指验证此块的处理。不论哪种情况,一个块的“完成”都有4个要求:
1)验证(或者,如果是挖矿的话,就是确定)ommers
在区块头中的每个ommer都必须是有效的头并且必须在当前块的6代之内

2)验证(或者,如果是挖矿的话,就是确定)交易
区块中的gasUsed数量必须与区块中所列交易使用的累积gas量相等。(回忆一下,当执行一个交易的时候,我们会跟踪区块的gas计数器,也就跟踪了区块中所有交易使用的gas总数量)

3)申请奖励(只有挖矿时)
受益人的地址会因为挖矿而获得5Ether(在以太坊EIP-649 提案中,5ETH很快将会被减少为3ETH)。另外,对于每个ommer,当前块的受益人会获得额外的1/32当前块奖励金的奖励。最近,每个ommer区块的受益人能够得到一定量的奖励(有个特殊公式可以进行计算)。

4)校验(或者,如果是挖矿的话,就是计算一个有效的)状态和nonce
确保所有的交易和改变的结果状态都被应用了,然后在区块奖励被应用于最终交易结果状态之后定义一个新块为状态。通过检查最终状态与存储在头中的状态树来进行验证。

工作量证明挖矿

在“区块”这个章节简短的说明了一下区块难度这个概念。给予区块难度意义的算法叫做工作量证明(PoW)。

以太坊的工作量证明算法称之为“Ethash” (之前叫做Dagger-Hashimoto)。
算法正式定义为:
p31
m代表的是mixHash,n代表的是nonce,Hn代表的是新区块的头(不包含需要计算的nonce和mixHash),Hn是区块头的nonce,d是DAG ,就是一个大数据集。

在”区块”章节,我们讨论了存在于区块头中的多项。其中两项叫做mixHash和nonce。也许你会回忆起:

  1. mixHash:一个Hash值,当与nonce组合时,证明此区块已经执行了足够的计算
  2. nonce:一个Hash值,当与mixHash组合时,证明此区块已经执行了足够的计算

PoW函数就是用来估算这两项的。
mixHash和nonce到底是如何使用PoW函数来计算出来的有点复杂,如果深入了解的话,我们可以另写一篇文章来讲解了。但是在一个高层面上,它大致就是这样计算的:
会为每个区块计算一个”种子”。每个“时期”的种子都不一样,每个时期是30,000个区块长度。对于第一时期,种子就是32位0的hash值。对于后续的每个时期,种子就是前一个种子hash值的hash值。使用这个种子,节点可以计算一个伪随机“缓存”。

这个缓存是非常有用的,因为它可以使“轻节点”的概念变成现实,轻节点概念在这篇文章的前面讨论过。轻节点的目的就是让某个节点有能力高效的校验交易而用不着存储整个区块链的数据集。一个轻节点可以仅基于缓存来校验一个交易的有效性,因为缓存可以重新生成需要校验的特定块。

使用这个缓存,节点可以生成DAG“数据集”,数据集中的每项取决于缓存中少量伪随机选择项。为了成为矿工,你需要要生成全数据集,所有全客户端和矿工都保存这个数据集,并且这个数据集随着时间线性增长。

然后矿工可以随机抽取数据集中的部分并将它们放入一个数学函数中Hash出一个”mixHash”。矿工会重复生成mixHash直到输出的值小于想要的目标值nonce。当输出的值符合这个条件的时候,nonce就被认为是有效的,然后区块就被添加到链中。

挖矿作为安全机制

总的来说,PoW的目的就是以加密安全的方式证明生成的一些输出(也就是nonce)是经过了一定量的计算的。因为除了列举所有的可能性,没有更好的其他方法来找到一个低于要求阈值的nonce。重复应用Hash函数的输出均匀分布,所以我们可以确保,在平均值上,找到满足要求的nonce所需时间取决于难度阈值。难度系数越大,所需时间越长。这样的话,PoW算法就给予难度这个概念的意义了:用来加强区块链的安全。

我们所说的区块链的安全又是什么意思?这非常简单:我们想要创造一个每个人都信任的区块链。像我们之前在这篇文章中讨论的那样,如果存在超过1条以上的链,用户的信任就会消失,因为他们没有能力合理的确认哪条链才是“有效的”。为了让一群用户接受存储在区块链中的潜在状态,我们需要有一群人信任的一个权威区块链。

这完完全全就是Pow算法所做的事情:它确保特定的区块链直到未来都一直保持着权威性,让攻击者创造一个新区块来重写某个历史部分(例如清除一个交易或者创建一个假的交易)或者保持一个分叉变得非常困难。为了首先让他们的区块被验证,攻击者需要总是比网络上的其他人要更快的解决掉nonce问题,这样网络就会相信他们的链是最重的链(基于我们之前提到的GHOST协议原则)。除非攻击者拥有超过一半的网络挖矿能力(这种场景也被称为大多数51%攻击 ),要不然这基本上是不可能的。
p32

挖矿作为财富分配机制

除了提供一个安全的区块链,PoW同样也是分配财富给那些为提供这个安全而花费自己计算力的人的一种方法。回忆一下,一个矿工挖出一个区块的时候会获得奖励,包括:

  1. 为“获胜”区块提供的5 ether静态区块奖励(马上就会变成3 ether )
  2. 区块中的交易在区块内所消耗的gas
  3. 纳入ommers作为区块的一部分的额外奖励

为了保证PoW共识算法机制对安全和财富分配的使用是长期可持续的,以太坊努力灌输这两个特性:

  1. 尽可能的让更多的人可访问。换句话说,人们不需要特殊的或者与众不同的硬件来运行这个算法。这样做的目的是为了让财富分配模式变的尽可能的开放,以便任何人都可以提供一些算力而获得Ether作为回报。
  2. 降低任何单个节点(或小组)能够创造与其不成比例的利润可能性。任何可以创造不成比例的利润的节点拥有比较大的影响力来决定权威区块链。这是件麻烦的事情,因为这降低了网络的安全性。

在区块链网络中,一个与上面两个特性有关的一个问题是PoW算法是一个SHA256哈希函数。这种函数的缺点就是它使用特殊的硬件(也被称之为ASCIs)可以更加快速高效的解决nonce问题。

为了减轻这个问题,以太坊选择让PoW算法(Ethhash) 提高内存级别难度。意思是此算法被设计为计算出要求的nonce需要大量的内存和带宽。大量内存的需求让电脑平行的使用内存同时计算多个nonce变得极其困难,高带宽的需求让即使是超级电脑同时计算多个nonce也变得十分艰难。这种方式降低了中心化的风险,并为正在进行验证的几点提供了更加公平的竞争环境。

有一件值得注意的事情是以太坊正在从PoW共识机制渐渐转换为一个叫做“权益证明(PoS)”的共识算法。这就是一个比较野心的话题了,我们希望可以在未来的文章中探索这个话题。

总结

呼! 你终于坚持到最后了。我希望如此?

这篇文章中有很多的地方需要消化。如果需要你阅读好几遍才能理解怎么回事,这完全正常。我个人重复阅读了好几次以太坊黄皮书,白皮书,以及代码的不同部分才渐渐明白是怎么回事。

无论如何,我希望你觉得这篇文章对你有帮助。如果你发现了任何的错误或失误,我很乐意你给我写个私人消息或者直接在评论区评论(我保证我会查看所有评论)。

记住,我是个人类(对,这是真的),我会犯错误。为了社区的利益,我花时间免费写了这篇文章。所以请你在反馈时不要带着没必要的攻击性,尽量是建设性的反馈。

以太坊的黄皮书

发文时比特币价格 ¥29899.9
原文:https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369
作者:Preethi Kasireddy
翻译:lilymoana
稿源(译):巴比特资讯(http://www.8btc.com/how-blockchain-can-lift-up-the-worlds-poor)
版权声明:  作者保留权利。文章为作者独立观点,不代表巴比特立场。

我是如何学习区块链的

原创文章,转载请注明:转载自Keegan小钢
并标明原文链接:http://keeganlee.me/post/full-stack/20170915
微信订阅号:keeganlee_me
写于2017-09-15


专栏地址:https://xiaozhuanlan.com/fullstack


前几天我们已经学了如何学习的“道”和“术”,学完之后就应该落地到实践上,通过不断地实践练习,才能将这些 知识资源 转化为我们的 知识资本。如果你看完前面的文章后,觉得讲得真好,然后缺乏思考缺乏行动,然后就没有然后了。为了更好地指导你们如何实践,本篇文章我将与你分享我是如何将知识资源转化为我的知识资本的。

为什么选择区块链

选择区块链作为实践学习的案例,原因有三:

  • 第一,区块链是我最近两三个月刚学习的领域,对我来说也是一门从零开始学习的领域,这样的学习案例最具有指导作用。因为时间没有隔太久,很多学习过程中的细节我也还记得,这样我可以还原出更真实的学习过程。
  • 第二,区块链——确切说是虚拟货币最近非常火,连中国大妈都知道了,我的微信群里也有部分人在玩或准备玩,但大部分人普遍对比特币和区块链缺乏正确的认知,只是跟随潮流,这其实是存在很大风险的。因此,我觉得也有必要普及一下区块链和比特币正确的认知。
  • 第三,区块链是价值互联网的基石,是未来必然的趋势,会成为像HTTP一样基础的技术,所以也应该是每个技术人员都要掌握的技术。

关于第二点,很多人是因为听到了太多虚拟货币的致富神话,所以才开始关注这个行业。但却因为对虚拟货币和区块链缺乏真正的了解,所以其实看不懂这个行业的现状,更看不懂这个行业的未来。因为看不懂,所以要么一直观望,要么畏畏缩缩。最典型的就是我的一个同事,看着别人赚钱,一直想进。但从比特币1万块观望到2万块,一直不敢入场,总觉得价格太高,但却一直看着它升高。后来,有一次,被他抓到了一次抄底的机会,就是7月中旬比特币跌到1万3后反弹到差不多两万的那次,他终于下了决心入场了,貌似是丢了2000块钱进去,结果呢,赚了200块钱他就抛了。后来,BCC从2000块左右开始起飞之前,也被他抓住了,这次他胆子大了,丢了10000块钱进去,但和上次一样,只赚了10%就怕了跑出来了。那次BCC起飞足足翻了一倍还多。不过他也算是幸运的,起码赚到了钱,虽然赚得少。但有很多人是亏钱了的,而且还亏得不少。说了这么多,其实就是想表明,你想在这个行业里赚钱,甚至长期赚钱,你看不懂是不行的。

第三点才是最重要的,区块链将会成为基础性技术。基于HTTP的互联网可以称为信息互联网,主要传递的就是各种信息。而基于区块链的互联网则称为价值互联网,传递的是价值。在信息互联网时代你需要熟悉HTTP,那么,在价值互联网时代你就需要熟悉区块链。而且,未来已来,我们应该提前做好准备。

开始学习之前

每个人开始学习某项领域的知识之前,或多或少都会先听到或读到各种概念和观点,没有人会在真正一无所知的情况下突然决定要去学习某个东西。就比如说,如果你连“区块链”这个概念都没听说过,那你就不可能会有想去学“区块链”的想法。

我在决定开始学习区块链之前,就已经听到和读到了很多相关的概念,包括:区块链1.0、区块链2.0、区块链3.0、公有链、联盟链、私有链、硬分叉、软分叉、隔离见证、闪电网络、雷电网络、以太坊、以太坊经典、币圈、链圈、智能合约、比特币钱包等等,一大堆陌生概念。不过,那时候,给我印象最深刻的还是比特币,一个星期就从1万涨到了1万5。

那时候了解到的信息大部分都是从巴比特读到的,很多文章其实都看不懂,主要还是不懂的概念太多。但有一些还是看懂了,比如,比特币可称为数字黄金,那它未来的价值应该可以接近黄金,从这个角度来看的话,那比特币还有很大的上涨空间。比如,区块链开启了价值互联网时代,是趋势所在。主要也是这两点激发起了我学习区块链的兴趣。

确定目标

《001 | 如何高效学习》一文中就已经说过,想要提高学习效率,第一个条件就是:目标导向。功利学习法的核心也是目标导向。因此,我们学习一个东西,第一步必须是确定目标,而且必须是清晰明确的目标。另外,目标有分大目标和小目标。一开始,你是先确定了大目标,然后根据大目标分解成一个个小目标,每个小目标都应该是非常清晰明确可操作的。下面我就讲解我是如何将大目标拆解成小目标的。

我学习区块链的目标是很明确的,从大的方面来说,目标就两个:

  1. 为了以后进入区块链开发做技术储备;
  2. 为了能指导我如何投资虚拟货币。

那么,为了达到这两个目标,需要学习哪些东西呢?第一个目标需要学习区块链相关技术,就要知道区块链涉及到哪些技术、区块链的技术原理等;第二个目标则需要学习虚拟货币相关知识,包括需要解决有哪些虚拟货币、去哪里买虚拟货币、怎么买等问题,以及要了解虚拟货币未来的前景会如何。梳理之后,就变成了一个个待解决的问题:

  • 什么是区块链?
  • 区块链1.0、区块链2.0、区块链3.0有什么区别?
  • 什么是公有链?联盟链?私有链?
  • 什么是分叉?硬分叉和软分叉有什么区别?
  • 什么是隔离见证?闪电网络?雷电网络?
  • 比特币的本质是什么?
  • 比特币是如何交易的?
  • 什么是比特币钱包?
  • 什么是智能合约?
  • 什么是以太坊?以太坊和以太坊经典有什么区别?
  • 什么是币圈?什么是链圈?
  • 哪里买虚拟货币?怎么买?
  • 区块链和各种虚拟货币的前景如何?

很多时候,第一次梳理出来的问题并不全面,甚至很少,但没关系,在学习的过程中,就会不断涌现出新的问题。比如,有哪些共识算法?什么是超级账本?什么是ICO?怎么玩?等等这些就是我在学习的过程中新发现的问题。

这一步,最重要的是确定好大目标,然后拆解成一个个待解决的小问题。

搜集知识资源

当你的目标已经明确细分到一个个小问题之后,就可以根据这些问题搜集各种知识资源了。知识资源主要有三类:书籍、官方文档网络上的零散文章。搜集知识资源时,首选应该是书籍,因为书籍相对比较系统化,可以解答我们大部分的疑问。官方文档主要是为了加深理解,毕竟,书籍一般不会细化到一些技术细节之类的。而有部分问题,从书籍和官方文档是找不到答案的,这时就只能到网络上搜索相关文章了。另外,有些英语比较差的人看官方文档太累太费时间,也可以搜索网络上的中文文章。但我还是推荐尽量看原文,不会失真。

那么,回到我的区块链学习上来,选书上,我主要还是在那些比较畅销的书里挑,而且会尽量多覆盖上面所提到的问题。在亚马逊看每本书的简介和目录,最后选了以下几本:

  • 《区块链:新经济蓝图及导读》:同事推荐的一本书,讲到了区块链1.0、2.0、3.0,可以帮助我从宏观上了解区块链。
  • 《区块链:技术驱动金融》:从技术层面逐步解释了比特币是如何运作的。
  • 《区块链技术指南》:更加深入技术底层的书,还讲到了智能合约和超级账本,可以作为上一本书的补充。
  • 《区块链革命:比特币底层技术如何改变货币、商业和世界》:全景式描述了区块链理论及应用,这是为了扩大视野的书。

官方文档主要就是各种白皮书了,我搜集的白皮书主要包括:

最后,有些问题无法直接在书籍或白皮书中得到解答,比如说,什么是币圈?什么是链圈?这问题在百度或Google搜索一下就能得到答案了。有些文章会比较长,比如这篇:《详解最近大热的闪电网络、雷电网络和CORDA》,一时难以看懂,没关系,先收集起来,可以等后面进行大量泛读时再看。推荐可以去巴比特找资源,大部分都能找到。

这一步,主要还是搜集各种知识资源。先挑选书籍,尽量覆盖面广一点。再搜集各种官方文档,这是第一手信息,详细而不失真,可以加深理解。最后才是搜集网络上零散的文章,有些比较简单的问题可能直接就得到答案了,有些难以理解的要留到后面进行大量泛读时再看。

大量泛读

知识资源都搜集好了,接下来就可以开始进行大量泛读了。不知道大家是否还记得,大量泛读的主要目的就是:梳理出核心概念、主要观点框架逻辑。虽然在学习之前,我们或多或少都已经了解到了部分概念和观点,但在学习的过程中,我们就会发现还有更多我们不了解的概念和观点,这些都需要一一去理解的。

我们之前讲功利学习法时,提到知识资源可以分为三类:娱乐性、知识性、心智性。学习不同类型的知识应该分配不同的时间资源,知识性的比较适合碎片化学习,心智性的则需要集中几个小时进行系统性学习。因此,对我们搜集的这些知识资源,首先要区分好哪些是知识性的,哪些是心智性的,然后使用不同的时间管理策略进行阅读学习。对于我学习的区块链来说,大部分知识资源是属于知识性的,包括几本书籍的大部分内容和网络上搜集来的零散文章,这些我一般会放在上下班路上,或中午休息时学习;而那些专业的白皮书和书籍中深入技术架构的部分则属于心智性的知识,我一般就会放在晚上或周末集中两三个小时进行高强度学习。

阅读的方式也是有讲究的,我不会将几本书按顺序看完一本又一本,这样的话学习效率太低了。我会从一个个的问题出发,为了解决问题而从各种知识资源中找答案。解决完一个问题后再解决下一个。另外,在解决问题的过程中,普遍会遇到新的问题,那就把新问题先记下来,然后继续解决当前的问题。如果一个问题花了很长时间都解决不了,那可能这个问题对现阶段的你还没能力理解,这时可以先放一放,等学完其他再回过头来继续研究。

比如,我在解决“什么是比特币?”这个问题时,我会将每本书对比特币的介绍先看一遍,了解其框架逻辑后,再研读比特币白皮书,理解其技术架构和一些技术细节,直到终于明白,比特币从技术角度来说,本质上就是一堆复杂算法所生成的特解。另外,学习的过程中,就遇到了很多新的问题,比如“什么是共识算法?什么是Merkle Tree?什么是挖矿?等等,于是我就先把这些问题记下来,继续解决“什么是区块链?”的问题。

以下是我在大量泛读之后对一些核心概念的总结性理解:

  1. 区块链:从狭义上来说,区块链就是一种分布式的数据库,数据结构上就是按时间顺序将数据区块相连的一条链表,链上的每个节点就是一个区块,区块一般通过二叉树(如Merkle Tree)将每笔交易数据打包在一起,形成一个汇总的哈希值,再加上时间戳,就是一个区块的唯一标识。从广义上来说,区块链是结合了分布式数据存储、点对点传输、共识机制、加密算法等多种技术的一种分布式基础架构模式。
  2. 比特币:有很多人对比特币的理解就是账上的那串数字,但严格意义上来说,比特币是一种点对点的电子现金系统,是一整套系统,这点从比特币白皮书的标题上就已经说明了。可以将比特币简单理解为就是区块链技术的第一个应用。不过,“比特币”的概念要比“区块链”早,“区块链”这个概念是比特币发展了一段时间之后,将比特币的底层技术抽象出来形成的。另外,从投资的角度来看,比特币总量恒定为2100万个,其价值可以和黄金相比,但目前的市值和黄金的市值差距,还有很大的上涨空间,所以从长期来看,我还是非常看好。
  3. 以太坊:区块链2.0的典型代表,主要实现了智能合约的功能,开发人员可以在以太坊平台建立和发布各种分布式应用,这些应用,其实就是合约,智能合约说白了其实就是当达到某条件时会自动执行的代码。很多ICO的代币就是在以太坊平台上创建的应用。
  4. 公有链/联盟链/私有链:公有链就是完全公开的区块链,像比特币、以太坊;联盟链则不是完成公开的,是指有若干个机构共同参与管理的区块链,每个机构都运行着一个或多个节点,其中的数据只允许系统内不同的机构进行读写和发送交易,并且共同来记录交易数据,该联盟链的每个参与方不用担心自己数据存在哪里,自己产生的数据都只有自己看到,只有通过对方授权的密钥才能看到其他参与者的数据,这样就解决数据隐私和安全性问题,同时能够实现去中心化;私有链则是完全私有的,一般适合跨国公司,目前这一块还没了解到有什么代表性应用。

这一步,最高效率的阅读应该是带着问题去找答案。而且,要分配好时间资源,阅读知识性的信息时可以多用碎片化时间,心智性的内容则需要集中时间研读,要尽量理解每个核心概念。

建立模型

上一步我们已经大致理解了每个核心概念,但这些还只是一个个点,这一步就要将点与点之间连成线,逐渐连成网。即是说要理清不同核心概念之间的关联关系,逐渐形成系统模型。如果有条件的话,大白板当然是最好的思考工具,没有的话,用Visio、OmniGraffle之类的画图工具也可以,或者用XMind之类的思维导图也可以,甚至只用纸和笔都行,最重要的是要画出来。

以下是我用OmniGraffle梳理的区块链的系统模型图,因为时间和篇幅所限,所以只是部分内容:

求教专家

如果还存在无法解决的问题,那就要求教专家了。不过,这里也有一些需要注意的地方。

首先,你的朋友圈里要尽量多加一些专注不同领域的专家。不过,现在大部分人应该都加了不少牛人了,所以这一点没什么需要特别讲的。但有一点我想特别讲一下:不要随便什么问题都去求教专家

一来,专家基本都是很忙的,没太多时间总去帮你解决问题,尤其是当你问一些对他没有价值的问题时更不想搭理你。比如,你去请教一个Android架构师,问的却是“Android怎么打开蓝牙?”这种随便百度一下就能得到答案的问题,就算是我,我可能就会丢回一句“请自己去百度”。既然你请教的是Android架构师,就应该问架构方面的问题,而且最好是有深度、值得讨论、能给他带来价值的问题,比如,你去问他“什么是MVP?”这种问题也不合适,合适的请教方式应该是:你先讲出自己对MVP的理解,自己是如何用来架构项目的,再逐步与对方讨论MVP的架构思想、实现方案等。

二来,专家是你很重要的资源,你需要经营好。有一句话说得好:那些能帮到你的人,不是你的人脉,只有那些你能帮到的人,才是你的人脉。对于专家,虽然平时在专业领域上你很难帮得到他,但在其他方面你可以尽量多去给他提供帮助。

回到学习上来,为什么我们要先完成上一步的建立起系统模型后才来求教专家?之前的文章也有说过,因为如果你没有基本的全局观,问不出好问题。另外,也可以利用好知乎平台,很多问题,知乎上都有很多牛人有很好的回答。你也可以上去发问,当然,前提是你要提出好问题,这样,才有牛人愿意回答。

理解复述

复述最主要就是能起到强化理解的作用,费曼技巧是很好的一种复述方法,写作也是一种不错的方式,而且最好是公开性的。公开的写作,一来,你要写给不了解的人看,会促使你进行更完善的思考;二来,你可以从外部得到反馈,来完善和升级你的认知。所以我是推荐每个人都写博客的。

对于我来说,我更多就是写成文章分享出来,另外,有时候也会在公司内部做技术分享。

这一步也许是最费脑力的事情,但也是最能提高你的学习力的关键一步。

总结

我学习的方式可以总结为以下几个步骤:

  1. 确定目标:先确定大目标,再拆解成一个个待解决的小问题;
  2. 搜集知识资源:知识资源主要有三类:书籍、官方文档和网络上的零散文章,尽量搜集全一点;
  3. 大量泛读:最高效率的阅读应该是带着问题去找答案,而且要分配好时间资源;
  4. 建立模型:将一个个核心概念的点连成线,逐渐形成网,建立起系统模型;
  5. 求教专家:需要注意,不要随便什么问题都去求教专家,而且要经营好专家人脉;
  6. 理解复述:提高学习力的最关键一步,除了费曼技巧,写作也是一种推荐的方式。

思考和实践

如果让你学一门新的编程语言,你又会怎么学习?

白话区块链技术栈与应用

内容概要
现如今说起比特币,相信不少朋友已是耳熟能详了,尤其是这两年随着其价格飙升,甚至超过了黄金 ,超过了房地产,各大财经媒体乃至央视都有所关注报道;

在很多朋友心目中,比特币似乎就是一个类似于游戏币、邮币卡这样的炒作标的物,除了惊叹于它的价格上升速度外,对其了解还是寥寥。

然而,这一切的背后,到底是什么在支撑,现如今除了比特币,还有很多其他的类似系统, 比如莱特币、以太坊、 比特股等等,不胜其多,但凡介绍这些内容的软文, 大体都会提到一个名词:区块链 

一切似乎都是由区块链引起的,那么,就让我们剖开迷雾,揭开神秘的面纱,来看看这里头到底是个什么,它有什么特点,能有什么用处。
白话区块链技术栈与应用

导读:本章内容主要介绍区块链本身的含义以及代表性的技术组成,并由此介绍比特币是怎么通过这样的技术产生的。

1. 什么是区块链

1.1  一个有趣的数据记录格式

区块链,拆开来就是“区块+链”,实际上是一种数据的记录格式,软件在处理数据的时候,总是需要按照某种格式来读写,比如我们通常使用的关系型数据库,数据是按照一条一条的记录保存,或者再通俗的说,就像会计记账,将每一笔发生的业务都记在账本中,每一笔记录的账务称之为是凭证,一个月下来,将记录的一堆凭证数据汇总成 一个账簿,每过一个月就月结一下。区块链的格式,跟会计的这种记账方法很类似,所谓区块也就是一大坨数据的意思,我们可以将会计每个月所有记录的记账凭证看成是一个个的区块,区块之间通过年 月串联起来,这样看起来就像是一条数据链一样,区块链其实就是这么简单的一个格式,我们看个示意图:

如图所示,就是区块链格式的样子了 ,在比特币中,不是每个月存储一个区块, 而是大约每10分钟一个区块(注意只是大约,不是精确的10分钟),区块中存储的数据是最近的10分钟内发 生的交易 事务(最近的10分钟这个说法其实并不严谨,现在可以就这么理 解,在下面另有解释),可以理解为就是流水账。

大家看到这样的格式后,不知道是否有些似曾相识的联想,其实这样的数据格式,在生活中是有很多相似的;

比如工厂仓库的出入库记录,这个跟会计账本是类似的,还有家谱或者族谱,每一代人之间的关系是一个区块,到了下一代 又是一个区块,区块之间是父辈与子 女的关系连接,等等;而如果是计算机专业的朋友,一眼看上去,这不就是个线性表吗?是的,这就是比特币软件的主要数据存储格式,也是其他所有基于区块链技术的系统存取数据的格式。

这是一个很有趣的数据格式,它将连续不断的发生的数据分成了一个 一个的数据块,这样每个区块就都有自己的数字编号,也可以有自己的身份证号(通过哈希算法计算得到),在下载同步这些数据的时候,可以并行的从各个节点来获得,无论数据先后,到达本地后再根据区块号或者身份证号来组装起来就行 。

另外,这种格式是一种链条的格式,链条最大的特点就是一环扣一环,很难从中间去破坏, 比如有人篡改了中间的5号区块,那么如果要让数据看起来是完整的,就得同步把5号区块后续的所有区块都要更改掉,这个难度就大了,这也是区块链数据格式不可篡改的其中一个原因(当然了,如果仅仅只是本机的数据,也没什么不可篡改的,区块链系统真正的防篡改能力是通过无数个区块链系统运行的节点网络以及共识算法来实现的,这个在下面再介绍)。

这种格式还要个妙处,如果这个数据总是由一个人来记录的,那自然也没什么,但是如果放到网络中, 大家共同来记录这个数据,那就有点意思了,每个区块数据由谁来记录或者说打包,是可以设置一个游戏规则的,比如说掷骰 子,大家约定谁能连续3次掷出6,那就让他来记这个数据,为了补偿 一下他的劳动投入,奖励给他一些收益, 比特币正是使用了这样的原理来不断的发行新的比特币出来,奖励给打包的那个人的比特币就是新发行的比特币。

说到这里,大家觉得有点意思了吧?

1.2  一组技术的代表称呼

刚刚我们说了,区块链是一种数据的记录格式,可如果仅仅如此的话,实在不算是什么大不了的创新,事实上,在技术上区块链是一组技术的代名词,我们通常都说使用了区块链技术就是这个意思,那么既然是一组技术,那是由哪些技术组合起来的呢?我们来看一组关键词:

  • 公开密钥算法
  • 网络共识算法(挖矿)
  • 梅克尔数据证明
  • 可编程脚本合约
  • 区块链账本

1.公开密钥算法

属于计算机密码学⾥面传统的技术,公开密钥算法是⼀种不对称的加密算法,拥有两个密钥,可以互相加解密,通常其中的一个密钥是公开的称之为公钥,另外一个密钥是保密的称之为私钥;

2.哈希算法

也是属于计算机密码学中传统的技术,应⽤就更广泛了,主要⽤来对⼀段数据进行计算,得出⼀个摘要信息,通俗点说就是给一段数据⽣成⼀个身份证号;不同的消息生成的摘要数据是不⼀样的(某些抗碰撞能力弱的哈希算法可能在这⽅面会有些问题,但是使⽤广泛的⼀些知名的哈希算法,发⽣碰撞的概率很低),相当于给⼀段数据⽣成了一个身份证号这么个意思,在区块链系统中,哈希算法的使⽤很多,⽐如区块与区块之间,就是通过区块头的哈希关联起来的,⽽区块中的每⼀笔交易事务也都会⽣成⼀个哈希值作为交易易数据的ID,通过这些身份证号可以⽅便的检索或者关联区块,也能⽅便的指定某⼀笔交易事务。

哈希算法还可以用来生成梅克尔树,在下面我们再详细介绍,我们说了,哈希算法的特点是,只要目标数据有哪怕⼀点点的改动,生成的哈希值就会完全不不一样,因此可以⽤用来验证数据是否被改动过。

3.⽹络共识算法

在很久前就有计算机科学家研究过,并且提出过一些模型,⽐如拜占庭容错算法之类,比特币、以太坊这些使用的是⼀种工作量证明算法,其它的一些区块链系统有使用其他各种衍⽣的算法,⽽算法的原理都很简单,就是约定⼀个规则,通过共同执行这个规则,让每个分布式的节点数据都保持最终一致;

4.梅克尔数据证明

这是利用哈希算法将⼀组数据创建为⼀棵哈希树结构,⽤于验证数据完整性的一种结构,同时也应⽤在了轻量级钱包中。不同的区块链系统对梅克尔树的应⽤不尽相同,比特币中是⼆叉梅克尔树,比较简单,通过交易事务的哈希值两两配合生成一棵树,以太坊这种就复杂的多了,称之为梅克尔.帕特⾥夏树,这里暂时不赘述。

5.可编程脚本合约

什么叫合约?就是⼀组约定的规则,⽐如银行的结算系统,⼩明转账100给小王,在这么⼀个过程中,银⾏系统就会根据⼀组规则自动执行,规则包含⽐如检测⼩明的密码是否正确,余额是否⾜够,⼩王的账号是否正确,检测通过则分别更改两者的账户⾦额并写⼊事务⽇志。是的,这就是合约的意思了,当然,如果范围再⼴泛些,各种商业合约也都是这么个意思,因此可编程脚本合约也没什么好稀奇的,然⽽,如果将这种编程合约放到区块链的环境中,就⽐较有趣了,看两个特点:

第⼀个,区块链系统是⽆中⼼的分布式⽹络,没有边界

第⼆个,区块链系统通过⼀系列的技术实现了可信任⽹络

加起来,就是⽆边界的可信任⽹络,在这样的⼀个⽹络中执⾏既定的合约,成本低⽽而且安全,⽐特币在本质上也是属于这么⼀种脚本合约,只不过在⽐特币软件中,合约中处理的事情是⽐特币的转账,如果扩展这个概念,众筹、担保、分润等各种合约种类都能应⽤在这上⾯,⽤户也可以⾃行编写合约规则,以太坊便是这⽅面的⼀个典型代表,并由此带出了智能合约的应⽤。

这些技术的具体解释,我们在下⾯⼀一详述。

其中的【区块链账本】我们已经介绍过了,不再赘述,那么其他的技术都具体是什么意思呢,它们是怎么与区块链账本结合起来的?我们来一一说明一下:

1.3 创世应用“比特币”

说了这么多,我们知道,区块链技术反正就是一套软件开发技术,跟我们平时的网站开发技术、游戏开发技术、手机APP开发技术类似,只不过,与其他的开发技术不同的是,它能开发出一款软件,这种软件能制造“货币”出来,这就让人觉得有些不可思议了,比特币正是区块链技术的第一个应用软件,因此我们称它为“创世应用”。

正是比特币把区块链的技术理念带到了我们的视野中,虽然⽐特币的创始人中本聪⼀直都是⼀个谜,没有搞得清楚他到底是⼀个⼈人还是⼀个组织,但这些都不重要,重要的是⽐特币系统以⼀种极其天才的创新设计,解决了人们⼀直以来都难以解决的问题,那就是异步⽹络环境中实现数据的可信任共识的⽅案。我们抛开⽐特币这个货币的概念,纯粹站在软件或者⽹络的⻆度来看⼀下,假设我们是当初的中本聪,模拟⼀下当时的想法,⾸先,希望实现⼀套系统,可以联⽹,并且通过网络传递数据,如果是使⽤中心服务器这个结构的话,那显然是不够安全的,只要服务器上的数据损坏或者被攻击,系统等于就被瘫痪了,因此,决定采⽤分布式的结构,可是分布式结构有几个问题;

第一个,这些分布式的系统节点运⾏在哪呢,谁愿意提供计算机设施来运⾏行,靠⾃己来部署,那个成本就没底了;

第⼆个,分布式的节点,那么数据的⼀致性就是个问题,没有了服务器,数据来源也就没有权威的保证了;

第三个,怎么来验证⽹络中的数据呢?

对于第⼀个问题,站在经济⻆度,如果系统提供⼀种激励措施,让运⾏节点的⼈有利可图应该就能解决了,因此设计这个系统,得要有⼀个奖励或者激励的规则,在⽐特币中,打包区块的矿⼯工能够获得⼀定数量量的⽐特币奖励,这就是激励措施了。

对于第⼆个,这个问题是个难点,比特币要运⾏在公⽹上,各种情况都有,数据可能被篡改,⽹络可能不稳定,就连节点什么时候运⾏也不在控制之中,如何来解决这些问题呢?得要有⼀个机制,这个机制必须要有公正性,既然网络是可能不可靠不稳定的,那这个机制中就不能有太多对其他节点的依赖,得是⼀个主要依靠本机就能实⾏的⼀个做法。

换成是我,还真的很难想到⼀个好方法,传统的⼀些技术都有些问题,如果是在⼀个节点明确,网络也较为良好的场合,还好处理理⼀些,可是⽐特币的情况要⽐这个复杂的多。著名的CAP原理,阐述了这么⼀个结论:分布式计算系统不可能同时确保⼀致性、可⽤性和分区容忍性。看下这三个术语分别是是什么意思吧:

【⼀致性】:这⾥是指强⼀致性,发⽣在后⾯的事件能看到前⾯事件发⽣导致的结果

【可⽤性】:在有限时间内,任何⾮失败节点都能应答请求

【分区容忍性】:也就是说⽹络有可能发⽣分区,也就是说节点之间的通信不可保障不能同时确保,那就只能靠弱化某⼀个或者某两个特性,⽽而增强其中⼀个特性了。

中本聪在实现的时候,设计了⼀个工作量证明,很有意思,设置⼀个难度值,大家都通过⼀个类似于掷骰⼦的算法来命中⼀个结果,若结果符合预期的要求,就成功,成功者可以获得数据的记账权也就是区块数据打包,打包完毕后⼴广播给其他⼈,其他⼈验证后写⼊⾃己的数据中。

在这个过程中,由于使⽤的算法是⼀个类似于暴力破解的算法,除了靠提⾼计算机算力没有更高的办法去讨巧(这就⼀定程度上实现了⼀定程度的公正,当然了,⼟豪有能⼒购买更高性能的计算机设施,从⽽比普通⽤户更加具有抢得打包权的能力,这也是⼀个问题,不过⼀种技术总是只能解决⼀定范围的技术问题),但是大家需要注意的是,能够算出⼀个命中的值的,可并不⼀定只有⼀个⼈,如果出现了多个呢?那大家就只能进⾏区块的⼴播竞争了,谁被其他的节点接收的多,谁就被最终认可,⽽其他同样挖矿成功的就会被丢弃,从⽽得不到奖励。

因此,比特币中的这种数据⼀致性的算法是最终⼀致性而不是实时的⼀致性,这个大家⼀定要注意了。

对于第三个问题,怎么验证⽹络中的数据,在⽐特币⽹络中,每个节点都是独⽴的验证数据的,在验证过程不需要⽹络中其他节点提供依赖的服务。

2. 区块链技术栈

 

2.1 记录格式—区块.链

见【1.1  一个有趣的数据记录格式

2.2  网络结构-P2P

现如今,⼤概很少软件是单机版的了,就连输⼊法⽐如搜狗输⼊法、讯飞输⼊法也都是要通过联⽹来更新词库以及提供其他⼀些智能功能的,那么,既然是联⽹的软件,就避不开⼀个问题,那就是⽹络结构,就好⽐我们要造房⼦,总得设计下房屋的结构吧,砖瓦结构呢还是框架结构,单独的平⽅呢还是连⽚的⼩区。

迄今为⽌,⽆论什么样的⽹络结构,总体来区分⼀下的话,就是两种:客户端-服务器结构、P2P结构。

P2P也就是peer to peer的意思,中⽂点对点,也就是对等的意思。

区块链中的特点之⼀就是分布式,每个节点都维持完整的账本数据,可以独⽴的进⾏数据验证,独立的发送数据接收数据,彼此之间通过共识来实现数据的不可篡改和⼀致性,⽽每个节点都独⽴的按照规则做着⾃己的事情。任何⼀个节点的损坏或者图退出都不⾜以影响整个⽹络的正常使⽤,尤其当节点数量很多的事情,这也就避免了单点故障。

由于不存在⼀个服务器,也因此对等⽹络结构中的节点,是需要有⼀个认识彼此的机制的,这就是⽹络路由功能,简单来说,就是每个节点都会负责为其他节点提供地址信息,同时也会去索取和更新有效的节点地址。

就个⼈理解来说,对等⽹络结构最核⼼的就是⽹络共识机制,每个节点既当客户端也当服务器器,通过共识机制来协同。

2.3 同步机制-共识算法

区块链系统是对等⽹络结构,每个运⾏的节点都各⾃保存⾃⼰的数据副本,那么问题就来了,怎么来保证彼此之间的数据统⼀呢,既然没有⼀个中⼼服务器,⾃然也就没有⼀个传统意义上的权威数据来源了,⽽且对等⽹络中的每个节点都是平等的,那要是彼此的数据不⼀致,以谁的为准呢?这就要使⽤到⼀个同步机制,也就是共识算法。

共识算法的主要⽬的就是通过⼀种机制,使得⽹络中产⽣的数据让⼤家都能认可也就是所谓的共识,⽽对于那些⾮法的⽆效的数据会被丢弃掉,可以说,共识算法是确保区块链⽹络数据同步以及数据安全的重要环节。每⼀种不同的区块链系统都会有⾃⼰的⼀套共识算法,⽐如PoW(proof of work,⼯作量量证明)、PoS(proof of stake,权益证明)、DPoS(Delegated proof of stake,股份授权证明)、PBFT(Practical Byzantine Fault Tolerance,拜占庭容错算法)等等,很多,每种不同的算法也各有特点和优劣。

再具体说明之前,有朋友可能会有疑问,就算是对等⽹络,没有⼀个服务器来权威的提供数据来源,但只要节点之间彼此都连接,随时保持⼀致不就⾏了,如果是在⼀个⽹络良好的局域⽹中,并且运⾏的节点是受到严格的管理的,那⼤概也就没什么问题了,可事实上是,类似⽐特币这样的区块链系统是运⾏在互联⽹上的,⽽且谁也不能保证⽹络是个什么状况,甚⾄就连运⾏的节点什么时候启动什么时候会关闭掉都不知道,⽐如我们使⽤微信聊天,假设没有⼀个微信服务器存在,当⼩明发消息给⼩王时,⼩王正好没开微信,或者⼩王正好在地下停⻋场,没⽹络,那怎么办?种种情况,都不能保证节点之间能够随时连接在⼀起,因此区块链中的共识算法,要解决的是这样⼀个情况异常复杂的⽹络环境中的数据同步问题。

为了让⼤家⽐较能够形象的理解,我们还是以⽐特币为例,⽐特币中使⽤的是⼀种⼯作量量证明算法,其原理很简单,如下:

我们还是以⽐特币为例来说明,⽐特币中的⽹络共识算法的过程原理相对简单,理解了这部分,再去理解其他的共识算法就会⽐较有基础。

在⽐特币中,使⽤的共识算法是⼀种⼯作量量证明算法,说通俗点,⼤家通过⼀种竞争算法来抢夺区块数据的打包权,谁抢到了谁就能将发⽣的交易易数据打包成区块,并且⼴播出去,其他节点验证后没有问题就保存到⾃⼰的区块链账本中,这种竞争算法的原理很简单,系统会计算出⼀个难度⽬标值,然后⼤家通过对区块头进⾏⼀个加入了随机数的哈希计算,直到算出的值⼩于难度⽬标值,那就算是成功拿到记账权了,就跟掷骰子差不多意思,谁掷出了⼀组符合条件的数字谁就赢了。

有朋友可能问,那要是不⽌⼀个⼈算出了那么⼀个数字呢,以谁的为准呢?呵呵,这个时候,就要靠运⽓了,假如A和B都得到了符合条件的⽬标数据,都打包,都⼴播了,这个时候就看谁⼴播的范围最⼤,影响最⻓远了,最后⽐特币⽹络会保留⼴播范围最⼤的那个。

⼤家看到在这个⼩节的标题上放了个“挖矿”的字样,是不是共识算法都称之为是挖矿算法呢?答案是否定的。在这⾥之所以放⼀个“挖矿”的字样,是因为在不少的公链系统中,⽐如⽐特币、莱特币、以太坊等,都是通过这样的⼀个共识算法来发行新币的,怎么发⾏呢,就是奖励⼀定数量量的币给成功挖到区块的矿⼯。

2.4 完整证明-梅克尔树

梅克尔树是一种数据结构,跟区块链账本数据格式一样,是用于维护 一类数据的,区块链的账本格式是一条链,梅克尔树,顾名思义是 一种树结构,梅克尔树的目的是为了实现完整性证明,在不同的区块链系统中,对梅克尔树的使 用不尽相同,比特币中使用的称之为二叉梅克尔树,而比如以太坊系统中使用的则是梅克尔-帕特里夏树,相对来说, 二叉梅克尔树要简单许多,咱们就从简单的开始介绍吧,还是以比特币中的为例 。

既然是树结构,那就有一个个的树节点,那么比特币中的树节点中都是哪些数据呢?实际上,在比特币中,每个区块中都包含有一颗梅 克尔树,我们来看看,这棵树是怎么种出来的。

在每个区块中都包含有很多交易事务,每条事务都有一个身份证号,这是通过哈希算法计算而来的,可以唯一的表示某条事务记录,假如说某个区块中有6条事务记录,那我们就拿出6条事务记录的身份证号也就是哈希值,进行两两配对,然后分别再计算出两两配对的事务哈希值,依次往上,直到最后计算出一个根哈希,我们来看个图示:

 

 

在⽐特币中,每个区块都能⽣成⼀颗梅克尔树,是通过什么来⽣成的呢?是通过交易事务,在⼀个区块中,每条交易事务都会被计算⼀个哈希值,假设某个区块有4条事务,则如图所示,Hash1到Hash4就是这4条事务的哈希值,接下来再次对事务的哈希值两两哈希,直到最后⽣成⼀个根哈希,如此,⼀棵梅克尔树就⽣成了。那么,这样的⼀棵树⽣成后有什么⽤呢?

⾸先,⽐特币的节点在进⾏数据同步的时候,会向多个节点下载数据,这个时候,就会有个问题,怎么来验证获得的数据是完整的还是不完整的呢,是有问题还是没问题的呢?在点对点⽹络中进⾏数据传输的时候,显然并不只是从⼀台服务器上下载数据,⽽且其中的⼀些机器还可能是不稳定的,甚⾄是不可信的,这个时候,通过上述的⼀个⼤文件⼀个哈希值的⽅式就不太能起作⽤了。

然后通过梅克尔树,假设图中的2号事务数据下载有问题,则计算出的Hash12必然是与其他节点不⼀致的,很快就能定位到问题块,除了能够快速定位到数据块外,还有⼀个作⽤,就是对SPV(Simplified Payment Verification, 简单⽀付验证)的支持,我们知道,⽐特币核⼼钱包是要搭配完整的区块链数据使⽤的,包含了所有发⽣的交易事务,也因此,可以对接收或者发起的交易事务进⾏完整的验证,⽐如是否包含⾜够的余额,是否双花等,但是这种却也有个很⼤的问题,它必须要带上⼀个数据量很⼤的账本副本,这就限制了⽐特币钱包的使⽤,有时候我们只是想验证⼀下⽀付是否发⽣过就⾏了,完整的交易可以交给核心节点,那怎么办呢?可以通过如下的过程来实现:

1.  ⾸先下载完整的区块头数据,注意是区块头不是所有的区块链数据,区块头中包含有区块的梅克尔根

2.  如果是想要验证某笔⽀付交易,则计算出这笔交易事务的哈希值txHash

3.  找到txHash所在的区块,验证⼀下所在区块的区块头是否包含在区块链账本中

4.  获得所在区块中计算梅克尔根所需要的哈希值,注意我们并不需要所有的事务哈希值,如图所示,如果是要校验Hash1的话,我们只需要再搜集Hash2、Hash34即可

5.  计算出梅克尔根

6.  若计算结果与所在区块的梅克尔根相等,则⽀付交易是存在的。

7.  根据该block header所处的位置,还可以确定该交易得到了多少个确认

从中我们可以看到,梅克尔树是相当重要的。⼤家可以设想⼀下,这种结构还能应⽤在哪些场景下。

2.5 账户管理 -公开密钥算法

我们在使用通常的网络服务时,都会注册一个用户名,无论是使用淘宝、京东、微信等,还是玩网络游戏之类,都会去注册一个用户名,那么区块链系统中是怎么来注册用户名的呢?实际上在区块链系统中 一般是没有用户名这个概念的,而只有一个账户地址的概念, 无论是使用比特币还是以太坊还是其他的,基本都是通过一个地址来表示的,对于支持数字货币的区块链系统这个地址也称之为是钱包地址,那么这个地址是从何而来的呢?我们先来了解一下公开密钥算法:

这是⼀种加密算法,通常的加密算法,密钥只有⼀个,举个例子,我们希望对⼀串串数字进⾏行加密,约定将每⼀个数字都加上2,⽐如1,2,3,4,5就变成了3,4,5,6,7,如果有谁知道了这种加密⽅法,那同时也就知道了解密算法,这种⼀般称之为叫对称密码算法;

如果希望加密的⽅法与解密的⽅法是可以独⽴的且⽆无法互相直接推倒出来,那么,这种算法就是不对称加密算法,也就是所说的公开密钥算法,为什么叫公开密钥呢,因为这种拥有两种密钥,⼀个是保密的称之为私钥,⼀个是可以公开的,称之为公钥,使⽤用私钥加密的数据可以通过公钥解密,反过来使⽤公钥加密的数据可以通过私钥解密,⽬目前这种算法应⽤比较多的有RSA算法ECC椭圆曲线算法,前者是利用了⼤素数分解难度的原理理,后者是利用了椭圆曲线离散对数的计算难度,具体细节基于篇幅这⾥不再展开,区块链系统中,通常椭圆曲线算法应⽤的最多。

以⽐特币为例,⽤户可以在⾃己的钱包中创建地址,这个地址类似于银⾏账号,我们可以将⽐特币从⼀个地址发往另外⼀个地址,那么,这个地址从何⽽来的呢,实际上,从本质上来讲,并没有⽐特币地址这么⼀个东⻄存在,为什么这么说?⽤户在创建钱包地址时,实际上是创建了⼀对公钥和私钥,⽽所谓的地址只是公钥的⼀种格式化表示。 ⽤户通过私钥签名证明⾃己拥有某笔⽐特币,⽽通过公开的公钥可以验证⾃己的身份,只要⾃己通过私钥签名⼀笔交易或者签名⼀笔消息,任何⼈人都可以通过公开的公钥来确认是否是合法的用户。也就是说,公开密钥算法不但⽤来识别某个地址用户,也是⽤来完成交易事务的,不但是⽐特币,其他的区块链系统也是同样的原理。

2.6 智能合约-可编程状态逻辑

这是区块链系统⾮常重要的特点,我们知道,区块链系统可以创建⼀个可信任的⽹络,在这样⼀个可信任的网络中可以放心的通过⼀组代码编写的既定规则,转移数据的所有权,变更数据的状态。⽐特币⽹络中可以转移⽐特币,以太坊⽹络中可以转移以太坊还可以通过其他的智能合约实现按规则的状态变更。

这些到底是什么意思呢?

通常,在⼀个传统系统中,⽐如银⾏行的账户系统,是怎么来表明⼀笔钱是谁的呢?是通过账户和密码,⽐如⼩明转了了100元给⼩王,这100的⾦金金额数值就会写⼊到⼩王的账户,然后扣除掉⼩明账户⾥100,⼩王的账户只有通过⼩王⾃己的密码才能验证通过使⽤,这个逻辑看起来很正常,⼀直以来我们都是来的。然⽽而,区块链系统中却不是这么来实现的。

让我们来站在⼀个⽐较⾼的⻆角度来看待⼀下,以银⾏账户为例,⽆论是转账,存钱还是扣除费⽤等,不管是什么样的业务,对于账户来说,站在数据的层⾯,无⾮就是数据状态的不断变更,⽽每⼀次的变更都是通过⼀系列的规则验证的,这么⼀来,我们可以将这个账户看成是⼀个状态机,如下:

 

这个图很好理解,那么我们可以看到,最主要的不是状态本身,⽽是状态变更的触发条件,在这个图中,每个状态之间的变更都是有条件的,区块链系统中通常会怎么来实现这么⼀个条件的触发呢?我们以转账来说明:

1. 发送⽅发起⼀个转账交易,类似于开了⼀张⽀票,然后签上⾃⼰的名字(私钥签名)

2. 在⽀票上写上对⽅的账户地址(对⽅的钱包地址,我们知道钱包地址就是通过公钥转换⽽来的)

3. 向⽹络中发送这笔交易,每个节点都可以来验证这条交易是否有效(⽐如发送⽅的余额是否⾜足够,私钥签名是否合法等)

4. 节点如果验证没问题就能通过,这条交易事务最终会被矿⼯打包到区块(相当于正式的记了个账)

5. 接收⽅可以通过⾃⼰的私钥来验证⾃⼰对这条转账交易的拥有权(这句话⼀定要理解⼀下),通过⾃⼰的私钥和⽀票上的公钥转成的地址匹配,若能成功,就表明⾃⼰拥有这条交易事务转账的所有权,那么⾃⼰就能花这笔钱了。

这样的⼀个过程是通过什么来实现的呢,是通过⼀组脚本程序,在⽐特币中是⼀对锁定与解锁脚本,在以太坊中是更为复杂的编程脚本,总之,就是通过这样的程序逻辑实现了状态变更的触发条件,只要脚本程序写好,达到触发条件,程序就会严格的执⾏,刚正不阿,不留留半点情⾯面^_^。

那么,我们可以发现,这个程序,实际上相当于就是⼀份合约,大家约定了⼀个规则,符合规则了就照章办事,⽽具体是什么样的规则,这个是可以事先编写的(⽐特币中功能⽐较受限,⼀般也就能实现转账交易,以太坊则可以⾃定义编写各种合约规则),将这样的⼀份合约放在这样的⼀个去中⼼,分布式的环境中,由⽹络共识来保证不可篡改,这是多么创新的⼀个思路啊,这种可编程合约的思想可以⼴泛的应⽤于各种商业环境之下包括金融领域。

3. 应用特点

 

3.1 分布式网络

P2P⽹络本身就是⼀个分布式⽹络,区块链⽹络中并没有⼀个真正意义上的服务器,内部的运⾏逻辑也并不假设有服务器的存在。在区块链之前,也有过不少的分布式⽹络系统,⽐如⼤家很熟悉的电驴下载、BT下载,互联⽹初期的时候,⼤家都是到⽹站服务器去下载,下载的⼈多了,速度就会慢,因为占流量了或者说服务器更繁忙了,然而BT下载这种,确实下载的⼈越多,速度越快,我们不来详细的解析BT下载的具体技术细节,就光从⽹络结构上来讲,分布式的⽹络结构,使每个节点都既是使⽤者也是服务的提供者,也就形成了⼈多力量⼤的效果。

分布式⽹络中,首要的⼀个问题就是,如何保证数据的⼀致性,有些对数据的⼀致性要求不⾼⽐如⽹⻚资源,⽂件服务,早点晚点影响也不⼤;有些则希望在⼀个能承受的时间范围内达成⼀致,⽐特币就是这种,通常会建议发送⼀笔交易事务后,等待⾄少6个区块,原因就是6个区块后,数据基本上被⼤部分节点收纳的概率就很⼤了,还有⼀些对⼀致性的要求很即时,⽐如银⾏结算,不可能说要等段时间,账本才能⼀致,那对银⾏来说不能接受。

针对不同的使⽤场景,分布式⽹络也会不同的扩展,⼤家要注意的是,分布式⽹络并不是说完全没有中心,而是说在整个⽹络结构上是分散的,分布式的,但是每个单元还是有可能会存在中⼼的,毕竟在某些效率要求⾼的场合,中⼼结构的效率是最⾼的,这两者之间并不是互相对立的,⽽是互补的。

3.2 数据不可篡改性

我们可以反过来看⼀下,什么情况下数据是可篡改的。

⽐如数据都管理在⼀个服务器上,那⾃然是可篡改的,再怎么设置身份认证之类,只要突破进去就是⼀马平川了;

再⽐如数据虽然不在⼀个服务器上,但是对数据的验证是⼀个人说了了算的,⽐如现在很多的⽹站服务,⽐如各种电商⽹站啊,甚⾄包括银行(当然,不是说这些系统就会被随意的修改,这⾥只是参照⼀个例子),数据的管理权在⼀个管理员⼿中,数据怎么改并不需要得到其他不受⾃⼰控制的系统验证; 数据的记录权限在⼀个管理员⼿中,跟第二点类似,⾃⼰说了算;

区块链系统怎么保证数据不可篡改性的,对于第⼀点,区块链系统是分布式的,因此不存在⼀个明显的服务器目标;第二点,区块数据需要被⽹络中其他节点验证,⼤家都认可才会被记录在账本中由此达成共识,除非控制了大部分的节点,否则是不现实的;

对于第三点,区块链系统中使⽤各种共识算法,记账权不会掌握在⼀家⼿中,⽐如⽐特币的挖矿算法。

这种特性对于⼀些公众数据的记录是很有意义的,⽐如公证类数据,⽐如众筹账务,慈善款项等。

3.3 规则强制执行性

  • 代码即法律
  • 智能合约的条件执行

3.4  无边界价值转移

区块链网络可以创造一个可信任网络,可信任就表示有信用,而信 用是一切金融传递的基础

区块链系统可以自带金融属性,通过比特币的例子我们也能看到,它可以通过网络在全球各地进行转账交易,通过这种原理,不但可以传递货币,也可以传递其他任何的数字资产。

传统的比如游戏币,游戏道具,某平台的积分等,一定程度上也可以转移价值,但都是很难做到无边界传递的,而且其本身的信用程度也并不高,区块链⽹络⽆无边界,并且可以维持⼀个可信任的网络,这就为资产或者说价值的传递构造了一个成本相当低廉且传播很广泛的⽹络基础设施。

3.5  自治网络系统

这个其实是一个未来的愿景展望,可编程社会的一个基础模型

4. 应用场景

 

4.1 数字代币

比特币、莱特币、以太坊以及基于以太坊的各种合约代币

4.2 众筹合约

属于智能合约的 一种

4.3 跨境 支付

无边界的价值转移能力以及智能合约的特点,很适合应用在金融的跨境支付领域,目前的跨境支付手续繁杂,等待时间也很长,效率不  高,可以考虑在各国银行之间建立一个基于区块链的支付系统。

R3联盟

swift应用超级正本的fabric建立支付网络

4.4身份证明

使用区块链来构建身份管理系统

4.5去中心交易

目前的案例,Bitshares以及Openledger

基于区块链的交易系统,通过预言机创建链上资产,通过代码规则运行公开透明的交易逻辑

5.主流技术平台

5.1比特币

历史上第一个区块链系统,第一个加密数字货币系统,其他的系统基本都是在比特币的基础上开发的

5.2以太坊

数字货币+智能合约,既是一个数字货币系统,也是一个智能合约的开发平台

5.3超级账本

包含一系列的项目

比较著名的就是fabric,是一个面向商业的区块链系统开发框架,其本身其实并不是一个运行的区块链系统而是一套开发框架,一套开发用的半成品基础设施,是由Linux基金会主导的项目。
from:https://mp.weixin.qq.com/s/kuNtNekdsBYxoTtP6xxQqw