欢迎光临散文网 会员登陆 & 注册

肖臻区块链b站网课笔记——11-18

2022-09-26 22:54 作者:苦茶今天断更了吗  | 我要投稿

视频链接:【北京大学肖臻老师《区块链技术与应用》公开课】 https://www.bilibili.com/video/BV1Vt411X7JF?p=6&;;;share_source=copy_web&vd_source=33abd457d9415a4317112e8206e5360e

【笔记的内容也结合了评论区里其他同学的笔记】 



11-BTC-问答

1.转账交易如果接收者不在线,怎么办?

  转账交易只不过需要在区块链上记录一下,把A账户上的比特币转到B的账户上,与接收者是否连在比特币网络中无关。

 

2.假设某个全节点收到了转账交易,有没有可能转账交易中接收者的收款地址是这个全节点以前从未听说过的?

  有可能的。比特币系统中,账户创建的时候是不需要通知其他人的,只需要在本地产生一个公私钥对就可以了。只有在以后,该账户产生的收款地址收到钱的时候,其他节点才会知道该账户的存在。

 

3.如果账户的私钥丢失了,该怎么办?

  没有办法,账户上的钱就变成了死钱,是没有办法取出来的。比特币系统是去中心化的系统,是没有人可以帮你重置密码的。

 

  有些加密货币是有交易所的,交易所是一个中心化的机构,一般来说,在交易所注册账户时,需要提供身份证。这种情况下,将比特币保存在交易所里,私钥实际上是由交易所保管的。登录交易所跟登录银行账户的操作类似,一般需要用户名、口令和二次验证消息(如Google身份验证器生成的一次性密码),在这种情况下,如果登录口令丢失,可以联系交易所,通过身份验证后重置密码。

 

  上述这种丢失口令的情况跟比特币系统中丢失私钥的情况是很不一样的。比特币系统中虽然也存在一些能够帮忙保管私钥的应用,如比特币钱包等。但是,并不能说明这些应用保管私钥会比私人保存更安全。相比之下,有些冷钱包或者说硬件钱包是比较安全的。

  私钥丢失之后,那么这些比特币将会永远花不出去,但矿工并不知道这个账户的私钥已经丢失了,这些比特币是取不出来的,所以他需要永远把交易的输出保存在UTXO中,这个操作对全节点是不友好的。

 

4.如果私钥泄露了,怎么办?

  尽快把这个账户上的钱转到其他安全账户上。账户创建的时候会在本地创建一对公私钥对,私钥就是这个时候产生的,公私钥对一旦生成无法修改。可以生成新账户,但是原账户的私钥无法修改,账户的持有者也没办法阻止他人发布从该账户转账的交易,任何有私钥的人都可以发布转账交易,把账户里的比特币转走。

 

问:用户持有者如何知道自己的私钥泄露了,是否看见从该账户上转出的非本人发起的交易才能知道?

 

5.如果转账时写错了地址,该怎么办?

  在比特币系统中没有提供一些能取消已经发布交易的机制。如果转账转到错误的地址,若知道地址归属于某账户(如B)的话,联系对方看是否愿意把比特币还给你,没有办法强迫。

  地址一般是该账户公钥取哈希值得到的,但是有些地址其实并不是取公钥的哈希得到的,如Digital Commitment。如果想要把某项内容发布在区块上,证明在某个时间知道某个事情,这里有一种比较经典的方法就是Proof of Burn,就是将需要发布的内容的哈希值存放在OP_RETURN后面。但是有的人不这么做,他用哈希值生成一个像是比特币地址的东西,来代替比特币的转账交易接收方的地址的内容。就比如说正常实现转账交易A→B,这里B表示账户公钥取哈希值得到的地址,但是如果用其他哈希值来代替接收方的地址的内容,比特币系统并不知道这个地址是真的还是假的,这样转账的比特币就成了死钱,是取不出来的。这种虽然也达到了牺牲一点比特币,往比特币中写入一点东西的效果,类似于Proof of Burn,但是这种做法是很不提倡的,因为这样的交易的输出将会永远被写在UTXO集合中,全节点收到这样的转账交易,并不能判断这个交易的地址是否为真,不知道这个转账交易是花不出去的,这个操作对全节点是不友好的。

  在Proof of Burn的情况下,OP_RETURN后的结果是无条件返回错误,不满足合法区块才会被写入区块中的条件,那么为什么还会用这种方式来向区块链中写入内容呢?验证的时候是将这个交易的输入脚本与前一个交易的输出脚本拼在一起运行,顺利执行就是合法交易。而在Proof of Burn的情况下OP_RETURN是写在输出脚本中的,所以验证这个交易合法性的时候并不会执行到OP_RETURN,也就不会返回错误。如果后面再有一笔交易想要花这笔交易里的钱的时候,才需要验证这个交易的输出脚本。所以判断交易是否合法,能否写入区块的时候,并不会执行到OP_RETURN部分。

 

6.比特币挖矿的实质是在找合适的Nonce。会不会有矿工“偷答案”,如何辨别是哪个矿工最前找到的这个Nonce?

  发布的区块里面有个CoinBase Transaction,里面有个收款人地址,是挖到矿的矿工的地址。如果要“偷答案”,需要将收款人的地址改为自己的地址,那么这个CoinBase Transaction的内容将会发生改变,这样会导致Merkel Tree的根哈希值会发生变化。Nonce在块头中,根哈希值也在块头中,Block Header的值发生变化之后,原来找到的Nonce就作废了。

问:如果要是挖到矿的矿工与偷答案的矿工同属于一个矿场呢?

 

7.交易费可以看作是发布一个交易的时候给矿工的一点小费,那么如何知道这个交易费给哪个矿工?

  交易费的计算是total inputs - total outputs,即总输入与总输出的差值,哪个矿工先挖到矿了不需要事先知道,挖到矿的矿工可以将区块中所包含交易发输入与输出的差额收集起来,作为他自己的交易费。

 

12-BTC-匿名信

一、 比特币的匿名性

1.什么是比特币系统的匿名性

     比特币系统中不要求用真实姓名,可以使用公钥产生的地址。一个用户可以产生任意多的地址,然后用不同的地址做不同的事情。但是比特币系统也并不是说完全没有名字,它用的是化名,所以有人认为,比特币系统中的匿名性叫做Pseudonymity(假名字)。

 

2.比特币系统的匿名性可以提供哪些隐私保护

    比特币系统的匿名性没有现金好,现金是完全匿名的,其缺点是不方便保管和运输。比特币系统的匿名性显然比银行存款要好,因为现在的银行账户是实名制的。如果银行用化名的话(存钱提供化名即可,取钱的时候拿着存折取钱),其匿名性会优于比特币,因为比特币账本是公开的,所有人都可以查到,而银行的账本是受控制的,一般只有银行工作人员和一些司法机关可以查到银行的账本。

