加密货币 / 区块链 · 2022年3月26日 0

区块链学习——以太坊基础知识

以太坊概述

BTC和ETH为最主要的两种加密货币,BTC称为区块链1.0,以太坊称为区块链2.0。

之前文章中提出了比特币设计中存在某些不足,以太坊便对其进行了改进。例如:出块时间、共识协议、mining puzzle(对内存要求高,反ASIC芯片使用)
未来,以太坊还将会用权益证明(POS,主要是基于权益,类似于股权)替代工作量证明(POW,主要是基于算力)
此外,以太坊增加了对智能合约(smart contract)的支持(很多山寨币都是基于智能合约来实现的)。
ETH的设计目的就是,通过技术手段来实现取代政府对于合约的职能。智能合约的好处是利用了区块链的无法篡改性,来确保所有人只能按照合约执行。

以太坊发展历史

1)边境(Frontier,2015年7月):以太坊网络第一次上线,开发者可以在上面挖以太币,并开始开发dApp和各种工具。核心功能:挖矿功能(一个区块奖励5个 eth)、上传和执行合约、一个中心化的保护措施(金丝雀合约)、虽然体验很差但是一定的可用性。
2)家园(Homestead,2016年3月):以太坊发布了第一个正式、稳定版本,对协议进行了优化,为之后的升级奠定了基础,并加快了交易速度。核心改进:取消金丝雀合约、引入 mist 钱包。在此版本后不久发生了 The Dao 事件,以太坊进行了硬分叉, 分为 ETH 和 ETC
3)大都会(Metropolis,2017年10月):这个阶段分两次上线,分别是拜占庭是拜占庭(Byzantium,2017年10月)和君士坦丁堡(Constantinople,2019年1月),让以太坊变得更轻量、更快速、更安全。
拜占庭(17年10月):第一次难度炸弹调整,同时出块奖励从5变为3。
君士坦丁堡(19年2月)第二次难度炸弹调整,出块奖励从3变为2。提供了智能合约之间的相互验证。
伊斯坦布尔(19年12月),提高了性能,降低了成本(交易数据成本从每字节68gas降低到16gas),之前每秒交易30笔,之后每秒3000笔
4)宁静(Serenity,时间待定):这个阶段将会为我们带来期待已久的PoS共识,使用Casper共识算法。
详细信息参考:https://zhuanlan.zhihu.com/p/109531201

账户

BTC使用的是基于交易的,Transaction-based ledger,想要只要余额需要根据UTXO模型一个个找。类似于只给你一个账本,想要知道还剩多少钱要自己汇总。
ETH账户是 account-based ledger,系统中要显式地记录每个账户中有多少个ether,类似于银行,银行记录交易,以及帮你计算你实时的余额。

  1. 优点:这种类型对于double spending attack(发出者不诚实spend again)具有天然的防御作用,花两次扣两次就可以。
  2. 弱点:replay attack:A->B(10ether)重放攻击(接收者不诚实 receive again)
    有2种账户类型:外部账户(可以理解为个人账户)、合约账户

状态树

账户系统

以太坊系统则采用了基于账户的模型,与现实中银行账户相似。系统中显示记录每个账户以太币的数量,转账是否合法只需要查看转账者账户中以太币是否足够即可,同时也不需要每次全部转账。同时,这也也天然地防范了双花攻击。

采用的数据结构-MPT

简单的Tire

特点:
1、trie中每个节点的分支数目取决于Key值中每个元素的取值范围(图例中最多26个英文字母分叉+一个结束标志位)。
2、trie查找效率取决于key的长度。实际应用中(以太坊地址长度为160byte)。
3、理论上哈希会出现碰撞,而trie上面不会发生碰撞。
4、给定输入,无论如何顺序插入,构造的trie都是一样的。
5、更新操作局部性较好 那么trie有缺点吗?
trie的存储浪费。很多节点只存储一个key,但其“儿子”只有一个,过于浪费。因此,为了解决这一问题,我们引入Patricia tree/trie

