一、BTC-密码学原理

BTC是一种加密货币(crypto-currency)。但实际上BTC是不加密的,因为区块链上的交易都是公开的。

01 - 哈希

(1)collision resistance

  • 防止碰撞性

​哈希碰撞,即两个不同的输入用哈希函数算出来相同的哈希地址,X ≠ Y,H(X) = H(Y)。理论上无法证明存在哈希函数无碰撞,因为输入总是远大于输出空间的。例如MD5以前认为是无碰撞的但是后来被人们找出了碰撞的方法。(鸽笼原理 or 抽屉原理)

​一般来说没有什么高效的方法人为的制造哈希碰撞,除非brute-force即通过暴力遍历去算输入空间的哈希值直到找到要碰撞的那个输入。因此带来了防止篡改的特性,如果信息的内容被改变则那个哈希值就会发生变化。

​这条性质理论上是无法证明的,没有哪一个哈希函数可以在数学上证明是可以防止碰撞的,只能靠实践中的经验。

(2)hiding or one-way

  • 隐藏性或单向性

​哈希函数的计算是单向的不可逆的,哈希值没有泄露输入的任何信息。通过蛮力求解,在输入空间足够大分布较为均匀时不可取。

以上两者性质结合:digital commitment(数字认证)

​也称digital equivalent of a sealed envelope(密封信封的数字等价物)。例如在预测某件事的发生结果问题上的做法是,把预测的结果计算出一个哈希值,把哈希值公布出去。因为hiding 的性质人们是无法得知预测的结果,等到预测结果公布验证预测时,因为collision resistance的性质所以预测结果没有被篡改过。这里为满足hiding性质里的输入空间足够大,要在输入的后面加上一个Nonce(随机数)。

(3)puzzle friendly

  • 谜题友好性

​哈希值的计算事先是不可预算的,例如要求哈希值要落到某一范围内。

​关于比特币挖矿:实际上是找一个Nonce(它属于block header)和区块块头里的其他信息合在一起作为输入取出一个哈希值,这个哈希值要小于等于某特指定的阈值,H(block header) <= target。所以挖矿没有捷径只能靠不断尝试不同的nonce,这个过程产生了工作量证明(proof of work)。挖矿很难,验证很容易。

​比特币中用的哈希函数是SHA-256。

02 - 加密与签名

​BTC中的去中心化开户是创建一个pubilc key和private key的过程,其中(pubuilc key,private key)代表了一个账户。公钥和私钥来自非对称的加密方式(asymmetric encryption algorithm)。产生公私钥要有好的随机源。一般先去哈希然后再签名。

​加密:使用接收方的公钥进行加密,接收方使用自己的私钥进行解密,公钥可以公开,私钥不公开本地保存。

​签名:使用发送方的私钥进行签名,接受方使用对应公开的公钥进行验证。

二、BTC-数据结构

hash pointers:哈希指针 普通指针:存储某个结构体在内存中的地址。P-> 哈希指针:存储某结构体的地址和哈希值。H()-> 哈希指针不光能找到结构体的位置,而且还能检测结构体的值有没有被篡改过。

01 - Blockchain

  • 区块链

​一个一个区块组成的链表,和普通链表的区别是采用哈希指针代替普通的指针。

1.png

​采用这种结构的好处:取哈希时是把前一个区块的整个区块的内容合在一起取哈希,可以实现tamper-evident log(防篡改日志),篡改某一区块的内容后面的哈希指针就无法正确链接,因此后面的区块的哈希都要发生变化,直到最后系统保留的哈希H()也要被修改。这样只要有最终保留在系统的哈希值,都可以算出哪一个区块发生了改变,牵一发而动全身。可以只保存部分区块,需要再往前的区块可以向其他节点索要。

02 - Merkle tree

  • 默克尔树

​和普通的binary tree相比就是用哈希指针代替了普通指针,只要记住根哈希值,就可以推测出对树中任何位置的修改。

BTC中各个区块用哈希指针链接在一起,每个区块的所有交易是以默克尔树的形式组织在一起。

2.png

​作用是提供merkle proof(默克尔证明)交易到根节点的路径。每个区块分为两部分:块头(block header)用来存储根哈希值和块身(block body)用来存储交易列表。比特币中的节点分为两类:

​(1)全节点(full node),保存整个区块的内容,即block header和block body。

​(2)轻节点(light node),例如手机上的BTC钱包,只保存一个block header。通过merkle proof证明交易存在且成功是通过验证全节点提供的哈希值与之拼合计算上层哈希值直到算到根节点然后和轻节点中的block header存储的根哈希值比较即可验证。

​系统中大多数是轻节点。

三、BTC-共识协议

加密数字货币,存在“双花问题”或称“双花攻击 ”(double spending attack),是指数字资产具有可复制性一笔钱可能被多次消费。

01 - 如何验证交易的合法性

​维护一个数据结构(区块链),由所有的用户共同维护。

3.png

​BTC系统中都包含了输入和输出两部分,输入部分要说明币的来源,输出部分要给出收款人的哈希地址。币的来源指向也是一种哈希指针,说明币的来源可以防止凭空捏造和“双花问题”。BTC中收款的地址是通过接收方公钥推算出来的,地址相当于银行账号。接收方要知道发送方的公钥(所有节点都要知道)因为要验证签名,而这个签名是输入时给出的,输入除了要说明币的来源还要给出公钥,这个公钥还要和它来源里给出的公钥相一致来防止伪造(脚本运行实现)。

(1)Block header:包含的是区块的宏观信息。例如:使用的是BTC哪一个版本的协议(version),指向前一个区块的哈希指针(hash of previous block header),默克尔树的根哈希值(merkle root hash),与挖矿相关的:难度目标阈值(target)、随机数(nonce)。

(2)Block body:交易列表(transaction list)。