(1)一个人可能生成很多个地址账户,但是这些地址账户是有可能被关联起来的。

    假设存在如图,该交易存在两个输入和两个输出,那么addr1和addr2很可能是同一个人所持有的账户,此人同时拥有这两个私钥的地址,这种情况可能是此人持有的一个账户中的比特币可能不够支付这次交易而导致的。而在输出中,很有可能有一个地址是属于找零钱的地址,即花掉之后剩余的钱。在某些情况下,也是可以分析出来的。

     

        从理论上讨论,如果想要加强隐私保护,可以人为产生很多没必要的输出,迷惑敌人。但是这些交易都是用钱包软件生成的,常用的比特币钱包就那么几种,所以如果将比特币钱包生成交易的原理,那么区块链上很大一部分转账交易都可以分析出来,常用钱包目前为止不会生成没必要的输出地址。

 

(2)比特币系统中的地址账户与账户持有者在现实社会中的真实身份也可能产生关联。

        任何让虚拟货币跟实体世界发生联系的操作,都可能跟真实身份产生关联。

       在很多国家,都有防洗钱法。如何防范不法分子采用比特币进行洗钱呢?其实很简单,只需要盯住资金转入转出链即可。对于大额资金转入比特币或将大量比特币转为现实货币,很难逃避司法金融机构的监管。这也是比特币匿名性被破坏的很重要的例子。

 

(3)在实体世界中,用比特币做支付的时候。

        国外有的商家接收比特币支付,如咖啡厅、餐厅等。但是这可能不是一个good idea,因为用比特币交易延迟高,交易费贵。在这种情况下,也是可能对比特币的匿名性造成破坏的。因为这就相当于一个账户会参与很多交易,比较容易把这些交易信息关联起来,从而破坏匿名性。其实不光接受支付的商家会知道,其他人也会知道。

       

4.实际当中比特币的匿名性

        比特币系统的匿名性是相对的。在实际中,也有很多人保持有较好的匿名性。保持最好的当属其开发者中本聪,其参与比特币时间最长,但是全世界都不知道他是谁。但实际上,中本聪的比特币并非有花出去,这也使得我们难以发现他具体是谁。

        曾经美国有一个skil road网站,被称为eBay for illegal drugs,主要用于匿名支付售卖违禁品,为了逃离网络监管,其支付手段就是比特币,底层的网络层是洋葱路由TOR。但运行没有几年就被查封,其老板当时赚取了十几万比特币,从纸面上看,已经非常有钱了。但由于其担心身份暴露,这些钱一个都不敢花,在美国仍然过的是非常简朴的生活。最终据说由于疏忽,在同一电脑上登录现实社会账户和非法网站上账户,从而被抓(具体原因未公开)。

       

5.比特币匿名性有多好?

        匿名的本质是不想要暴露身份,但是它区别于你是想对谁隐瞒身份。而对于普通人来说,比特币的现有机制已经足够保持个人隐私了。但如果涉及违法,行政机关想要获得真实身份,其实很容易。

 

6.如何提高匿名性?

        比特币协议实际上是运行在应用层的,其底层实际上是P2P Overlay Network。提高匿名性就要从这两个层面来提高。如果不保证网络层的匿名性,其他结点发现这个交易都是单一路径(同一个IP地址)发布,其他结点很可能通过这一路径推测其在物理世界中的真实身份。

        网络层的匿名性学术界已经有了很好的解决方法:采用多路径转发的方法,数据不直接发送出去,而是经过很多跳(中间结点只知道它的上一层结点是谁,并不知道最开始发送消息的人是谁)这也是洋葱路由的基本思想。

        应用层的匿名性,可以将各个不同用户的比特币混合在一起,使追查变得混乱,这种方法就是Coin Mixing。

        实际上,暴露用户隐私正是由于区块链的公开性和不可篡改性。实际上,不可篡改性对于隐私保护,是灾难性的,因为一旦某一个交易不小心把身份暴露出去了,这个交易永久的写在区块链里,想抹掉都不能,所以说账户之间的关联性是需要小心的。

 

二、零知识证明

1.什么是零知识证明

        零知识证明是指一方(证明者)向另一方(验证者)证明某一个陈述是正确的,而不需要透露除该陈述是正确的之外的任何信息。

 

2.同态隐藏

        同态隐藏是零知识证明的数学基础,其三个性质如下:

(1)如果x,y不同,那么它们的加密函数值 E(x) 和 E(y) 也不相同。(说明这个加密函数值E不会发生碰撞,与哈希函数不同。若 x ≠ y,那么E(x) ≠ E(y)。如果E(x) = E(y),则x = y。)

(2)给定 E(x) 的值,很难反推出x的值。(说明加密函数是不可逆的)

(3)给定 E(x) 和 E(y) 的值,我们可以很容易计算出某些关于x,y的加密函数值。(同态运算,说明对加密后的函数值进行某些代数运算,等价于对输入直接进行代数运算再加密。)

        ①同态加法:通过 E(x) 和 E(y) 计算出 E(x+y)  的值。

        ②同态乘法:通过 E(x) 和 E(y) 计算出 E(xy) 的值。

        ③扩展到多项式。

例:Alice想要向Bob证明她知道一组数x 和 y 使得x + y = 7,同时不让Bob知道x 和 y 的具体数值。

①Alice把 E(x) 和 E(y) 的数值发给Bob

②Bob通过收到的 E(x) 和 E(y) ,计算出 E(x+y)  的值

③Bob同时计算 E(7) 的值,如果 E(x+y) = E(7),说明x+y = 7,那么验证通过,否则验证失败。

 

3.盲签方法

(1)用户A提供SerialNum(货币编号),银行在不知道SerialNum的情况下返回签名Token(银行签名的时候看不见序号的内容),减少A的存款;

(2)用户A把SerialNum和Token交给B完成交易;

(3)用户B拿SerialNum(明文)和Token给银行验证,银行验证通过,增加B的存款;(银行要记录该序号是否存在Double Spending)

        这样做的好处是银行无法把A和B联系起来;而且实现了中心化。

 

4.零币和零钞——专门为匿名性设计的加密货币

(1)零币和零钞在协议层就融合了匿名化处理,其匿名属性来自密码学保证。

(2)零币(zerocoin)系统中存在基础币(如比特币)和零币,通过基础币和零币的来回转换,消除就地址和新地址的关联性,其原理类似于混币服务。

(3)零钞(zerocash)系统使用zk-SNARKs协议,不依赖一种基础币,区块链中只记录交易的存在性和矿工用来验证系统正常运行所需要关键属性的证明。区块链上既不显示交易地址也不显示交易金额,所有交易通过零知识验证的方式进行

     零币和零钞在花费的时候,只需要用零知识证明来证明所花掉的币是系统中存在的某一个合法的币,但不用透露具体花掉的是系统中哪一个币。这样就破坏了关联性。但这类货币并非主流加密货币,原因如下:

①其为了设计匿名性,付出了一定代价;