Patricia trie(Patricia tree)

Patricia trie就是进行了路径压缩的trie。如上图例子,进行路径压缩后如下图所示:

将所有账户组织为一个经过路径压缩和排序的Merkle Tree,其根哈希值存储于block header中。
根哈希值的用处:

  1. 防止篡改。

  2. 提供Merkle proof,可以证明账户余额,轻节点可以进行验证。

  3. 证明某个发生了交易的账户是否存在
    MPT(Modified Patricia tree)

    每次发布新区块,状态树中部分节点状态会改变。但改变并非在原地修改,而是新建一些分支,保留原本状态。如下图中,仅仅有新发生改变的节点才需要修改,其他未修改节点直接指向前一个区块中的对应节点。

    以太坊数据结构

  4. block header 中的数据结构

  5. 区块结构

    交易树和收据

    交易树和收据树只将当前区块中的交易组织起来,而状态树将所有账户的状态都包含进去,无论这些账户是否与当前区块中交易有关系。
    多个区块状态树共享节点,而交易树和收据树依照区块独立。
    交易树和收据树的用途:
    向轻节点提供Merkle Proof。
    更加复杂的查找操作(例如:查找过去十天的交易;过去十天的众筹事件等)
    Bloom filter可以判断有没有要的交易,然后再通过收据树来看交易细节,主要是为了提升下查找效率。
    以太坊的运行过程可以看作是一个交易驱动的状态机。transcation driven state machine

以太坊共识机制——Ghost协议

以太坊的出块时间15秒,区块链是10分钟,会造成一个问题,挖好的区块传到其他位置需要十几秒时间,造成临时分叉。临时分叉产生的单块被称为orphan block/stale block(孤儿块,陈旧的块)
一个问题是Mining centralization,当矿池和普通miner同时出块的时候,矿池会在拓扑中占据有利位置(比如部署多个接口,占据有利位置等),导致的问题是其他人不会跟随着普通miner挖出来的块之后挖,而是跟随着pool,使pool所在的链成为最长合法链,对于普通的miner是不利的,会出现恶性循环,越来越集中。
GHOST协议的核心思想:挖出块虽没有采纳但是会给予一些奖励。
以太坊将orphan block称为uncle block, uncle block获得7/8∗∗coinbase奖励的出块奖励,同时矿工将uncle block每包含进去一个叔区块会额外获得奖励1/32 ∗coinbase。一个区块最多可以包含两个uncle block
这样的设计有利于系统中出现分叉之后及时合并

改进之后的版本:

● 后面的区块也可以继续包含,而不再仅是unlce辈分的,可能是祖父,曾祖父等,但是也会进行限制,以太坊规定只能有6代unlce block可以被包含,在七代以内有共同的祖先才可以,隔代减少
● 对于M来说,无论包含哪个辈分的“叔父”,得到的出块奖励都是1/32出块奖励。
● 也就是说,叔父区块的定义是和当前区块在七代之内有共同祖先才可(合法的叔父只有6辈)。

ETH系统中规定,只认可A区块为叔父区块,给予其补偿,而其后的区块全部作废,这样就增加了分叉攻击的成本。
这样,就方便了全节点进行记录,此外,也从协议上鼓励一旦出现分叉马上进行合并。

以太坊中的奖励:

BTC:静态奖励(出块奖励)+动态奖励(交易费,占据比例很小)
ETH:静态奖励(出块奖励+包含叔父区块的奖励)+动态奖励(汽油费,占据比例很小,叔父区块没有)
BTC中为了人为制造稀缺性,比特币每隔一段时间出块奖励会降低,最终当出块奖励趋于0后会主要依赖于交易费运作。而以太坊中并没有人为规定每隔一段时间降低出块奖励。
加密货币的比喻:比特币:黄金(是为了存储),以太币:石油(是为了支持智能合约的运行,区别是石油用了就没了,但是以太币只是账户之间的转移)