​取哈希时是对整个Block header取哈希。

02 - distributed consensus

  • 分布式共识

(1)拜占庭将军问题(Byzantine failures),是由莱斯利·兰伯特提出的点对点通信中的基本问题。含义是在存在消息丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。

(2)CAP理论:Consistency(一致性),Availability(可用性),Partition tolerance(分区容错性),任何一个分布式系统最多只能满足两个性质。

03 - Consensus in BitCoin

  • 比特币中的共识协议

hyperledger联盟链、sybil attack女巫攻击

4.png

​BTC是用算力来投票,每个节点都可以组装一个候选区块,然后尝试各种nonce值,获得记账权(向BTC去中心化的账本里写入下一个区块),只有获得记账权的节点才能发布下一个区块。其他节点收到后验证合法性。

(1)出现分叉(forking attack分叉攻击),最长合法链原则,接受的区块应该是在扩展最长合法链。

(2)等长分叉,维持一段时间直到一方分叉抢先发布下一区块,另一方则被丢弃。

04 - 谁有权力发行数字货币

​发行货币是由挖矿决定的。获得记账权的节点,会有块奖励(block reward),可以获得一个特殊的交易(铸币交易-coinbase transaction)可以发布一定数量的BTC,这是BTC系统中发行货币的唯一方法,其他交易都是已有BTC的交易。

​BTC刚上线时每一个区块可以产生50BTC,21万个区块之后奖励减半,以此类推。设计的平均出块时间是十分钟,大概4年时间产生21万区块然后奖励减半。

​总结,取得的共识是去中心化账本里的内容,而只有获得记账权的节点才有权力写入区块,获得记账权的途径是挖矿。

四、BTC-系统的实现

01 - 概念

​区块链是一个去中心化的账本,BTC是采用基于交易的账本模式(transaction-based ledger)转账交易、铸币交易,但并不显示的记录账户的金额。BTC的全节点要维护一个UTXO(Unspent Transtion Output-未使用的交易输出)的数据结构。UTXO要给出产生这个交易输出的哈希值以及在此交易中是第几个输出,目的是为了检测”双花问题“。

​每个交易会消耗掉一部分输出同时也会产生一些输出,所有输入金额的总和要等于输出金额的总和(total inputs = total outputs),这之中会有交易费(transaction fee)给获得记账权的节点,交易费的金额相对较小甚至没有。矿工挖矿的主要目的还是获得初块奖励。ETH是基于账户的模式(account-based ledger),需要显示的记录账户上的金额。

02 - 演示

5.png

6.png

7.png

8.png

​由于挖矿难度的不断增加,只调整nonce的值很大概率无法满足要求,这里还可以调整默克尔树的根哈希值,CoinBase的值可以任意。

9.png

10.png

11.png

​挖矿时尝试nonce可以看作是Bernoulli trial:a random experiment with binary outcome(伯努利试验:具有二元结果的随机实验),过程为Bernoulli process:a sequence of independent Bernoulli trials(伯努利过程:一系列独立的伯努利试验),具有memoryless(无记忆性),挖矿可以看作Poisson process近似。出块的时间是expoential distribution(指数分布)。

12.png

​ 所有BTC的总量2100万。挖矿对维护BTC系统的安全性至关重要。它并不是解决某一数学难题,只是在比拼算力,不产生实际意义,越来越难挖是人为造成的。Bitcoin is secured by mining(比特币通过挖矿获得保障),是通过算力投票的有效手段。

13.png

​BTC要等6个confirmation,此时认为交易就不可篡改,不可篡改是概率性的问题。selfish mining攻击。

五、BTC-网络

​用户把交易发布到BTC网络上,节点收到这些交易后把它们打包到区块里,然后把区块发布到BTC网络上。BTC协议工作在应用层,底层是P2P的网络层。BTC的P2P网络是简单的,所有的节点是对等的(有的P2P网络有超级节点或主节点)。

application layer: BitCoin Block chain


network layer: P2P Overlay Network

​要加入该网络要知道一个种子节点(Seed node),然后和种子节点联系,种子节点会告诉它所知道的其他节点。节点之间是通过TCP进行通信的,有利于穿透防火墙。离开时不用做任何操作,不用通知其他节点,退出应用程序即可,其他节点在一定时间收不到消息就会删除。

​BTC设计的原则是简单,健壮但不高效 (simple, robust, but not efficient)。每个节点维护一个邻居节点的集合,消息传播在网络中采取flooding(泛洪)的方式,节点在听到某个消息的时候传播给它所有的邻居节点,同时记录该消息已经记录过,下次再收到该消息就不用转发给邻居节点,邻居节点的选取是随机的没有考虑底层的拓扑结构。健壮性很强但是牺牲了一定的效率,例如你像身边的人转账和像美国的朋友转账速度是基本一样的。

​BTC系统每个节点要维护一个等待上链的交易的集合,第一次听到交易广播之后把这个交易加入集合并且转发这个交易给邻居节点,转发的前提是该交易是合法的。

14.png

​新发布的区块和新发布的交易在网络中的传播方式类似,除了要检测区块的内容是否合法外还要检测是否在最长合法链上。越是大的区块在网络上传播的速度越慢,BTC对区块大小的限制是1MB。传播是best effor(尽最大努力的)。线上系统解决不了线下问题。退款之类属于产生了新的交易。

六、BTC-挖矿难度

​H(block header) =< target,target是目标阈值,阈值越小挖矿难度越大,调整挖矿难度就是调整目标空间在整个输出空间所占的比例。比特币用的哈希算法是SHA256,产生的哈希值是256位,所以产生的输出空间的大小是2∧256的取值范围。通俗的说就是调整哈希值前面有多少个0。挖矿难度和目标阈值是反比关系。

15.png