②在数学原理上对初始化有比较严格的要求(即初始时候用的随机元要能销毁掉,如果不能销毁则会出现安全漏洞);

③需要强匿名性的用户并不多;

④虽然从数学上看,零币和零钞是安全的,但其并不是百分之百的匿名,并未解决与系统外部实体发生交互时对匿名性的破坏。

 

13-思考

1.比特币在设计的过程中很多地方用到了哈希指针,如块头就包含指向前一个区块的哈希指针,指针保存的是本地内存的地址,只在这台计算机上才有意义,发送到其他计算机上就没有意义了,那么在发布区块的时候哈希指针是如何通过网络传输的呢

  实际上,在比特币系统中,所谓哈希指针只是一种形象的说法,实际在用的时候,其实只有哈希,没有指针。回顾之前学习过的Block Header的数据结构,如下所示,我们可以得知, uint256 hashPrevBlock;这里表示的就是前一个区块的哈希,实际上是没有指针的。

class CBlockHeader

{

public:

//header

int32_t nVersion;//当前使用的比特币协议的版本号,没法修改(4字节)

    uint256 hashPrevBlock;//前一个区块块头哈希值(32字节),不能修改

    uint256 hashMerkleRoot;//Merkle Tree的根哈希值(32字节);

  //通过修改Merkle Tree中铸币交易的CoinBase域当作ExtraNonce来调整其根哈希值

    uint32_t nTime;//区块产生时间,有一定调整余地(4字节);

                //比特币系统并不要求非常精确的时间,这个时间可以在一定范围内调整

    uint32_t nBits;//挖矿后的目标阈值编码后的版本(4字节);

                    //只能按照协议中的要求定期进行调整,不能随便改

    uint32_t nNonce;//(4字节)单纯靠调整nonce的值很大概率找不到符合难度要求的

}

 

   那么,如何找到前一个区块的内容呢? 全结点一般是将这些区块存储在一个 (Key,Value) 数据库中,Key表示哈希值,Value表示区块的内容,有一个比较常用的 (Key,Value) 数据库——LevelDB。所谓的区块链是一个链表结构,实际上是在 LevelDB 里面,用哈希值串起来的。只要掌握最后一个区块的哈希值,用 LevelDB 查找 (Key,Value) ,就可以通过哈希值Key得到Value,就可以把最后一个区块的内容取出来。然后这个区块的Block Header里面又有指向前一个区块的哈希值,然后再去用 LevelDB 查找 (Key,Value) ,就可以找到前一个区块的内容,以此类推,就可以把整条区块链都找出来。

  所以,在实际系统之中,所谓的哈希指针是只有哈希没有指针的,或者也可以认为哈希值本身就是指针。有些结点没有保存区块链整条链上的全部信息,只保存了最近的几千个区块的信息,如果需要用到前面区块的信息,可以问其他全结点要,哈希指针的性质保证整个区块链是不可篡改的。

 

2.区块恋可能造成的问题

  情侣两个人合在一起买比特币,然后将私钥从中间截断,分成两部分,每人保存其中的一段,如果两个人分手了,当初买的比特币就被永久地所在区块链上,谁也取不出来。

 

可能造成的问题:

(1)如果有一个人把私钥丢失(或遗忘),都会导致比特币无法取出。

(2)降低账户的安全性。

  比特币系统中账户的安全性跟用户所用的私钥的长度是相关的,用256位的私钥就是因为这个长度的私钥用暴力破解的方式是不可行的,但是如果从中截断,就会大大降低其安全性。

  假设其中一个人想要把比特币取出来,那么只需要破解另外一半就可以,破解长度为256的私钥需要尝试的可能性为2256,而破解128位的私钥需要尝试的可能性为2128,是指数级的减小。

 所以说对于多个人共同持有的账户,不能用私钥截断的方式,而应该使用多重签名的方式来保障安全性。 在多重签名(MULITISIG)中,每个人用到的私钥都是独立产生的,而且多重签名还具有很多灵活性,如N个人中只给出M个人的签名就可以验证通过。

 

(3)取不出来的钱将会永久被存在UTXO集合中,对矿工是不友好的。

  假设“区块恋”的例子中的两个情侣分手,不存在其中有人有使用暴力手段破解私钥的情况,那么这些比特币将会永远花不出去,矿工并不知道这对情侣已经分手了,这些比特币是取不出来的,所以他需要永远把钱保存在UTXO中,这个操作对全结点是不友好的。

 

3.分布式系统比较著名的不可能结论,从理论上证明,分布式系统中取得共识是不可能的,那么既然理论上已经证明了是不可能的,实际上为什么又变得可能了呢?就是说比特币系统为什么能取得共识,为什么它能绕过分布式系统理论上证明的那些不可能结论?

  严格意义上说,比特币系统并没有真正意义上的共识,因为取得的共识随时都有可能被推翻,如出现分叉攻击(本来你以为已经取得某项共识,分叉攻击之后,系统会回滚到前一个状态,从理论上说甚至有可能一直回滚到创世纪块),按照分布式系统理论上的要求,共识一旦达成就不应该再修改。从这个意义上说,比特币系统并没有绕过分布式系统那些不可能的结论,因为它并没有达到真正意义上的共识。理论和实际往往是有距离的,理论上的不可能只是在某种特定的模型下是不可能的,实际上把模型稍微改一改,这个不可能结论就不成立了。

  如何判断远程数据中心的一台服务器是不是已经死机了。专家的看法是:分布式系统的理论已经证明了,在异步环境中,不可能区分某个远程服务器到底是死机还是运行缓慢。(所谓的异步环境是指通讯传播的延迟是没有上限的)但是实际上,我们可以给远程服务器的工作人员打个电话,让他们看看这个服务器是不是死机了,如果死机帮忙重启一下,这样下来,这个理论上不可行的案例,实际上就变成可行的了。或者给服务器加一根电话线,进行拨号上网,如果发现Internet执行缓慢可以试一下电话线,两根线一般不会出现同时拥堵的情况,这样就可以确认远程服务器是否死机。

 

4.比特币的稀缺性

  为了获得收益,挖矿的收益大于挖矿的开销,才是有利可图的。所以,想要吸引到更多人来挖矿,要么增加挖矿的预期收益,要么降低挖矿的开销。

  比特币的设计是非常巧妙的,我们之前计算过,每过大约四年时间,出块奖励会减半一次,也就是说比特币的总数是恒定的。有些人说这种总量恒定的东西是不适合作为货币的,以太坊就没有出块奖励定期减半的做法,有些加密货币甚至每过一段时间会自行通胀一次,因为稀缺的东西是不适合做货币的。

  

