以太坊相关知识学习
以太坊的发展阶段
- Frontier(前沿):这个阶段的版本是以太坊的基础,此时的以太坊具备了挖矿、交易以及智能合约功能模块。但是没有供普通用户使用的图形化界面,仅适合于开发者使用。所使用的共识算法是“PoW”。
- Homestead(家园):这个阶段的以太坊网络变得更加稳定,且具备了图形界面的钱包软件。所使用的共识算法还是是“PoW”。
- Metropolis(大都会):分有下面两个子版本
- 拜占庭。发布了集合钱包功能以及合约发布等丰富功能的图形化界面软件“Mist”,同时也引入了很多新的技术,例如零知识证明,抽象账号等。使用的共识算法仍然是“PoW”。
- 君士坦丁堡。使用混合共识算法“PoW + PoS”,为“宁静”做铺垫。
- Serenity(宁静):将把以太坊的共识算法全部换成基于“PoS”的变种算法--“Casper投注共识”,它属于PoS系列。
账户模型
以太坊的账户区别于比特币中的UTXO的概念,其与银行个人账户模型的概念是比较相似的。以太坊中存在两种不同类型的账户:
- EOA(Externally Owned Account,外部账户):该类账户是由用户的公私钥控制,用户申请的地址代表一个外部账户,地址是作为控制该账户的公钥的最后20个字节(160位)导出的16进制格式,例如外部账户地址0x5f53d6B1FEc4C75B73D8A3bF0Ebc1306C439daBb,以太坊中的交易都是由外部账户发起。
- CA(Contract Accounts,合约账户):不能主动发起一个交易,被调用。
以太坊中的数据结构
-
状态树
以太坊采用的是基于账户的模式,系统显式的维护账户的余额(需要设计一个数据结构从账户地址到账户状态的映射)直观的看来,其本质为key-value键值对,所以直观的想法便是用哈希表实现,若不考虑哈希碰撞,查询效率为常数级。但采用哈希表,难以提供Merkle proof.
我们思考一下采取什么样的数据结构合适?我们能否像BTC中,将哈希表的内容组织为Merkle Tree? 不可以,因为每当新区块发布时,哈希表中的内容会改变,以此又会重新构建一个Merkle tree,对于以太坊中的账户,其数量级远大于比特币的交易数量,很明显这是不现实的。(比特币区块包含的交易上限为4000个左右,实际上块中的交易只有几百,所以Merkle tree不是无限增大的。而以太坊中若采用Merkle树来组织账户信息,很明显会越来越大,实际中发生变化的数据很小部分,每次重构代价很大)
注意:BTC系统中,虽然每个节点构建的Merkle Tree不一致(不排序),但最终是获得记账权的节点的Merkle Tree才是唯一有效的。
trie字典树->Patricia trie(tree)路径压缩的trie->Merkle Patricia Tree
(对于Patricia trie来说,如果插入新的值,原本的压缩路径可能需要扩展开来。所以插入的键值分布比较稀疏的情况下,路径压缩效果比较好。)在以太坊系统中,160位的地址存在2^160 种,该数实际上已经非常大了,和账户数目相比,可以认为地址这一键值非常稀疏(防止哈希碰撞)。
因此,以太坊采用了新的数据结构MPT(Merkle Patricia Tree,梅克尔帕特里夏树)
(采用修改过后的MPT)
每一个合约账户的存储都是一个小的MPT树
账户的状态是怎么存储在状态树的?(key地址,value)先使用RLP(Recursive Length Prefix)序列化编码后存储在状态树中。 -
交易树&收据树
交易树和收据树都是MPT,MPT的好处是支持查找操作
,通过键值沿着树进行查找即可。对于状态树,查找键值为账户地址;对于交易树和收据树,查找键值为交易在发布的区块中的序号。
每次发布一个区块时,区块中的交易会形成一棵MTP,即交易树。此外,以太坊还添加了一个收据树,每个交易执行完之后形成一个收据,记录交易相关信息。也就是说,交易树和收据树上的节点是一一对应的。(注意:交易树和收据树只将当前区块中的交易组织起来,而状态树将所有账户的状态都包含进去,无论这些账户是否与当前区块中交易有关系)
交易树和收据树的用途:向轻节点提供Merkle proof;提供更加复杂的查找操作
以太坊中的主链选择协议—GHOST协议
以太坊中采用的GHOST(Greedy Heaviest-Observed Sub-Tree protocl,贪婪子树协议)
用来保障其最长合法链(考虑了分叉的情况,给予叔块奖励及时让分叉进行合并)
GHOST协议最初版本:
假定以太坊系统存在以下情况,A、B、C、D在四个分支上,最后,随着时间推移B所在链成为最长合法链,因此A、C、D区块都作废,但为了补偿这些区块所属矿工所作的工作,给这些区块一些“补偿”,并称其为Uncle Block叔父区块
。规定E区块在发布时可以将A、C、D叔父区块包含进来,A、C、D叔父区块可以得到出块奖励的7/8,而为了激励E包含叔父区块,规定E每包含一个叔父区块可以额外得到1/32的出块奖励。为了防止E大量包含叔父区块,规定一个区块只能最多包含两个叔父区块,因此E在A、C、D中最多只能包含两个区块作为自己的出块奖励。
最初版本缺陷:
- 因为叔父区块最多只能包含两个,如图出现3个怎么办?
- 矿工自私,故意不包含叔父区块,导致叔父区块7/8出块奖励没了,而自己仅仅损失1/32。如果甲、乙两个大型矿池存在竞争关系,那么他们可以采用故意不包含对方的叔父区块,因为这样对自己损失小而对对方损失大。
我们将“叔父”这个概念进行扩展,“叔父”这一定义隔多少代才好呢?
如下图所示,M为该区块链上一个区块,F为其严格意义上的叔父,E为其严格意义上的“爷爷辈”。以太坊中规定,如果M包含F辈区块,则F获得7/8出块奖励;如果M包含E辈区块,则F获得6/8出块奖励,以此类推向前。直到包含A辈区块,A获得2/8出块奖励,再往前的“叔父区块”,对于M来说就不再认可其为M的"叔父"了。对于M来说,无论包含哪个辈分的“叔父”,得到的出块奖励都是1/32出块奖励。也就是说,叔父区块的定义是和当前区块在七代之内有共同祖先才可(合法的叔父只有6辈)。
https://blog.csdn.net/RenLJ1895/article/details/122397207(这篇理解GHOST协议还不错)
以太坊中的挖矿算法
以太坊中设计了两个数据集,一大一小。小的为16M的cache,大的数据集为1G的database(DAG)。两种之间的关系为1G的数据集是通过16M的cache生成而来。(为什么要设计一大一小两个数据集? 为了便于进行验证,轻节点保存16M的cache进行验证即可,但对于挖矿来说,如果这样则大部分算力都花费在了通过Cache计算DAG上面,因此为了减少重复计算则需要存储1G大小的数据集)
-
16M cache的生成:Seed为种子节点,通过Seed进行一些运算获得第一个数,之后每个数字都是通过前一个位置的值取哈希得到的(数组中取值存在前后依赖关系)
-
1G DAG生成方式:大的数据集中的每个元素都是从小数据集中按照伪随机顺序读取一些元素,如第一次读取A的位置,对当前哈希值更新迭代算出下一次读取的位置B,再进行哈希值更新迭代计算出C位置元素,如此来回迭代读取
256次
,最终算出一个数作为DAG中的第一个元素,如此类推。
-
以太坊挖矿过程:用的是大数据集中的数,根据区块头和nonce值计算一个初始哈希值,映射到大数据集中的某个位置A,读取A位置的数以及后一个相邻位置A'的数进行运算,算得下一个位置B,读取B位置的数以及后一个相邻位置B'的数,以此类推,迭代读取64次,共读取128个数。最后计算出一个哈希值与挖矿难度目标阈值比较,若不符合则更换新的nonce值,重复以上操作直到计算出的哈希值符合要求或当前区块已经被挖出。
以太坊挖矿难度调整
比特币中的挖矿难度调整是每隔2016个区块进行调整,从而达到维持出块时间稳定在10min左右,而以太坊则不同,每个区块都有可能进行难度调整。具体如下:
以太坊中的共识——PoS
以太坊中的采用的共识是PoS(Proof of Stake,权益证明)的变种——Casper the Friendly Finality Gadget(FFG)
Casper协议引入一个概念:Validator(验证者),一个用户想要成为Validator,需要上交一笔“保证金”,这笔保证金会被系统锁定。Validator的职责是推动系统达成共识,投票决定哪一条链成为最长合法链,投票权重取决于保证金数目。
实际中,采用两次投票的方式:预投票
和Commit投票
,规定每次投票结果都要获得2/3
以上的验证者同意。在实际中,针对其进行了一些修改,两次投票在实际中只需要一次即可。
矿工挖矿会获得出块奖励,而验证者也会得到相应奖励。当然,为了防止验证者的不良行为,规定其被发现时要受到处罚。例如某个验证者“行政不作为”,不参与投票导致系统迟迟无法达成共识,这时扣掉其保证金;如果某个验证者“乱作为”,给两边都进行投票,被发现后没收全部保证金。没收的保证金被销毁,从而减少系统中货币总量。验证者存在“任期”,在任期结束后,进入“等待期”,在此期间等待其他节点检举揭发是否存在不良行为,若通过等待期,则可以取回保证金并获得一定投票奖励。
了解DeFi、NFT的概念
DeFi,即Decentralized Finance(去中心化金融)是一种创建于区块链上的金融,它不依赖券商、交易所或银行等金融机构提供金融工具,而是利用区块链上的智能合约进行金融活动。
一般说来,加密数字货币可分为两类:同质化代币(FT)和非同质化代币(NFT)。
FT(Fungible Token,同质化代币):指的就是ETH、BNB等代币,在交易转账等过程中每个代币可以互换、无限拆分,无法区分。
NFT(Non-Fungible Token,非同质化代币):指每个代币拥有独特且唯一的标识,两两不可互换,最小单位是1且不可分割,如加密猫,MEME等应用。
思考问题
账户模型和UTXO的优劣之处
以太坊这种基于账户的模式更加符合我们日常生活中的消费习惯,而且其天然的防范了double spending双花问题,因为无需关系币的来源,每花费一次,只需从账户扣除即可。但是以太坊的账户模型也有缺点,该模型存在replay attack重放攻击
的缺陷,例如A向B转账,过了一段时间,B将A的交易重新发布,从而导致A的钱被扣了两次。
为了防范重放攻击,开发者给账户交易添加计数器
记录该账户交易过多少次,转账时将转账次数也计入交易的内容中。系统中全节点维护账户余额和该计数器的交易数,从而防止本地篡改余额或进行重放攻击。
比特币这种基于交易的模式UTXO不太符合我们日常生活中的消费习惯,此外在进行交易时必须将币一次性转出,否则为转出的一部分将会以交易费用的形式奖励给挖出区块的矿工(即在交易时至少将剩下的币转移到自己的另一个地址,这样也变相的增加了被篡改的难度),但是其很好的解决了double spending双花攻击。
为什么要做以太坊,更换为基于账户的模型而不是沿袭BTC系统?
比特币中支持每次更换账户,但以太坊是为了支持智能合约,而合约签订双方是需要明确且较少变化的。尤其是对于合约账户来说,需要保持稳定状态。
PoS共识和GHOST共识的区别?
以太坊中的共识是PoS的变种Casper共识,其中的validator节点投票决定哪一条链成为最长合法链,而GHOST协议是通过引入叔块奖励鼓励系统中出现分叉之后及时进行合并,保障最长合法链(而不是决定)