​这里的difficulty_1_target是指挖矿难度为1的时候对应的目标阈值,挖矿难度最小为1,对应的目标阈值是一个非常大的数。调整挖矿难度是应对算力越来越强,从而控制出块速度,控制在大约10分钟。如果出块的时间太短,网络传播速度较慢时其他节点无法响应,会出现更多的分叉。分叉如果过多,对达成共识是没有好处的。51%攻击,恶意节点掌握51%的算力,让恶意链比正常链长。

​ETH的出块时间在15秒,因而有新的协议ghost,orphan block(孤儿块)不能简单的丢弃,而是也有一定的奖励。ETH同样需要调整挖矿的难度,使得出块难度保持一定。无论出块时间设置为多少,都需要保持一定的稳定性而不能无限的缩小。

16.png

​BTC规定每隔2016区块要重新调整目标阈值,大概是每两周调整一次,调整公式:

17.png

​实际时间/预期时间,实际代码中有最大4倍的限制。计算公式是写在BTC系统的代码里的,每挖到2016个区块就会自动的调整。

代码开源,恶意节点不调整,诚实的节点不会认可。

18.png

七、BTC-挖矿

01 - 全节点

19.png

02 - 轻节点

20.png

03 - 安全性

(1)密码学上的保证。他人无法获得私钥没有办法伪造签名,前提是系统中拥有大多数算力的矿工是好的是遵守协议的,不会接受没有合法签名的交易。

(2)共识机制。

04 - 挖矿的设备

​设备越来越趋于专业化,最早是用CPU(通用计算能力强)挖矿但是性价比太低。然后使用GPU挖矿但还是浪费(GPU有强大的通用并行计算能力),用来挖矿仍然有很多部件被限制。然后又使用ASIC(Application Specific Integrated Circuit-专用集成电路)为了BTC计算哈希值计算而生,但是专用的矿机的获利周期性价比也低。mining puzzle\Alterbative mining puzzle

​挖矿的另一个趋势是大型矿池的出现(单个矿工任务重、概率小)。矿池的架构是一个全节点会驱动很多矿机,一个矿池会有一个矿主(pool manager)下面有很多的矿工,矿工只负责计算哈希值,而全节点的其他任务由矿主承担。矿池一般分为两类:第一类是像大型的数据中心一样,矿机属于同一个矿主;第二类是分布式的,矿工的矿机和矿主不在同一个地方,矿工要加入矿池是根据一定的协议和矿主进行联系,矿主把要计算哈希值的任务分配给它,矿工计算完后把计算结果返回给矿主,当有出块奖励的时候参与分红。矿池的出现还为了解决收入不稳定的问题,单个矿工的收入是不稳定的,大家合伙干有了收入进行分配。

​收益的分配是根据工作量进行的,提交almost valid block(几乎有效,也就是近似的结果)这样根据提交的share工作量进行分配。这样做的原因:每个矿工挖到矿的概率取决于尝试nonce的数目,尝试的越多能够找到的share越多,所以可以作为做了多少工作的衡量。

​关于一些问题:矿工是不可能私吞发布挖到的区块的,每个矿工的任务是由矿主分配的,矿主负责主装好一个区块,然后交给矿工去尝试nonce计算,而且还要调整其他值,给矿工的是一个尝试的范围,区块中有一个收款人的地址是矿主的地址(奖励的地址是矿主的)私吞了也不会得到奖励。另外要是私自改收款地址这时提交矿主的share就不会被认可,因为交易列表发生了变化。矿主会收取一定比例的管理费。

​矿池的出现的弊端是具备51%攻击能力的可能性大大增加,还可能抵制某一账户。好处是减少了矿工的负担,收入分配更加稳定。

八、BTC-脚本

  • The BitCoin Scripting Language

​BTC使用的脚本唯一能访问的内存空间是一个堆栈,是基于栈的语言。

21.png

22.png

​一个交易可以有多个输入和多个输出,所以一个交易中可能有多个签名。另外有的交易有多重签名。

23.png

24.png

25.png

​前期是两个脚本交叉拼接在一起执行验证,后来为了安全性的考虑两个脚本单独执行,首先执行输入脚本如果没有出错再执行输出脚本如果栈顶结果为0即true则验证通过交易合法。多个交易全都验证通过才能证明这个交易是合法的。

01 - P2PK

  • Pay to Public Key

26.png

27.png

02 - P2PKH

  • Pay to Public Key Hash(这是最常用的一种形式)

28.png

29.png

30.png

03 - P2SH

  • Pay to Script Hash(最复杂的一种形式)

31.png

32.png

33.png

34.png

35.png

04 - 多重签名

36.png

37.png

  • P2SH实现多重签名的本质是把复杂度从输出脚本转移到输入脚本。

38.png

39.png

40.png

41.png

05 - Proof of Burn

42.png

​这是销毁BTC的方法。AltCoin Alternative Coin(除BTC以外小的加密货币),要求销毁BTC获得小币种。

​OP_CHECKSIG

九、BTC-分叉

**原因一:**系统中的两个节点差不多同时挖到了区块,这时会产生一个临时性的分叉,这种分叉称为state fork(状态叉)。

**原因二:**分叉攻击(forking attack)也属于state fork。也是对当前的状态产生了意见分歧,只不过分叉攻击的分歧是故意造成的,所以也称(deliberate fork)。

**原因三:**BTC的协议发生了改变,修改协议需要软件升级,在一个去中心化的系统中要升级系统,没有办法保障所有的节点都升级软件,称为(protocol fork)。根据升级协议的不同可以进一步分为:

01 - 硬分叉

  • hard fork

​对BTC新增一些新的特性或拓展一些新的功能,没有升级协议的旧节点是不认可这些新协议的,认为这些新特性是非法的,对BTC协议的内容产生了分歧从而产生了分叉。例如BTC中的区块大小限制。