叔父区块和同辈的主链上区块有可能包含有冲突的交易。而且也提到叔父区块是没有动态奖励的。因此,一个节点在收到一个叔父区块的时候,只检查区块合法性而不检查其中交易的合法性。


挖矿算法

Block chain is secured by mining.
比特币的挖矿主要依赖ASIC芯片,跟最早的“one CPU One Vote”有很大差距,因此,以太坊期望设计一个对ASIC芯片不友好的系统。

以太坊的挖矿算法

使用两个数据集,小的是一个16M的cache,大的数据集是一个1GB的dataset,叫做DAG
1G的dataset是由16M的cache生成的,就是为了便于验证,轻节点只要保存16M的cache,只有需要挖矿的矿工才需要保存这1G的大数据集。
小的数据集的生成方式是:从一个种子节点经过一些运算生成第一个元素,然后依次取哈希,第一个元素取哈希得到第二个元素,第二个元素取哈希得到第三个元素,把数组从前往后进行填充伪随机数就得到一个cache。
大的数组里面的第一个元素的生成顺序:
在cache里面随机选取一个A,之后进行运算得到B的位置,如此运行256次最后得到一个哈希值存在第一个位置。
求解puzzle的时候使用的是大数据集里面的数,不使用cache,按照伪随机的顺序,从大的数据集中读取128个数,一开始根据block header和nonce算出一个初始的哈希,根据这个哈希映射到大数据集中的某个位置,将它读取出来,对他进行运算,算出下一个值的位置,特殊之处在于,每次读取的时候,除了计算出这个位置的元素之外,把相邻的元素也要计算出来,相当于每次读取两个相邻的元素。64次循环,每次读两个元素,一共128个元素。最后算出一个hash值,与挖矿难度的目标阈值比较一下,是不是符合难度要求,如果不是的话,把Block header里面的nonce替换一下。

权益证明(POS: Proof of State)

权益证明:按照所占权益投票进行共识达成,类似于股份制有限共识按照股份多少投票,权益证明不需要挖矿。
在设计之初,以太坊开发者就设想要从POW转向POS,并为了防止有矿工不愿意转埋下了一颗“难度炸弹”。如果按照原本思想,通过不断改进挖矿算法来达成ASIC Resistance,无疑是比较难的。而这里通过不停宣传要转向POS来不断吓阻矿工,使得矿工不敢擅自转入ASIC挖矿,从而实现了ASIC Resistance。(因为ASIC芯片研发周期很长,成本很高,如果以太坊转入权益证明,这些投入的研发费用将全部白费)
预挖矿(Pre-Mining)
以太坊中采用的预挖矿的机制。这里“预挖矿”并不挖矿,而是在开发以太坊时,给开发者预留了一部分货币。以太坊的早期开发者,目前就很有钱了。
和Pre-Mining对应,还有Pre-Sale,Pre-Sale指的是将预留的货币出售掉用于后续开发,类似于拉风投或众筹。目前,各类加密货币很多,存在一部分货币就在采用Pre-Sale来获取资金,如果此时买入,后续如果该货币取得成功,同样可以获得很大收益,但真正成功的货币只占少数,这就是其风险性。

以太坊统计数据





难度调整

比特币难度调整是每隔2016个区块调整难度,从而达到维持出块时间10min的目标。


难度炸弹

为什么要设置难度炸弹?
根据以上以太坊难度调整算法可以看到,该算法可以很好地动态调整挖矿难度,从而保障系统整体出块时间维持在15s左右。但之前在挖矿算法的文章中有介绍到,以太坊在设计之初就计划要逐步从POW(工作量证明)转向POS(权益证明),而权益证明不需要挖矿。
从旁观者角度来看,挖矿消耗了大量电力、资金等,如果转入放弃挖矿,必然是一件好事。但从矿工的角度,花费了很大精力投入成本购买设备,突然被告知“不挖矿了”,这必然是一件很难接受的事情。而以太坊本身为一个分布式系统,其转入POS必须经过系统中大多数矿工认可才行,如果届时矿工联合起来转入POS,那么这一设计初衷就成了一江流水。
因此,以太坊在设计之初便添加了难度炸弹,迫使矿工转入POS。那么 如何促使矿工自愿升级软件,而非坚持POS呢?