5.量子计算

  最近几年量子计算发展很快,有人产生这样一种担心:比特币这种加密货币是建立在密码学的基础上的,将来量子计算技术发展起来以后,这些加密货币会不会变得不安全?

  传说中的量子计算机是非常强大的,可以破解现存的各种加密算法,但是这个担心是不必要的。首先,量子计算机距离使用还有很长一段时间,在比特币的有生之年不一定能产生实质性的威胁。而且,如果将来有一天量子计算真正强大到可以破坏现有的加密体系的话,首先受到冲击的是传统金融业,像网银、网上支付等等都会变得不安全。所以,与其担心量子计算对比特币的冲击还不如担心量子计算对传统金融业的冲击,因为大多数的钱都是存放在传统金融体系中的,加密货币的总市值现代金融体系的很少一部分,而且将来还会有量子加密算法。

  第二,比特币系统中并没有把账户的公钥直接暴露出来,而是用公钥取哈希之后得到一个地址。比特币中用的是非对称加密体系,从私钥可以推导出公钥,所以只要将私钥保管好,公钥即使丢了也没有关系,公钥显然不能推出私钥。假设以后,量子技术发达了,可以通过公钥推到得到私钥,那么在比特币系统中,还需要突破另一层保护机制,就是需要能够从公钥的哈希推算出公钥,而这一点即使使用量子计算机也是无法完成的。加密跟取哈希是两种不同性质的操作,加密的目的是保证信息的安全性,以后还要解密,所以加密需要保证信息的完整性,加密过程不能丢失信息。而取哈希不一样,取哈希一般情况下会造成信息的损失,哈希函数一般都是不可逆的,从哈希值是无法得到原来的输入的。

  比特币系统中哈希函数用的是SHA-256,即无论输入有多大,输出的都是256位的,这种情况如果可逆就会变成一个超级无敌的压缩算法。所以,如果仅用来收钱的情况下,不建议把公钥暴露在比特币系统上,收钱的时候只需要提供公钥的哈希提供的地址就可以,取钱的时候才需要提供公钥,取钱的交易中需要公钥和由私钥产生的签名。如果一个人想要偷A账户上的钱,他需要在A发布交易时实时破解从A的公钥推导出A的私钥,再实时产生一个跟A的交易竞争的交易。即使这个人具有量子计算技术也很难在几分钟之内就将私钥破解,而且他发布的交易还需要抢在A发布交易的前面,因为如果在A发布交易之后,就会产生Double Spending。所以从比特币安全的角度来看,比特币系统中每个账户只取一次钱,花不完的钱转给自己的其他账户,这样做既提升了安全性,也提高了隐私保护的程度。



14-ETH-以太坊概述

1.以太坊相较比特币做出的改进

  比特币称为区块链1.0,以太坊称为区块链2.0。

(1)出块时间:

比特币的出块时间是十分钟,以太坊的出块时间是十几秒,而且为了适应新的出块时间,以太坊还设计了一套基于GHOST协议的共识机制

(2)Mining Puzzle:

比特币的Mining Puzzle是计算密集型,比拼计算哈希值的算力,这样造成的结果是挖矿设备的专业化,现在大家用的是ASIC芯片,很多人认为这与区块链去中心化的理念相悖,

以太坊设计的Mining Puzzle对内存要求高,在一定程度上限ASIC芯片(ASIC Resistance)的使用;

(3)用权益证明来替代工作量证明:

以太坊中改成了权益证明(Proof of Stake),不挖矿了,改成了类似股份投票的方法,决定下一个区块怎么产生。

 

2.以太坊增加的新功能

  智能合约(Smart Contract)。以太坊的一个特性就是增加了对去中心化的合约的支持。比特币(BTC)最小计量单位是Satoshi(聪),以太坊(ETH)中的货币称为以太(Ether),最小计量单位是Wei。

 

3.去中心化的合约

  现实社会中合约的有效性也是通过政府采取司法手段来维护的,使用技术手段把这些司法手段取代,就是智能合约的目的,如果合约中的内容是可以通过代码实现的,就可以将这样的代码放在区块链上,通过合约的不可篡改性保证代码正常运行。

并非所有合同都能通过代码实现的,也不是所有合同条款都可以量化的,但是有些逻辑比较清晰的合同是可以写成智能合约的形式的。

 

4.去中心化的合约有什么好处?

  去中心化的货币有什么好处?比如跨国转账,传统的方式交易费非常昂贵而且转账时间非常长,用加密货币(如BTC)则方便很多。

  那么,智能合约也有类似的应用场景,若合同签署方并非一个国家,来自世界各个国家,没有统一的司法部门,若此时想要利用司法手段来维护合同的有效性会比较麻烦。用技术手段编写无法修改的合约,所有人只能按照相关参与方执行,无法违约,这是最好的。

 

15-ETH-帐户

1.比特币的账户模式

  比特币系统是基于交易的账本(Transaction Based Ledger),系统中并未显示记录每个账户上有多少钱,只能通过UTXO进行推算(即在UTXO中查找该账户公钥有多少输入即可)。

  假设A转给B钱的时候,需要说明币的来源。比特币账户中,在前面一笔交易中收到的比特币,在花的时候必须一次性全部花出去,不能只花一部分。

 

假设B收到A的5个比特币,他只给C转账2个比特币,若按上图方式,其余3个比特币会以交易费(Transaction Fee)的形式给挖出区块的矿工。

采用下图的方式,将3个BTC转给C,将剩余7个BTC转到B的另一账户D上面。很多比特币钱包就采用这种方式,每次转账就生成一个自己的新的地址,有利于隐私保护,但是仍然与日常生活有所不同。这是因为比特币系统中没有显示的基于账户的交易的概念,在比特币系统中,每个交易是单独进行处理的


2.以太坊的账户模式

  以太坊系统则采用了基于账户的模型系统中显示记录每个账户中以太币的数量,转账是否合法只需要查看转账者账户中以太币是否足够即可,不用确切指出转出的钱属于哪一部分,同时也不需要每次全部转账。同时,也天然地防范了双花攻击。若出现Double Spending,无需说明币的来源,只需要扣两次钱就好了。

      但这种模式存在重放攻击(Reply Attack)的缺陷。A向B转账10个ETH,过一段时间,B将A的交易重新发布,从而导致A账户被扣钱两次。

在比特币中会有重放攻击吗?不会,因为收到过的交易信息再广播一次是很显然的Double Spending。

  解决重放攻击的方法:在每笔交易中添加一个Nonce计数器,记录该账户有史以来一共发布多少交易,转账时,Nonce作为交易的一部分,同时受到签名的保护,从而防止本地篡改余额或进行重放攻击。


3.以太坊的账户类型

①外部账户:外部账户中有账户余额Balance和计数器Nonce(≠挖矿调整的Nonce)。

②合约账户:并非通过公私钥对控制。合约账户不能主动发起交易,若外部账户发起交易调动了一个合约账户,该合约账户可以发起一个Message调用另外一个合约,但是不能自己主动发起交易。合约账户除了Balance和Nonce之外还有代码(Code)、相关状态-存储(Storage),包括每个变量的取值

  创建合约时候会返回一个地址,知道这个地址就可以调用这个合约。调用过程中,代码不变但状态会发生改变,存储也会发生变化

 