​硬分叉是永久性的,只要这部分旧节点不更新软件分叉就不会消失。总结,新节点发布的区块旧节点不认可,旧节点发布的区块新节点不认可。案例:以太坊的ETC和ETH。

43.png

02 - 软分叉

  • soft fork

​对BTC的协议加入一些限制,原来合法的现在在新的规定下是不合法的了,会引起软分叉。

​分叉是临时性的,旧节点不更新协议会白白挖矿。总结,新节点发布的区块新旧节点都是认可的,但是旧节点发布的区块新节点是不认可的。例如,给协议中某些域赋予新的含义,铸币交易里的coinbase域没有规定现在有提出新想法。案例,P2SH:Pay to Script Hash

44.png

十、BTC-问答

  • 1、转账交易时对方不在线怎么办?

答:转账交易时不需要接收者在线,转账交易只是在区块链上记录下把我账户上的钱转到他的账户上,当时对方有没有链接在区块链网络上是没有关系的。

  • 2、假设某个全节点收到了一笔转账交易,有没有可能这个交易的账户是以前从来没有听说过的?

答:可能,BTC在创建时是不需要通知其他人的,在本地产生一个公私钥对就可以,只有在以后的收款地址第一次收到钱的时候,其他节点才知道这个账户的存在。

  • 3、如果账户的私钥丢失怎么办?私钥泄露了怎么办?

答:私钥丢失之后是没有办法的,账户上的钱就变成了死钱。私钥泄露要尽快的转到另外的一个安全的账户上。

  • 4、如果转账的时候写错了地址怎么办?

答:没有办法取消已经发布的交易,如果知道对方的身份可以尝试联系转回。地址是公钥的哈希产生的。

  • 补充:OP_RETURN是在当前交易的输出脚本里,这个输出脚本在本次的验证中是用不到的是不会被验证的虽然它无条件的抛出错误。

  • 事件:Mt.Gox门头沟事件。

十一、BTC-匿名性

  • Bitcoin and anonymity

​BTC不是真正的匿名,是使用的一种化名。如果银行可以使用化名,那么它的匿名性会比BTC要好,银行的账本是不公开的,BTC的账本是公开的大家都看的到。

BTC什么情况下会破坏匿名性?

01 - 多地址关联

​生成了很多化名的地址账户但是有可能被关联起来,例如输入地址和输出地址通过推理关联起来的时候。所以可以制造一些没有必要的输出,但是像找零地址等目前基本都是BTC的钱包生成的,没有制造非必要输出的环节。

02 - 现实关联

​账户地址交易时和现实世界产生关联,例如法币和BTC之间的转入转出。用BTC购买实物交易的时候因为账本是公开的容易被行为分析找到个人的信息。

​所以BTC的匿名性不是绝对的。匿名性保持的最好的是中本聪,因为他没有花过BTC。

hide your identity from whom?

03 - 保持匿名性

(1)网络层上:IP地址和现实世界是有很大关联性的,解决的普遍方法是多路径的转发(例如TOR洋葱路由就是这个原理),中间的节点只知道上一层的节点但并不知道最早发出者。

(2)应用层上:coin mixing,原理就是把身份和周围的人混在一起,达到混淆的目的。但是做混淆的机构大多数是缺乏信任的容易跑路。在线钱包有的也具有coin mixing。加密货币的交易所自带coin mixing的特性。

​匿名性难做的本质原因是区块链是公开的而且是不可篡改的。

04 - 零知识证明

​是指一方(证明者)向另一方(验证者)证明一个陈诉是正确的,而无需透露除该陈诉是正确的外的任何信息。

05 - 同态隐藏

  • 零知识证明的数学基础

45.png

06 - 盲签方法

46.png

07 - 零币和零钞

47.png

​与实体发生交互的时候仍然会产生匿名漏洞。

十二、BTC-思考

01 - 哈希指针

​BTC中很多地方用到了哈希指针,例如区块的块头包含指向前一个区块的哈希指针。指针保存的是本地内存的地址,只是在本地这台计算机上有意义,发送到其他的计算机上就没有意义了。那么在发布区块时哈希指针是怎么通过网络进行传输的呢?真相是所谓的哈希指针只是一种形象的说法,实际在使用的时候只有哈希没有指针。

48.png

  • 如何找到前一个区块的内容?

​全节点一般是把区块存储在一个键值对里(key, value),常用的键值对数据库是leavel DB。所谓的区块链的链表结构实际是键值对数据库通过哈希值串起来的。只要掌握了最后一个区块的哈希值,通过leavel DB的查找哈希值对应的key的value就可以把区块的内容取出来,通过header里前一个区块的哈希值可以继续向前找。可以理解为哈希值本身就是指针。

  • 区块恋

买的币会永久的存在UTXO中

  • 多个合伙人不要用截断私钥的方法,要用多重签名。MULTISIG多重签名还可以规定N个签名给出M个就可以。

02 - 分布式共识

​理论上证明分布式系统上取得共识是不可能的。为什么比特币系统能够绕过分布式共识中那些不可能结论?严格的说比特币没有取得真正意义上的共识,比如出现了分叉攻击。理论和实际往往是有一定的距离的,理论上不可能的结论可能只是在特定的模型下,现实生活中把模型改一改实际不可能会变成可能。

03 - 比特币的稀缺性

​稀缺的东西是不适合用来做货币的,一个好的货币是要有一定的通货膨胀的功能的。

04 - 量子计算

​量子崛起首先受到威胁的是传统金融行业,现有的传统支付手段将会变的不安全,当然也会孕育而出量子加密的算法。另外BTC中的公钥也没有直接暴漏出来,而是对其取一个哈希地址。

十三、ETH-概述