难度炸弹调整

在实际应用中,权益证明的方式仍然并不成熟,目前以太坊共识机制仍然是POW,依然需要矿工参与挖矿维护以太坊系统的稳定。也就是说,转入POS的时间节点被一再推迟,虽然挖矿变得越来越难,系统出块时间开始逐渐变长,但矿工仍然需要继续挖矿。



权益证明

POW机制能耗状况


矿工挖矿是为了取得出块奖励,获取收益。而系统给予出块奖励的目的是激励矿工参与区块链系统维护,进行记账,而挖矿本质上是看矿工投入资金来决定的(投入资金买设备->设备决定算力->算力比例决定收益)。
那么,为什么不直接拼“钱”呢?现状是用钱购买矿机维护系统稳定,为什么不大家都将钱投入到系统开发和维护中,而根据投入钱的多少来进行收益分配呢?这就是权益证明的基本思想。
权益证明
采用权益证明的货币,会先预留一些货币给开发者,而开发者也会出售一些货币换取开发所需要的资金,在系统进入稳定状态后,每个人都安装持有货币的数量进行投票。 优点:
1、省去了挖矿的过程,也避免了因此产生的能耗和对环境影响,减少了温室气体的排放。
2、维护区块链安全的资源形成闭环,而POW中维护其安全的资源需要通过现实中流通的货币购买矿机等设备进去区块链的,这也就导致只要有人想要攻击,只需要外部聚集足够资金就可以攻击成功(小型币种很容易被攻击,也就是在摇篮里就扼杀掉)。可见,POS机制可以有效防御这种情况。
攻击者需要先买足够多的币才能发动攻击,而买多的币会导致币价上涨,会加大攻击者的难度。
以太坊拟采用的权益证明
以太坊中,准备采用的权益证明协议为Casper the Friendly Finality Gadget(FFG),该协议在过渡阶段是要和POW结合使用的。
在比特币系统中,我们有提到为了防范分叉攻击,一个交易在其获得6次确认(其后跟着6个区块)后认为该区块安全。但实际上,这种安全只是概率意义上的安全,仍然可能会被拥有强大算力的用户在其前面发动分叉攻击进行回滚。
Casper协议引入一个概念:Validator(验证者),一个用户想要成为Validator,需要上交一笔“保证金”,这笔保证金会被系统锁定。Validator的职责是推动系统达成共识,投票决定哪一条链成为最长合法链,投票权重取决于保证金数目。
实际中,采用两次投票的方式:预投票和Commit 投票,规定每次投票结果都要获得2/3以上的验证者同意。在实际中,针对其进行了一些修改,两次投票在实际中只需要一次即可。
验证者
● 认真工作可以获得奖励
● 如果拖延工作,可能被扣除一部分保证金,
● 如果乱作为,乱投票,两边下注,可能被扣除所有的保证金.没收的保证金被销毁掉,
● 验证者存在“任期”,在任期结束后,进入“等待期”,在此期间等待其他节点检举揭发是否存在不良行为,若通过等待期,则可以取回保证金并获得一定投票奖励。
通过验证者达成的finality有没有可能被推翻?
● 1/3及以上的验证者进行两边下注
为什么不从一开始就是用权益证明?主要是因为不成熟,POW 经过了十几年,是比较成熟的。但是 POS 还没有经过时间的检验。
EOS加密货币,即“柚子”,2018年上线,就是采用权益证明的共识机制,其采用的是DPOS:Delegated Proof of Stake。该协议核心思想是通过投票选21个超级节点,再由超级节点产生区块。但目前,权益证明仍然处于探索阶段。

智能合约