4.为什么创建以太坊,更换为基于账户的模型而不是沿袭比特币系统?

  比特币基于交易的模型隐私保护比较好,每次交易支持更换账户。

以太坊是为了支持智能合约,对于合约来说,要求参与方的身份较为稳定。如果地址变了,那投入到原来合约的钱也就找不见了。

 

16-ETH-状态树

一、什么是以太坊中的状态树

        以太坊中采用的是一种基于账户的模式,想要实现这种模式需要完成从账户地址(Address)到账户状态(State)的映射以太坊中的账户地址是160位的,也就是20字节,一般将其表示为40个十六进制的数。状态是指外部账户和合约账户的状态,包括余额,交易次数Nonce,对于合约账户还包括代码和存储。

 

二、实现从账户地址到账户状态的映射

方案一、哈希表+Merkle tree

用哈希表实现,系统中的全节点维护一个哈希表,每次有一个新的账户,插入到哈希表里面,查询账户的余额,就直接在哈希表中查询,如果不考虑哈希碰撞的话,基本上查询的效率是在常数时间内完成的,更新也是很容易在哈希表中更新的。

 

问题:

1. 如果用这个哈希表要提供merkle proof怎么提供?比如说你要跟一个人签合同,希望他能证明一下他有多少钱,怎么提供证明呢?

类似比特币系统中的做法,把哈希表中的元素组织成一个Merkle Tree,然后算出一个根哈希值,这个根哈希值存在Block Header里,只要根哈希值是正确的,就能保证底下的树不会被篡改。


2. 比特币系统中也是每出现一个区块都要重新构造一个Merkle tree,这为什么没有问题?

比特币系统中的Merkle tree是把区块里包含的交易组织成一个Merkle tree,那区块中的交易每次发布一个新的区块又有一系列新的交易,比特币中的Merkle tree是不变(immutable)的。每次发布一个新的区块对应一个Merkle tree,然后这棵Merkle tree构建完之后是不会再改的,下次再发布一个新的区块再构建一个新的Merkle tree


那区块里有多少个交易呢?最多差不多4000个(按照1M字节,每个交易大概是250M字节左右),其实是一个上限。所以每次发布一个区块,比特币里要把这几百个到几千个交易构成一个Merkle tree。

 

若以太坊中想要采取类似方法,需要把所有的以太坊账户一起构成一个Merkle tree,量要高出好几个数量级,相当于每次发布一个区块要把所有的账户遍历一遍构建出一个Merkle tree。

除了提供Merkle proof证明账户有多少钱之外,这个Merkle tree还有另外一个很重要的作用,就是维护各个全节点之间状态的一致性,如果没有根哈希值发布出来,每个节点就是在本地维护一个数据结构,那怎么知道你的数据结构的状态跟别人的数据结构的状态是不是一致呢,要各个全节点保持状态的一致才行,这也是为什么比特币中把根哈希值写在块头里的原因,就是对于当前区块中包含哪些交易,所有的全节点要有一个共识。

        综上所述,哈希表本身的效率是挺好的,插入、更改效率都很好。但实际操作中,账户状态发生变化的只是一小部分,大多数是不变的,所以每次都重新构造一次Merkle tree的代价太大了。


方案二、不排序的Merkle tree

1. 直接用一个Merkle tree把所有的账户都放进去,要修改账户状态的时候直接在Merkle tree里改?

问题①:Merkle tree没有提供一个高效的查找、更新的方法。

问题②:直接把账户放到Merkle tree里,如果不排序,查找速度会慢,比特币中如果证明一个交易在这个区块中是不需要排序的,如果证明一个交易不在这个区块中,是需要排序的,否则证明的代价就非常大了。

如果不排序还有一个问题③:叶节点是这些账户的信息,如果不规定这些账户在叶节点出现的顺序,那么这样构建出来的Merkle tree不是唯一的。

 

2. 比特币中的节点也是不排序的,那为什么比特币就没有问题呢?

比特币中的每个全节点收到的交易的顺序也是不一样的,理论上说构建的Merkle tree的根哈希值也是不一样的。

但比特币中,每个节点在本地组装一个候选区块,这个节点自己决定哪些交易、以什么顺序打包进这个区块里,然后通过挖矿去竞争记账权。只有他有记账权,且发布区块后最终成为被大家接受的区块,这个顺序是唯一的,是发布这个区块的节点确定的

 

3. 为什么以太坊不能这样做?

因为如果也要这么做的话,需要把所有账户的状态发布到区块里,不是交易,个数差了很多个数量级。

账户状态可以维护在本地,而且大部分账户状态是不变的,一个区块里的交易只能改很少的账户,且重复发布,每隔十几秒发布一个新的区块,把所有状态都打包发布一遍,这个是不可行,刚才说明了不排序的Merkle tree是不行的

 

方案三、Sorted Merkle tree

也有问题。如新增一个账户时,产生一个账户的地址是随机的,他的叶节点的位置很可能是插在中间的,那后面这些树的结构都得变,插入,删除代价都很大,每次更新都需要新产生一遍Merkle tree。

区块链是不可篡改的,是说添东西容易,删东西难,其实以太坊中没有显式地删除账户的操作,有的账户上就一点钱,就一两个Wei,也不能把他删掉。       

 

上面的方案都不行。那么以太坊中采用的方法是用一个叫MPT的结构,在此之前先学习一个简单的数据结构——trie。

 

 

三、MPT结构

1.Trie:字典树前缀树

也是一种(key,value)的树,一般来说key用字符串用的比较多,如将一些单词排成一个trie的数据结构。比如将general,genesis,god,go,good排列成trie的数据结构如下图。


2.Trie结构的特点

每个节点的分支数目取决于key值里每个元素的取值范围

在以太坊中,地址是表示成40个十六进制的数,所以分叉数目(有时也叫做Branching Factor)是17,因为是十六进制的0~f,再加上结束标志位,所以是17。

 

trie的查找速率取决于key的长度,键值越长,查找需要访问的次数就越多

以太坊中,所有键值都是40,因为地址都是40位十六进制的数。

比特币和以太坊的地址是不通用的,长度不同(比特币中的地址是用公钥取哈希得到的256位的哈希值),以太坊中的地址是公钥取哈希,只要后面这部分,就得到一个160bit的地址。

 

trie是不会出现碰撞的只要两个地址不一样,最后肯定映射到树中的不同分支。

trie构造的树不受输入排序影响

Merkle tree,如果不排序的话,一账户插入到Merkle tree 的顺序不一样,得到的树的结构也不一样。

而trie,只要给定的输入不变,无论输入怎么打乱重排,得到的树是一样的。不同的节点,不论你怎么按照顺序去插入这些账户,最后构造出来的树是一样的。

 

更新操作的局部性很好每次发布一个区块,系统中绝大多数账户的状态是不变的,只有个别受到影响的账户才会变。

 

缺点:存储浪费