​比特币被称为区块链1.0,以太坊被称为区块链2.0。以太坊在设计的过程中针对比特币的一些问题进行了改进,例如出块时间,比特币的出块时间大概在10分钟而以太坊的出块时间大概只有十几秒,为了应当这个出块时间以太坊设计了一套ghost共识机制,还改进了挖矿使用的mining puzzle,比特币比拼的是计算哈希值的算力这会造成挖矿设备的专业化,以太坊设计的mining puzzle对内存的要求是比较高的,被称为memory hard mining puzzle,以后会升级为用权益证明代替工作量证明,proof of work -> proof of stake不挖矿,而是类似于股份投票制决定下一个区块是如何产生的。以太坊还增加了一个重要的功能是对智能合约的支持smart contract。

什么是/ 为什么搞智能合约?比特币是去中心化的货币。以太坊的出现增加了去中心化合约的知识。

BitCoin:decentralized currency

Ethereum:decentralized contract

十四、ETH-账户

​BTC中使用的是基于交易的账本,这种模式下系统中并没有显示的记录账户的余额,想知道余额可以通过UTXO中的数据推算。

49.png

​以太坊采用的是基于账户的模型account-based leger,系统中要显示的记录有多少个以太。转账的时候不用说明币的来源,而这种基于账户的模式对double spending attack有天然的防御作用。余额是系统中要维护状态,不是自己产生保管的。

​replay attack(重放攻击),双花攻击是指花钱的人不诚实以前花过的钱现在在花一遍,重放攻击时收钱的人不诚实别人已经转过的钱再转一次。为预防重放攻击,加一个计数器nonce,记录一下这个账户有史以来一共发布了多少个交易,转账的时候交易次数要成为交易内容的一部分都受到交易签名的保护。全节点要维护这个状态。

以太坊中有两类账户。

01 - 外部账户

  • externally owned account

​类似BTC的本地账户,是一个本地产生的公私钥对,谁有私钥就有这个账户的控制权,也称为普通账户。一个外部账户的状态有balance(余额)、nonce(交易次数)。

02 - 合约账户

  • smart contract account

​合约账户不能主动发起一个交易,有balance、nomce(调用次数)、code(代码)、storage(相关的状态,包括每个变量的值)。以太坊规定交易只能由外部账户发起,这个交易如果调用一个合约账户,这个合约账户可以发送一个消息来调用另外一个合约。创建合约账户的时候会返回一个地址,知道合约的地址就可以调用这个合约。

为什么要设置这样一个账户?因为有智能合约,所有要求身份的稳定。financial derivative 金融衍生品

十五、ETH-状态树

​状态树实现的功能是从账户地址到账户状态的映射,addr -> state。以太坊中用的账户地址是160位即20字节,表示为40个16进制的数。状态是指外部账户和合约账户的状态包括余额、交易次数,对合约账户还包括代码和存储。

  • 使用哈希表可以实现吗?

​假设系统中的全节点维护一个哈希表,有新的账户则直接插入到哈希表内,查询账户余额直接在哈希表中查询在不考虑哈希碰撞时查询是在常数时间内完成的,同样更新在哈希表中也是比较容易进行的。

  • 如果需要提供merkel proof如何提供?例如要和对方签合同需要对方证明他的账户余额。

​把哈希表中的内容组织为一颗merkel tree然后算出根哈希值,根哈希值保存在block header里,根哈希值只要是正确的就可以保证下面的树没有被篡改。

【问题所在】:如果有新区块发布怎么办,新区块就会有新交易就会使哈希表的值发生变化,然后发布下一个区块的时候再重新组织为merkel tree,这样做的代价是非常大的,实际发生状态变化的账户只是一小部分。

  • BTC每发布一个区块也要构造默克尔树为什么没有这个问题?

​BTC的merkel tree是组织起来的交易,区块发布之后就不会发生改变,而且区块最多只有4000个交易实际上都是比4000要少的。而这里是要把所有的以太坊账户构建为merkel tree这个数目就会高出好几个数量级。

不使用哈希表,直接把所有的账户构建为一颗merkle tree,改的时候只在树上做修改。

【问题所在】:merkel tree没有提供一个很好的高效的查找和更新的方法。

  • 要不要排序?

​不排序查找的速度会慢,不能证明包不包含在里面。再有叶结点是账户,如果不排序每个全节点构建出的树是不一样的,算出的根哈希值也是不一样的。BTC中也不排序,每个全节点收到的交易也是不一样的,但是最后是获得记账权的节点说了算。如果以太坊也这么做,需要把账户的状态发布到区块里,而账户状态是可以维护在本地的,而且大多数账户状态是不变的,每个交易涉及的账户只是少部分,要发布的主要内容是交易。要是排序,新加入的账户,树的结构可能就会发生变化,又变成了需要生成新的树。

01 - trie(retrieval)

  • 字典树/前缀树

​优点:① 每个节点的分支数目取决于key的取值范围,在以太坊中地址是表示为40个十六进制的数,所以分叉数目有17个,0~f加上结束标识符。② 查找效率取决于key的长度。③ trie不会出现碰撞。④ 输入不变不论顺序得到的是同一颗trie。⑤ 更新的局部性好。

​缺点:存储比较浪费,会出现一脉单传的情况。

50.png

02 - Patricia tree/trie

  • 压缩前缀树(PT)

​树高度降低,访问内存的次数减少,效率提高。路径压缩在键值比较稀疏的时候,效果比较好。

51.png

03 - Merkle Patricia tree

  • MPT

​以太坊使用Modified MPT,对原生的MTP做了些修改。

​所有的账户组织成一个Patricia tree,用路径压缩提高效率,然后把普通指针换成哈希指针,所以可以计算出一个根哈希值,这个哈希值要写入block header里。这个根哈希值可以防止篡改,还可以证明账户上的余额,可以证明某个键值是不存在的。以太坊的块头里有三个根哈希值。

52.png