智能合约是一种计算机程序或事务协议,其目的是自动执行,控制或文档根据的条款在法律上相关的事件和行为的合同或协议。自动售货机被认为是与智能合约实施等价的最古老的技术
智能合约是以太坊的精髓所在,也是其与比特币系统最大区别之处。
智能合约:运行在区块链系统上的一段代码,代码逻辑定义了合约内容。智能合约的账户保存了合约当前的运行状态:
● balance:当前余额
● nonce:交易次数
● code:合约代码
● storage:存储,数据结构为一棵MPT

以太坊中规定,如果一个函数可以接收外部转账,则必须标记为payable。该例中背景为拍卖,bid()为出价,因此需要payable进行标记,相当于竞拍的时候需要把钱转给合约账户中进行锁定;withdraw()为其他未拍卖到的人将锁定在智能合约中的钱取出的函数,其不涉及转账,因此不需要payable进行标记。
外部账户调用合约账户

转账金额和汽油费是不同的。汽油费是为了让矿工打包该交易,而转账金额是单纯为了转账,其可以为0,但汽油费必须给。
合约账户调用合约账户
但是智能合约中只有外部账户才可以主动发起,合约账户只能被动相应
汽油费 以太坊中功能很充足,提供图灵完备的平台(图灵完备,简单解释,就是能够执行所有可计算的问题),从而使得以太坊相对于比特币可以实现很多功能,但这也导致一些问题,例如当一个全节点收到一个对智能合约调用怎么知晓其是否会导致死循环。 事实上,无法预知其是否会导致死循环,实际上,该问题是一个停机问题,而停机问题不可解。因此,以太坊引入汽油费机制将该问题扔给了发起交易的账户。 以太坊规定,执行合约中指令需要收取汽油费,并且由发起交易的人进行支付。

在比特币系统中,交易是比较简单的,仅仅是转账操作,也就是说可以通过交易的字节数衡量出交易所需要消耗的资源多少。但以太坊中引入了智能合约,而智能合约逻辑很复杂,其字节数与消耗资源数并无关联。存在某些交易,从字节数来看很小,但其实际消耗资源很大(例如调用其他合约等),因此要根据交易的具体操作收费,所有引入了汽油费这一概念。 在block header中包含了gaslimit,其并非将所有交易的消耗汽油费相加,而是该区块中所有交易能够消耗的资源的上限。
挖矿与智能合约执行
先Mining还是先执行智能合约?
● 三棵树都是全节点在本地维护的数据结构
● 执行智能合约是改变自己本地的状态,只有达成了共识,发布到区块上,当与发布区块的状态不一致时,Miner会丢弃自己的状态转而更新本地三棵树,进行同步。都是需要重新执行一遍
● 所以先执行,后挖矿。
● 得先更新Blockheader里面的Root,TxHash,ReceiptHash。确定了Block Header,然后才可以进行Minging
会不会因为没有奖励,有的Miner就不去验证区块的正确性?
● 可能会存在,但是如果不验证的话,那么其Block header就得不到更新,本地的状态不对,以后就无法Mining,发布的区块得不到别人的验证
发布到区块链上的交易是不是都是成功执行的?:不一定
● 如果智能合约出现了错误要不要也发布到区块链上去?
● 要,否则Gas费用扣不掉,要达成共识,这样Miner才能收钱
汽油费是怎么扣除的? 首先,之前在以太坊数据结构中介绍了以太坊中“三棵树”——状态树、交易树、收据树。这三棵树都位于全节点中,是全节点在本地维护的数据结构,记录了每个账户的状态等数据,所以该节点收到调用时,是在本地对该账户的余额减掉即可。所以多个全节点每人扣一次,仅仅是每个全节点各自在本地扣一次。 也就是说,智能合约在执行过程中,修改的都是本地的数据结构,只有在该智能合约被发布到区块链上,所有节点才需要同步状态,各自在本地执行该智能合约。
以太坊地址类型
address.balance指的是address这个账户的余额 address.transfer(12345),并非address向外转账12345Wei,因为这样没有收款人的address。所以,该函数指的是当前合约向address地址中转入了12345Wei。后面的函数都是该语义,这里是需要注意的,因为其与我们认知存在差异。