比如在上图中,左边分支都只有一个子节点,如果能把节点进行合并,可减小存储的开销,同时提高查找的效率,不用一个个往下找。由此引入了Patricia tree。

 

3.Patricia treePatricia trie,经过路径压缩的前缀树,即压缩前缀树

将上图的trie进行路径压缩,结果如下图。

压缩后,缩短了树的高度,访问内存的次数则会大大减少,效率会明显提高。

对于Patricia tree来说,新插入一个单词,原来压缩的路径可能需要扩展开。

 

路径压缩在什么情况下效果比较好?

如英文单词,每个单词很长,但是一共没有几个单词。misunderstanding,decentralization(去中心化),disintermediation(非中间化)。用Patricia tree的话,参考下图

 

这样的结构效率是比较低的,用Patricia tree的结果如下图,这个树的高度明显改善。键值分布比较稀疏的时候,路径压缩效果比较好。如果应用在以太坊中,键值则为地址,地址是160位的,所以地址空间有,这是一个非常非常大的数,如果设计一个计算机程序的算法,需要进行运算的次数是2^160,那这个在我们的有生之年都不可能算出来,全世界的以太坊的账户数目加在一起也远远没有这么大,跟这个数比,是微乎其微的,所以以太坊的账户是非常非常稀疏的。

为什么设计地这么稀疏,不把地址长度缩短一点,这样访问效率也快,也没必要那么稀疏了?  以太坊中普通账户的创建方法跟比特币账户的创建方法是一样的,没有中央的节点,每个用户独立创建账户,在本地产生一个公私钥对,就是一个账户。为了防止两个人的账户碰撞(即产生的账户一样),特将地址设计得足够长,分布足够稀疏。这个可能看上去有点浪费,但是这是去中心化的系统防止账户冲突的唯一办法,所以在数据结构中,要用Patricia tree。

 

4.MPT(Merkle Patricia tree)

(1)什么是Merkle Patricia tree

区块链与普通链表的区别:把普通指针换成了哈希指针。

Merkel tree和Binary tree的区别:把普通指针换成了哈希指针。

在以太坊系统中,将所有账户组织成一个Patricia tree(用路径压缩提高效率),然后把普通指针换成哈希指针,计算出根哈希值,写在Block Header里。

比特币的Block Header里只有一个根哈希值,就是区块里包含的交易组成的Merkle tree组成的根哈希值;以太坊中有三个,有一个交易组成的交易树、用户状态组成状态树、和收据树,状态树由账户状态组成,他的根哈希值也是写在Block Header里。

 

(2)根哈希值的作用

防止篡改。根哈希值不发生变化,整个树的任何部分都没有办法被篡改。

②Merkle Proof:证明账户的余额是多少。该账户所在的分支自己向上作Merkle Proof发给轻节点,轻节点可以验证该账户的余额。

验证一个交易是不存在的。如果存在的话,把这个分支作为Merkle Proof发过去。

 

(3)以太坊中的MPT——Modified MPT

        以太坊中用到的不是原生的MPT,是Modified MPT,这里对MPT做了一些修改,这些修改并非本质的修改,如图,树中的根节点Root取哈希后得到的根哈希值会被写在块头里,如图左上角所示。另,图中各个节点原本存放地址的位置在这里存放的都是哈希值,具体方式参考BTC-思考。

 

        每次发布一个新的区块的时候,这个状态树中,有一些节点的值会发生变化,这些改变不是在原地修改,而是新建一个分支,所以说原来的状态实际上是保留下来的,如下图所示,以太坊中其实是一个大的MPT里面包含很多小的MPT,每个账户都有一个小的MPT。

 


为什么要保留历史状态,不能在原地直接修改状态树?

以太坊将出块时间降低到十几秒,导致临时性分叉成为常态(因为区块在网上传播时间可能也需要十几秒)。假设有个分叉,这两个节点同时获得记账权,上面的分叉胜出,成为最长合法连,下面这个分叉的节点就要回滚(roll back)。也就是说这个节点当前的状态(接受了下面这个节点的状态)要取消,退回到之前的状态,然后沿着上面那条合法链往下推进。为了实现回滚,就要维护这些历史纪录

比特币系统中,交易类型较简单,有时可通过反向操作推算出前一个状态。

以太坊中为什么不能直接回滚?因为以太坊中有智能合约,是图灵完备的,编程功能是很强的,从理论上说,可以实现很复杂的功能,跟比特币简单的脚本不太一样,所以以太坊中如果不保存前面的状态,智能合约执行完之后,想在推算出前面是什么状态,这是不可能的,所以想支持回滚,必须保存历史状态。

 

 

 四、以太坊中的数据结构

1.块头Block Header的定义

Bloom

布隆过滤器,提供一种高效的查询符合某种条件的交易的执行结果(跟收据树是相关的)

GasLimit

单个区块允许的最多Gas总量(智能合约要消耗汽油费,类似于比特币中的交易费)

GasUsed

该交易消耗的总Gas数量

 

 

 2.区块Block的定义


3.External block

        一个区块真正在网上发布的时候就是发布这些信息。

 

状态树中保存的是(key,value),key就是地址,前面主要讲的是键值,这个地址的管理方式。value,即账户的状态,是如何存储在状态树当中的?这需要经过一个序列化(RLPRecursive Length Prefix)的过程,然后再存储。

RLP是一种序列化方法,其特点是极简主义,越简单越好。

Protocal buffer:简称Protobuf,是个很有名的做序列化的库。

跟这些库相比,RLP的理念就是越简单越好,只支持一种类型,nested array bytes(字节数组),即一个一个字节组成的数组(可以嵌套)。以太坊里的所有的其他类型,如整数和哈希表等,最后都要变成nested array bytes。所以,实现RLP要比实现Protocal buffer简单很多,因为难的东西都不做,都交给应用层做。

 

 

 

 

17-ETH-交易树和收据树

一、以太坊中,三种基于树的数据结构——状态树、交易树和收据树。

所有的交易会组成一棵Merkle tree,叫交易树,类似于比特币系统中的Merkle tree。此外,以太坊中还增加了收据树每个交易执行完之后会形成一个记录这个其相关信息的收据,交易树和收据树上面的节点是一一对应的。增加这个收据树的目的是便于快速查询执行的结果(主要因为以太坊的智能合约执行过程比较复杂)。

 