​每次发布一个新的区块的时候,状态树中有一些节点的值会发生变化,而这些改变不是在原地改动而是新建一些分支,原来的状态被保留下来。合约账户的存储也是用MTP保存,存储也是一个键值对,是变量到变量取值的映射。以太坊的数据结构是一个大的MTP里面包含很多小的MTP,每一个合约账户的存储都是一个小的MTP。所以系统中的全节点不是维护一颗MTP,而是每次出现一个区块都要新建一个MTP,只不过这些状态数中的大部分节点是共享的,只有少数发生变化的节点需要新建分支。

  • 为什么要保留历史状态?

​系统中有时会出现分叉,以太坊的出块时间降到十几秒,出现临时分叉是一种常态。未胜出的节点要回滚roll back,回滚就需要维护这些历史记录。以太坊不能通过简单的推测回到前一个状态,因为有智能合约,智能合约是图灵完备的。

53.png

代码的数据结构:

54.png

55.png

56.png

​账户的状态(value)是经过序列化之后存储在状态数上的,用RLP:Pecursive Length Prefix编码做序列化之后再存储。RLP的理念是越简单越好,它只支持一种类型nested array of bytes(字节数组)。

十六、ETH-交易树和收据树

​交易树也是一颗默克尔树和BTC中的情况是类似的。每个交易执行完毕之后会形成一个收据记录这个交易的相关信息,交易树和收据树上面的节点是一一对应的。增加收益树是考虑到以太坊的智能合约执行比较复杂,有利于快速查询执行的结果。数据结构上看交易树和收据树都是MPT。(MPT也是一种默克尔树,使用MPT也便于查找)交易树和收据树是只把当前交易组织起来,而状态树是要把系统中所有账户都要包含进去不管这些账户和当前这些交易有没有关系,多个区块的状态树是共享节点的,而每个区块的交易树和收据树是相对独立不会共享节点的。

​交易树和收据树的作用:① 提供证明,证明某个交易被打包到交易中(像轻节点提供证明);② 以太坊还提供更加丰富的查询功能,例如查询过去十天和某个智能合约相关的交易。以太坊中引入了bloom filter这个数据结构,支持高效的查找某个元素是不是在某个比较大的数据结构中,算法思想是给一个比较大的集合计算出一个紧凑的摘要,查找时可以取哈希在对应的摘要位置对比查看结果,使用bloom filter可能会出现false positive,即可能出现误报但是不会出现漏报。bloom filter的局限性是不支持删除操作(原因是影响其他元素的映射)。还有修改过的bloom filter解决了不能删除等的问题,更加复杂。

​每个交易执行完后会产生一个收据,收据里就包含了这个交易的类型和地址等其他信息,发布的块头里也有一个总的bloom filter,这个总的bloom filter是所有交易的bloom filter的并集。用处是便于查询,可以过滤到大量无关区块。

​三棵树的根哈希值都是包括在块头里面的。以太坊的运行过程可以看作一个交易驱动的状态机transaction-driven state machine,状态机的状态就是所有账户的状态即状态树中包含的内容,交易是每次发布区块中包含的交易,通过这些交易会驱动系统从当前这个状态转移到下一个状态。如果BTC看作状态机那么它的状态是UTXO那些没有被花掉的输出。状态转移都得是确定性的,因为所有的全节点都得执行同样的状态转移。

​如果状态树只包含交易相关的账户,这样设计每个区块没有完整的状态树,想要查找某个账户的状态就不方便了。如果某个转入账户是新创建的账户,如此设计只有往前查询到创世纪块处才会发现是个新建的账户。

代码:

57.png

58.png

59.png

60.png

61.png

62.png

63.png

十七、ETC-GHOST

延用BTC的共识协议会出现很多问题。

64.png

​以太坊中采用了一个基于GHOST协议的共识机制,但是GHOST不是以太坊发明的,以太坊对其进行了一些修改。GHOST协议的核心思想是:挖到了一个区块但是被作废了,但是也能得到一些出块奖励,这些区块叫做uncle block,以后发布的区块可以包含这些叔父区块,这样叔父区块会获得7/8的出块奖励,而包含了叔父区块的新块会额外获得1/32的奖励,一个区块最多可以包含两个叔父区块。这样设计有利于鼓励系统中出现分叉及时进行合并。这样设计的缺点是:当出现第三个分叉则无法获得收益;可能被恶意不被包含。

65.png

​修改GHOST协议-1:再往后的区块仍然可以把没有包含进来的叔父区块认作叔父区块包含进来,会得到相应的奖励。

​修改GHOST协议-2:只有包含规定代数之内的叔父区块才会有奖励,而且越久远奖励越少,即叔父区块的定义是当前的区块在7代之内有共同的祖先,即只有6个辈分。这样设计可以鼓励尽早合并叔父区块。

66.png

​叔父区块被包含到新区块后,新区块不会执行叔父区块中的交易而且不检查叔父区块的交易合法性,只会检查这是不是一个合法发布的区块是不是符合挖矿难度。只有分叉后的第一个区块可以获得被合并的奖励,不然分叉攻击会得到保底的奖励,也是鼓励分叉之后及时进行合并,不合并就白挖了。

注:最开始的时候发布一个区块是奖励5个出块奖励。以太坊中的小费是gas,汽油费

十八、ETC-挖矿算法

挖矿是保障区块链安全的重要保障,Block chain is secured by mining。bhg bounty程序漏洞赏金。 中本聪在BTC中提出过,one cpu,one vote。BTC之后出现的其他币种的设计理念是要实现ASIC resistance。memory hard mining puzzle 根据这个理念设计的货币有LiteCoin使用的是Scrypt这个哈希算法对内存的要求比较高。 冷启动问题,早期是不安全的。