三种转账方法
transfer在转账失败后会导致连锁性回滚,抛出异常;而send转账失败会返回false,不会导致连锁性回滚。call的方式本意是用于发动函数调用,但是也可以进行转账。 前两者在调用时,只发生2300wei的汽油费,这点汽油费很少,只能写一个log,而call的方式则是将自己还剩下的所有汽油费全部发送过去(合约调用合约时常用call,没用完的汽油费会退回)。例如A合约调用B合约,而A不知道B要调用哪些合约,为了防止汽油费不足导致交易失败,A将自己所有汽油费发给B来减少失败可能性

一个拍卖的例子

SHIB 的智能合约

限定了它的名字、总供给等条件,以及可以进行哪些写操作。

The Dao

比特币实现了去中心化的货币;以太坊实现了去中心化的合约。
DAO:去中心化自治组织 DAC:去中心化自治公司
黑客利用代码的一个逻辑,转走了1.5亿美金
The Dao占了以太坊10%以上的份额,too big to fail
当时分成2派:
1、code is law,遵守“不可篡改”的规定,错了就是错了。
2、采取补救措施,挽回损失
硬分叉方案
1、通过软件升级的方法,将The DAO账户上所有的资金转到另一个智能合约,该合约之后只有退款功能,为什么是硬分叉? 2、到192W个区块时自动升级,直接转到另一个合约,没有所有者的签名,所以旧的矿工是不会认可的,硬分叉。 3、旧链ETC: Ethereum Classic,新链还叫做ETH 4、ETC和ETH并存有很多问题,导致重放攻击。所以最后加入了ChainID
核心原因:智能合约一旦发布就不能修改。

反思

1、智能合约不是智能,只能算自动合约。
2、不可篡改性是一把双刃剑,好处是可以保证安全,弊端是出现问题时修复很困难,出现问题也没办法改。
3、没有什么是绝对改不了的,不要迷信区块链的不可篡改性,代码是死的,人是活的
4、Is solidity the right programming language? 未来常用的智能合约会出现模板,在其上改进,类似律师事务所
5、开源软件不一定是安全的,虽然开源,但是并不一定就有人去检查
6、去中心化的含义?
● 以太坊硬分叉是矿工投票产生的结果;其他人可以选择其他分叉
● 去中心化不是说已经指定的规则就不能修改,而是对规则的修改要用去中心化的思想来完成
● 分叉恰恰是去中心化思想的体现
● 存在分叉的选项也恰恰是民主的一种体现
● V神创建以太坊的原因
○ V神喜欢玩魔兽,暴雪公司将他最喜欢的一个英雄技能去掉了,用户不能决定
○ 要去中心化,用户不满意就可以选择分叉
7、去中心化不是分布式,智能合约是编写控制逻辑的,只有那些在互不信任的实体之间建立共识的操作才需要写在智能合约里

美链


ICO:initial coin offering
ERC 20 : Ethereum Request for Comments 20

总结

目前区块链的概念被滥用了。
比如保险理赔,保险理赔最复杂的是人工审核,而不是支付。
用区块链做防伪溯源,其实意义也不大,区块链虽然有不可篡改性,但是如果本身是假的,再不可篡改也没意义。
区块链是去中心化的,但并不一定与之相关的应用也需要去中心化,比如特斯拉支持 doge 币。
监管不一定是坏事,有些监管提升了效率。
比特币的支付不一定要跟现在的支付渠道做竞争,应该用到已有的支付渠道做的不好的领域。
● Information can flow freely on the Internet, but payment cannot
● 未来的发展趋势是,支付渠道和信息传播渠道将会逐渐融合,使得价值交换也和信息传播一样的方便
智能合约出现过漏洞是很正常的事情,毕竟只是早期的一个产品。
去中心化和中心化各有利弊,一定要具体分析
if the business model is bad ,it's still bad on the Internet。