从数据结构上来看,交易树和收据树都是MPT(Merkle Patricia tree,BTC中是MT(Merkle tree)。以太坊中的三棵树都用同样的数据结构,这样代码比较统一,便于管理,用MPT的一个好处是支持查找操作,可以通过键值从顶向下沿着这颗树查找。在状态树中,查找的键值就是这个账户的地址,对于交易树和收据树来说,查找的键值就是这个交易在发布的区块里的序号,这个交易的排列顺序是由发布区块的那个节点决定的。

 

二、状态树、交易树和收据树的区别

(1)交易树和收据树都是只将当前发布的区块里的交易组织起来,状态树需要把系统中所有账户的状态都要包含进去。

 

(2)从数据结构上来说,多个区块的状态树是共享节点的(新发布一个区块的时候,只有该区块中改变了状态的节点需要新建一个分支,其他节点都是沿用原来状态树上的节点),相比之下,每个区块的交易树和收据树都是独立的,是不会共享节点的(一个区块和另一个区块发布的交易本身也认为是独立的)。

 

三、交易树和收据树的用途

1.交易树和收据树的用途

①向轻节点提供Merkle Proof。

②支持一些更加复杂的查询操作。

比如,查询过去十天当中,所有与某个智能合约有关的交易(一种方法是把过去十天产生的所有区块都扫描一遍,缺点:①复杂度较高;②存储要大,保存整个集合的元素;③轻节点没有交易列表,只有一个块头的信息,无法通过扫描所有交易列表来查询)。

 

2.如何实现复杂的查询操作

以太坊中引入了Bloom Filter布隆过滤器),这种数据结构可以支持比较高效的查找某个元素是不是在一个比较大的集合里。Bloom Filter给这个包含很多元素的集合计算出一个很紧凑的摘要(如一个128位的向量)。

例:如图,给定一个数据集,含元素a、b、c,通过一个哈希函数H()对其进行计算,将其映射到一个其初始全为0的128位的向量的某个位置,将该位置置为1。将所有元素处理完,就可以得到一个向量,则称该向量为原集合的“摘要”。该“摘要”比原集合是要小很多。

假定想要查询一个元素d是否在集合中,H(d)映射到向量中的位置处为0,不在;H(d)映射到向量中的位置处为1,有可能d在,有可能因哈希碰撞产生误报。

所以使用Bloom Filter要注意,可能出现误报false positive,不会出现漏报false negative。

 

Bloom Filter有各种各样的变种,为解决这样的哈希碰撞,有时候会用一组哈希函数,将某个待证明元素分别通过每个哈希函数映射到向量中的一个位置。一般来说,不会所有的哈希函数都出现哈希碰撞。Bloom Filter的局限性是不支持删除操作。比如把a删掉了,对应的向量1要不要改。若要支持删除操作,则需要将向量中的值改成一个计数器,记录该位置有多少元素映射过来,而且还需要考虑到计数器会不会溢出。

 

3.以太坊中Bloom Filter的用途

每个交易执行完之后会形成一个包含Bloom Filter的收据,Bloom Filter用于记录交易的类型、地址等信息。发布的区块的块头里也有一个总的Bloom Filter,是这个区块里所有交易的一个Bloom Filter的并集。

比如说要查找过去十天发生的跟智能合约相关的交易,可以找一些有哪些区块的块头的bloom filter有要的交易类型,如果有,再去查找区块里面包含的交易所对应的收据树里面的那些Bloom Filter(就每个收据的bloom filter)看看哪个有,也可能都没有,可能是false positive。如果是有的话,再找到相对应的交易直接进行一下确认,好处是通过Bloom Filter的结构能够快速过滤掉大量无关的区块

 

四、以太坊的运行过程

这三棵树的根哈希值都包括在块头里面,以太坊的运行过程可以看作一个交易驱动的状态机(Transaction-driven State Machine),这个状态机的状态是所有账户的状态,即状态树中包含的那些内容,交易是指每次发布区块里包含的交易,通过执行这些交易会驱动系统从当前状态转移到下一个状态。

比特币系统也可以认为是一个交易驱动的状态机,比特币中的状态是UTXO(没有被花掉的那些输出),每次新发布一个区块,会从UTXO里用掉一些输出,又会增加一些新的输出,发布的区块会驱动系统从当前状态转移到下一个状态。而且这两个状态机有一个共同的特点,就是状态转移都得是确定的,对一个给定的当前状态,一组给定的区块中包含的交易,能确定性地转移到下一个状态。因为所有的全节点,所有的矿工,都要执行同样的状态转移,所以状态转移必须是确定性的。

 

问题:

1、A转账到B,有没有可能收款账户不包含在状态树中?

可能。因为以太坊中账户可以节点自己产生,只有在产生交易时才会被系统知道。

 

2、可否将每个区块中状态树更改为只包含和区块中交易相关的账户状态?

不能。①查找账户状态很不方便;②因为需要知道收款账户的状态,才能给其添加金额,要向一个新创建账户转账,所有需要一直找到创世纪块才能知道该账户为新建账户,系统中并未存储,而区块链是不断延长的。

 

交易树和收据树的创建过程——代码中的具体体现

链接:https://blog.csdn.net/YSL_Lsy_/article/details/126436571?spm=1001.2014.3001.5502

 

18-ETH-GHOST

一、以太坊的出块时间及可能带来的问题

1.以太坊的出块时间

以太坊将出块时间降到了十几秒,提高了系统的吞吐量(Throughput)、降低了反应时间。比特币和以太坊都是运行在应用层的共识协议,底层是一个P2P的Overlay Network,Overlay Network本身的传输时间比较长(其拓扑协议做flooding的时候没有考虑实际的拓扑结构)。

问题:发布区块时,该区块在网络上传到其他节点可能需要十几秒,那么就有较大可能会有两个节点(甚至多个),同时获得记账权,从而造成临时性分叉

 

2.以太坊与比特币系统的平均出块时间对比

对于比特币系统来说,平均出块时间是600秒,足够让新发布的区块传播到网上的其他节点,但挖矿是个概率的过程,仍有两个矿工同时获得记账权、同时发布区块的可能,会带来临时性的分叉。

在以太坊中,这种临时性的分叉会变成常态,而且分叉的数目也会变得更多,这对于共识协议来说,是一个挑战。

 

 

3.带来的问题

 

假定中间区块胜出,则上下两个区块叫做Orphan Block或Stale Block,挖到这类区块的矿工在里面有一个铸币交易,得到的出块奖励最后等于作废。对于比特币来说,这种临时性的分叉不是很多,所以这么规定可以接受。

对于以太坊来说,如果也将分叉区块的出块奖励作废的话,则意味着这个矿工挖到的区块有很大概率是白挖,对于个体矿工特别明显。按照常理,矿工的收益应该与算力成正比,矿池的收益也应当与矿池的总算力成正比。但大型矿池会出现Mining Centralization(挖矿集中化),即大型矿池所在的分叉更有可能成为最长合法链,这促使别的矿工沿着最长合法链继续挖。这样会使大型矿池出现恶性循环,越是大型矿池得到的收益越大,Mining Centralization更严重,有时候叫Centralization Bias,即中心化带来的不成比例的优势。如果以太坊按照比特币的共识机制就会有一定的问题。

 

二、GHOST协议

为解决以太坊如果按照比特币的共识机制产生的问题,采用一个基于GHOST协议的共识机制,这个协议并非以太坊发明的,以太坊只是对该协议做了一些修改。

 