​以太坊也是使用一种memory hard mining puzzle ,但是在设计上和莱特币有很大不同。以太坊使用两个数据集一大一小,分别是16M cache + 1G dataset,这两个数据集是定期增长的,因为计算机的内存容量也是定期增长的,DAG。轻节点保存16M的cache,只有全节点保存1G的dataset,这样做便于验证。

​小数据集的生成方式,首先从种子节点seed,通过一些计算算出数组的第一个元素,然后依次取哈希值,把数组填充伪随机数。在以太坊需要生成一个更大的数组即大数据集,在小的数组中通过计算取循环读取256个数(计算下一个数的位置),然后计算之后填充到大的数组里,求解的时候用的是大数组中的数,在大数组中读取128个伪随机数后(每次读出后旁边的数也要读出,然后循环64轮),最后算出一个哈希值,然后和挖矿难度的目标阈值比较一下,查看是否符合要求,不符合要求就要更换block header里的nonce。

67.png

伪代码:

68.png

69.png

70.png

71.png

72.png

73.png

​以太坊很早就计划从POW转向POS,即转向权益证明,按所占的权益投票来达成共识。以太坊采用了pre-mining预挖矿,pre-sale。

十九、ETC-难度调整

​以太坊每个区块都有可能调整挖矿难度,调整的方法比较复杂已经修改过很多的版本,以太坊的黄皮书和目前的代码也有一些出入。

01 - 区块难度

74.png

75.png

76.png

02 - 难度炸弹💣

77.png

78.png

03 - 发展阶段

79.png

04 - 代码实现

80.png

81.png

82.png

  • 可以形象的比喻为最难合法链。

二十、ETC-权益证明

Proof of stake

  • 矿工为什么要挖矿?

  • 为了取得出块奖励,为了取得收益。

  • 为什么要给矿工收益?

  • 为了让矿工积极参与区块链的维护。

  • 决定参与矿工参与挖矿要怎么做?

  • 需要投入一笔资金购入专业的挖矿设备,买矿机买GPU。

  • 挖矿的收益是什么决定的?

是由挖出的区块数量决定的,这又是由投入的资金所购入的装备的算力所决定的。

综上,可以看出挖矿的收益是靠拼钱决定的。

​权益证明的基本思想:virtual mining 虚拟挖矿,不再把钱投入到矿机的购买挖矿中而是投入到区块链的研发中,按照投资的比例分配收益。采用权益证明的货币,会先预留一部分货币,留给开发者,也会出售一些来获得开发虚拟货币的资金。将来按照权益证明的共识机制,按照持有货币的数量进行投票。

与工作量证明相比的优点是:省去了挖矿的过程,以此减少了对能源的消耗(电能),更加环保。采用工作量证明的机制,本身不是闭环的,因为挖矿的设备本身就是使用类似美元之类的货币购买的是外界获取到的,这样会带来非常大的风险如果有恶意机构聚集资金攻击还是可以,发动攻击的资源是可以从区块链的外部获得的;权益证明发动攻击的资源只能从内部获得,是一个闭环。

(早期权益证明遇到的问题:两边下注)

83.png

以太坊中准备采用的权益证明是:Casper the Friendly Finality Gadget(GFG)

在过渡阶段也是要和工作量证明结合使用,想要成为validator就要投入一定数量的币,作为保证金,保证金会会被系统锁定,validator的职责是推动系统达成共识,投票决定哪条是合法链,投票的权重取决于投入币的数量。混用阶段,每挖100个区块作为epoch,然后进行投票two-phase commit: ① prepare message准备信息;② commit message提交信息。每次投票都要获得2/3以上的投票才能获得通过。实际系统中不再区分两个区块,把100个区块减少到50个区块,每50个区块是一个epoch。前后都要有2/3的投票支持才算通过。验证者做的这个工作也可以获得奖励,如果投票者不作为,会扣掉一部分保证金,如果乱投票比如两边下注,会扣除全部的保证金,没收的币将被销毁。每个验证者会有一定时间的验证期之后会有一定时间的等待期,等待期可以接受其他节点的举报是否有违法行为。等待期过后验证者可以取回之前的保证金并获得相应的奖励。

权益证明不是很成熟,工作量证明比较成熟经过了时间的检验。

84.png

二十一、ETC-智能合约

智能合约是以太坊的精髓,也是以太坊和比特币的最大区别。

01 - 概述

​智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容。智能合约的账户保存了合约当前的运行状态:balance(当前账户余额)、nonce(交易次数)、code(合约代码)、storage(存储,数据结构是一颗MPT)。Solidity是智能合约最常用的语言,语法上与JavaScript很接近。

85.png

02 - 调用

​调用智能合约和转账是类似的,例如A发起交易转账给B,如果B是普通账户,那么这就是一个普通的转账交易,如果B是合约账户,则是对B这个合约的调用。具体调用的哪个函数是在数据域中说明的。

86.png

(1)直接调用

87.png

​以太坊中规定一个交易只有外部账户才能发起,合约账户不能主动发起一个交易。

(2)call()函数

88.png

(3)代理调用

89.png

  • fallback()函数

90.png

​转账交易可以是0,但是汽油费是要给的,要不然矿工不会把交易打包到区块链上。

03 - 创建

91.png

04 - 汽油费

92.png

​没有办法,是Halting Prcblem问题。办法就是把问题推给发起交易的账户。

​汽油费是对执行交易消耗资源的补偿,但是这种补偿只会给挖到矿的节点,其他人是没有补偿的。同时汽油费也是遏制发布交易的账户,防止无限制发布交易。汽油费是如何扣除的?全节点在本地维护三棵树,当全节点收到一个交易的时候,在状态数的账户余额上扣除汽油费即可,如果账户余额不够那么不会执行交易,因为执行合约是一次扣除最大的汽油费,当执行完毕有剩余的汽油费会在账户上加回。多个全节点都需要执行交易以保持状态的同步,扣除的汽油费只是在本地,最终是需要获得记账权的全节点同步全网的状态。即智能合约对数据的修改都是在本地进行的,只有获得记账权发布到区块链之后才会真正生效变为共识。

05 - 错误处理

​以太坊的交易具有原子性。如果汽油费不够,交易执行状态会回退,但是已经消耗的汽油费不退。

93.png

94.png

​补:call()函数的调用方式,不会全部回滚,直接调用的方式会回滚。

​BTC限制资源是限制打包的大小最大是1M是固定死的;以太坊中限制资源是汽油费有汽油费的上限,以太坊中汽油费是可以微调的1/1024。

​先执行智能合约的交易,才能进行挖矿。

​每个全节点还要独立的验证新发布区块的正确性,还得得执行一遍,即把区块的内容在本地执行一遍算出根哈希值,看是否和发布区块的哈希值相一致。没有挖到矿的节点必须验证新发布的区块,因为需要在本地执行之后更新维护在本地的三棵树,不然是没有办法下一步的挖矿的工作。矿池的做法可以是把三棵树给矿工,矿工不需要验证了。

06 - 收据

如何知道一个交易是否执行成功了?

95.png

  • 智能合约是否支持多线程?多核并行处理

​Solidity是不支持多线程的,多核状态下执行结果可能不确定。以太坊下智能合约的随机数是伪随机数不是真正的随机数

07 - 其他

96.png

97.png

98.png

​address是转入的地址。transfer会导致连锁回滚。send不会导致连锁性回滚。code本意是函数调用但是也可以用来转账,也不会引起连锁式回滚。

99.png

coder is law

irrevocable trust

发布智能合约一定要反复测试,确定无误。

100.png

101.png

  • NPC问题。

二十二、ETC-TheDAO

​DAO:Decentralized Autonomous Organization,是建立在代码之上的,组织的规章制度是写在代码里的,通过区块链的共识协议维护协议的正常执行。

​2016年出现了一个注重众筹投资的组织叫The DAO,众筹时把以太币发给智能合约换取代币,代币越多投票的比重越大决定投资哪个项目等,分配收益按照合约中的规定的章程决定。类似的DAC:Decentralized Autonomous Corporation,一般是出于盈利目的为了挣钱,DAO可以是出于非盈利目的。最终The DAO只存活了三个月,取回收益采用的方法是splitDAO(拆分DAO),这种方法不是单纯取回收益,而是一种建立子基金的方法child DAO。拆分子基金之后,会收回代币同时相应的以太币会打到子基金,如果这个基金里只有自己一个人,把钱投资给自己就取回了收益。拆分之前有7天的讨论期,拆分之后有28天的锁定期。

102.png

​黑客利用了重入攻击,转走了5000万美元的基金。社区介入,更新了软件,规定和TheDAO交易相关属于非法,软分叉。但是升级之后的软件有一个BUG,和汽油费相关,判断和thedao是否相关要不要收取汽油费(本来是合法的,判断之后成为了非法的),升级之后是不收取汽油费的,这样就有大量的攻击交易,矿工无法接受便纷纷回滚了软件升级,这样软件分叉就失败了。28天的剩余时间所剩不多,于是以太坊的团队进行了硬分叉,通过软件升级的方法,把TheDAO基金账户上的钱强行转到一个新的基金上,这个新的基金只有一个功能就是退钱,这次通过投票之后硬分叉成功了。之后不支持硬分叉的少部分,继续沿着旧链挖矿。这之后新链还是ETH旧的链改为了ETC(Ethereum Classic经典以太坊),之后两条链上增加了chain ID区分两条链防止重放攻击。

二十三、ETC-反思

  • 1、智能合约其实不智能,相当于代码合同。

  • 2、不可篡改性是一个双刃剑。

  • 3、Nothing is irrevocable。没有绝对的不可篡改性。

  • 4、Solidity语言有很多值得改进的地方。

  • 5、开源软件,真正研读源码的人,是否比不开源的安全等。

  • 6、去中心化的问题。What does decentralization mean?去中心化并不是全自动化,也不是说已经制定的规则不能修改。挖矿通票,得有广大矿工的支持。分叉是中心化的特征。

  • 7、去中心化 ≠ 分布式。一个去中心化的系统一定是分布式的,分布式的应用不一定是去中心化的。大多数的分布式系统是不同的计算机干不同的事情,机器越多速度越快。状态机的目的是为了容错,机器的数目越多越慢。智能合约是用来编写控制逻辑的,不是用来做大规模计算和大规模存储的。

二十四、ETC-美链

  • Beauty Chain 是一种代币,很多代币是做ICO的。

103.png

ICO / IPO (Initial Public \ Coin Offering)

以太坊平台的出现,为发行代币提供了平台。

104.png

先扣再增加。

105.png

106.png

计算时一定要注意溢出。

107.png

二十五、总结

区块链不是万能的,不能什么都推给区块链。

溯源过程是合理的可靠的,但是上链前的内容是没有保证的,区块链是没法检测上链前的真假的,即只是说区块链的内容是不可篡改的,本身的内容就是假的,这个是无法检测的。

中心化和去中心化不是泾渭分明的,在一个成功的商业案例里既可以有去中心化的成分,也可以有中心化的成分。BTC只是一种支付方式,不是说采用了BTC的商业模式也得是中心化的。

支付方式和法律监管并不是固定绑定的。已有的付款方式做的很好的地方,没有必要再引入新的加密货币进行竞争。加密货币应该用在已有的支付方式解决的不是很好的地方,跨境支付(现有的信息和支付渠道是分开的,即信息的交互是比较方便的,但是价值的交换是不方便的)。

一种支付或者货币的好坏要在当时具体的环境中做评价。

很多东西早期出现漏洞是正常的,不能因此而直接唾弃。软件将会改变世界。不能走向极端。