1.GHOST协议的核心思想

挖到矿的矿工发布一个区块,即便这个区块最后作废了,也能得到一些出块奖励,将作废的区块(Orphan Block或Stale Block)称为Uncle Block。相对于最长合法链的当前区块来说,是他的叔父区块,最长合法链的下一个区块在发布的时候可以把叔父区块包含进来,如下图。


该协议的核心思想是:给予挖到矿但是没有成为最长合法链的那些矿工一种安慰。这样有利于鼓励系统中出现分叉后及时合并,相当于最长合法链上面的区块将另外两个分叉链给招安过来,这是GHOST协议最初的版本。

 

2.GHOST协议的缺陷

(1)Uncle Block的个数不能超过两个

设计GHOST的目的是给Uncle Block一点好处,把它们合并过来,但是只能招安两个。叔父区块得到八分之七的出块奖励是很高的,要是不限制的话,那么以太币就太不值钱了。

 

(2)区块传播存在延迟

区块D把区块A作为叔父区块的前提是:在挖这个区块D的时候已经知道区块A这个叔父区块的存在。

 

(3)受矿工主观影响

如果这个矿工比较自私的话,有可能故意不包含叔父区块。对叔父区块来说,7/8的出块奖励是得不到的,对于他自己来说,1/32的出块奖励是得不到了,好像是损人不利己,但要从商业竞争的角度讲,这么做对这个矿工的损失是比较小的,对挖出叔父区块的矿工的损失是比较大的。

 

3.改进后的GHOST协议

决了矿池出于竞争关系故意不把某个叔父区块包含进去的问题。比如区块D故意不包含区块A,但是区块E仍然可以包含区块A甚至有可能出现一个情况:挖到区块A的矿工发现自己不在最长合法链上,就沿着区块D挖出了区块E,然后就可以把自己的区块A包含进去。


 

也解决了出现第三个叔父区块的问题把叔父的定义扩展了,可能是隔着几代的叔父。以太坊规定,叔父区块可以得到7/8的出块奖励。如果往前推一代,叔父区块得到6/8的出块奖励。合法的叔父只有6个辈分。


为什么设定合法的叔父必须在当前区块在七代以内且有共同的祖先?

(1)如果不限制,全节点需要维护非常多的状态(可能要记着隔着100代以前有哪些叔父区块),新发布的区块包含的叔父区块,其他节点同样也需要验证;

 

(2)设计最多隔着7代,且出块奖励是逐渐递减的,有利于鼓励出现分叉之后,尽早合并,一出现分叉就马上合并的时候能得到的出块奖励是最多的

 

叔父区块的奖励叫做Uncle Reward,当前区块包含一个叔父区块,就会得到1/32的出块奖励,不论包含的是哪一个辈分的叔父。

 

4.改进后的GHOST协议无法解决的问题

主要是为了解决系统中出现的临时性分叉(State Fork),规定最长合法链的原则的目的是防止篡改,也是为了解决临时性分叉。

如果这个分叉是别的原因造成的,比如由于对运行的区块链协议有不同的意见,那么这种方法是解决不了的,也就是说,改进后的GHOST协议仍然无法解决硬分叉

 

例如,比特币系统跟中心化的系统不一样(中心化的系统发布一个新版本很容易),去中心化系统如果修改的话,会出现硬分叉。下图的那两条链如果不是因为对当前状态有意见分歧,而是互相认为对方是非法的,那么用这种方法是合并不了的。如果有矿工将这样的区块包含进来,其他矿工会认为这条链是非法的,还是不会沿着这条链继续挖,因为:即使主链最长,但是包含非法交易。


三、以太坊中的奖励

区块链和以太坊发布一个区块能得到的奖励如下图,叔父区块得到八分之七的奖励只限于Block Reward,即7/8×3ETH。叔父区块是得不到汽油费的,但汽油费所占的比例是非常小的,大部分是出块奖励,跟比特币的情况是类似的。


以太坊中没有规定定期要把出块奖励减半,比特币那么规定是为了人为制造稀缺性,以太坊中五个以太币降为三个以太币,不是为了认为制造稀缺性,实际上跟挖矿难度调整有关,2017年,挖矿难度炸弹被回调了300万个区块,导致挖矿难度大幅度下降,为了维护公平性,也是为了使以太币的供给量不要出现剧烈变化,所以降到了三个以太币,这是一次性的,并没有说以后会不断地下调。

 

比特币一般当作数字黄金,是用来储值的;以太币被比喻成石油,它是用来花的,用来消耗,然后可以执行智能合约的。这个比喻不是完全的恰当,因为石油花完之后就没了,而以太坊中执行智能合约要消耗的gas,只是从一个账户转移到另外一个账户,发布智能合约的时候,要付出gas费,执行这个智能合约的矿工可以得到这个gas费,所以这个比喻也不完全恰当。

 

四、思考

1.把叔父区块包含进来的时候,叔父区块的交易要不要执行?

不应该执行,最长合法链上的父区块和他的叔父区块包含的交易可能是冲突的,如果它们包含不同的交易,不同交易有可能不能都执行。在以太坊中,双花攻击花两次减两次,但是有可能一个交易花了之后,另一个交易就没法花了。叔父区块本身不一定是非法的,但执行完父区块的交易,再去执行叔父区块的交易可能就变成非法的。

以太坊中只执行在最长合法链上的交易。而且根本就不检查叔父区块交易的合法性,只检查叔父区块是不是一个合法发布的区块,即这个区块是不是符合挖矿难度,也就是有没有获得记账权。

 

2.叔父区块能不能广义化?

叔父区块都是分叉之后第一个区块。假定,将后面一连串的区块认为是叔父区块,会造成一个后果:分叉攻击的代价过低。正常意义上的分叉攻击需要使分叉链长度大于原来最长合法链长度才算成功,否则这些用来分叉攻击的区块会作废,原本的出块奖励也没有了。如果将分叉链上的区块认为是叔父区块的话,分叉攻击不成还能作为叔父区块获得一些奖励。所以以太坊中规定,只有分叉后的第一个区块可以得到Uncle Reward,后面的都不行。


五、以太坊中的真实情况

Etherscan.io可以实时查看以太坊的当前状态,右边这个曲线显示的是过去两周的交易历史,下面还包含最新挖出的区块和最新的交易。


下图所示为叔父区块的几种情况,这里的每一行对应一个叔父区块,第一列的Block Height就是区块的序号,也就是Block Number,与表中不同辈分的叔父得到的Uncle Reward的数目相对应。


下图是两个区块的具体例子,左边这个区块包含了一个叔父区块,倒数第二行uncle reward是2.25,应该是距离为2的叔父。这个区块得到的奖励,在倒数第三行,有三个部分组成,即3ETH出块奖励、汽油费和包含叔父区块得到的三十二分之一的出块奖励。

 


 


肖臻区块链b站网课笔记——11-18的评论 (共 条)

分享到微博请遵守国家法律