1.ETH——以太坊概述
(1)比特币、以太坊
- 比特币——区块链1.0,实现的是去中心化的货币(deccentralized currency),货币计量单位——1 Satoshi(一聪)
- 以太坊——区块链2.0,增加了去中心化的合约(技术手段取代司法手段)的支持(decentralized contract),货币计量单位——1 Wei
- 以太坊的改进:1)出块时间大大缩减到十几秒 2)挖矿使用的mining puzzle,比特币的mining puzzle计算密集型的,比拼的是计算哈希值的算力(结果是挖矿设备的专业化)。以太坊设计的memory hard mining puzzle对内存的要求很高,在一定程度上限制了ASIC芯片的使用。 3)以太坊用权益证明(proof of stake) 代替工作量证明(proof of worlk),按照股份投票的方法决定下一个区块怎么产生。 4)以太坊增加对智能合约(smart contrct) 的支持
(2)去中心化的货币有什么好处?
- 跨国转账(从美国转一笔账到埃及,用法币是很麻烦的,交易费也很贵,如果用比特币转账就会好很多)
- 智能合约也有类似的应用场景,比如合同的签署方是来自世界各地,没有统一的司法管辖权,这时用司法手段维护合同的有效性就很困难。这种情况下用事先写好的程序代码来保证每个人都按照规则来执行,就比较好。 | 代码一旦发布到区块链上,不可篡改性就能保证大家只能按照代码中制定的规则来执行。
2.ETH——账户
(1)比特币中用的是基于交易的账本,没有显示地记录每个账户的余额(根据UTXO推断)。
- 好处:隐私保护好
- 使用别扭:A转给B 10个比特币,要说明这10个币的来源,B给转给C 3个币,剩余的7个币要转给B的另一个地址(一次性要花完),很多比特币钱包可以自动生成接收余额的地址
(2)以太坊中用的是基于账户的模型,和银行相似,系统中显示记录每个账户上有多少以太币。
- A转给B 10个以太币(只要检查A账户上是否有足够的钱转账),B转给C 3个币,剩余的币留在账户上,B币的来源也不用说明。
- 好处:天然抵制double spending attck(花钱的人不诚实,以前花过的钱要再发一次)。状态树——所有账户的状态组成一棵树,余额是其中一个重要的域,余额没办法篡改,除非得到所有节点的认可。
- replay attack(重放攻击,收钱的人不诚实,以前这笔钱别人已经收过了,还要让他发一次)A转给B10个以太币,发布这个交易到区块上,A以为这个交易完成了,B是恶意账户,它又把这个交易发布了一遍,这样其他的账户以为A又完成了一笔交易,又扣了一次币。
- 加一个计数器nonce——记录这个账户有史以来一共发布了多少笔交易,且它要成为交易的一部分,受到发布交易者签名的保护。
(3)外部账户(普通账户)
- 用公私钥对控制
- 余额balance,nonce
- 所有交易只能由外部交易发起
(4)合约账户
- balance,nonce,代码code,状态state
- 一个合约可以调用另一个合约,也通过nonce来记录调用的次数。
- 外部账户发起一个交易,如果调用一个合约账户,它可以发送一个massage调用另外一个合约
- 怎么调用?创建一个合约的时候会生成一个地址,通过这个地址就可以调用。
(5)为什么不在比特币系统的基础上改进,而是要新建一个以太坊
- 智能合约
- 如果你和一个人签合同,签的时候是一个身份,签完后他的身份就变了,也找不到了,就有问题。将来出现纠纷的时候,也需要知道当初这个合约是和谁签的。
3.ETH——状态树
(1)账户地址Addr——>账户状态State
- 地址是160bit的(20字节,40个16进制的树)
- 方案一:用哈希表实现(这个方法不行,代价太大)——系统中的全节点维护一个哈希表,每次有新的账户插入到哈希表中。如果要提供Merkle Proof怎么办?比如你要和一个人签合同,希望他能证明一下他有多少钱,把哈希表中的元素组织成一棵Merkle Tree,然后算出一个根哈希值,保存在block header中,公布出去,只要根哈希值是正确的,就能保证底下的树不被篡改。问题:发布新区块,新区块中包含新的交易,要执行这个交易,就必然会使哈希表的内容发生变化,发布下一个区块的时候又要重新组织一棵MerkleTree。实际上发生状态变化的账户只是一小部分。
- 比特币系统中每出一个新的区块也要构造一棵新的Merkle Tree,它是把区块中包含的交易组织成一棵Merkle Tree,构成之后就不会修改,下次再发布新区块的时候再构建一棵新的Merkle Tree。区块中大概有4000个交易。
- Merkle Tree除了证明余额之外,还有一个作用是维护各个全节点状态的一致性,区块中包含哪些交易所有的全节点要有共识。
- 方案二:用一棵MerkleTree来组织所有的账户,要改的时候就在MerkleTree上改。
- 问题1:MerkleTree没有提供一个高效、便捷的查询和更新的方法。比特币中的MerkleTree最底下一层是交易,两两结合取哈希。
- 问题2:MerkleTree要排序吗?要证明一个交易包含在区块中,是不用排序的,但是要证明不存在是要用排序的,否则代价就变为了线性。/ 如果不给这些叶节点排序,那么构建出来的MerkleTree不是唯一的。
- 比特币中是否存在这种问题?获得记账权的节点可以决定交易的顺序,是唯一的。每个节点在本地组装一个候选区块,这些节点自己决定哪些交易应该被打包到区块里,然后去挖矿竞争记账权。
- 排序的MerkleTree呢?产生一个新区块的地址是随机的,很可能是插入到中间的,新产生的一个区块其他人是不必知道的,当它与外界发生交易时才需要公布。区块链删除东西是很麻烦的,添加容易。
- 以太坊中没有显式地删除账户的操作。
(2)以太坊用MPT结构
- trie数据结构:①每个节点的分支数目取决于key每个元素的取值范围(字母就是最多26)。 ②查找效率取决于key的长度。③不会出现碰撞。④不论输出的顺序是怎么样的,构成的Tree都是同一棵树。⑤更新的局部性:只用更新对应一条路径(分支)。⑥存储有点浪费
- 我们的应用: ①branching factor,17(16+结束标识符)。②所有的键值是一样长的(40)。
- Patricia Tree:将trie树进行路径压缩。①树的高度变短,访问内存的次数变少。②如果新插入一个值,压缩的部分可能要展开。③树中插入键值的分布比较稀疏的情况下,路径压缩效果比较好。
- PMT:Merkle Pertricia Tree与PT的区别是
- 【MerkleTree和BinaryTree的区别】把普通指针换成了哈希指针。
- 【根哈希值】①防止被篡改 ②Merkle Proof能证明账户上的余额(账户所在的分支向上作为MerkleProof发给轻节点,它可以验证) ②证明某个账户不存在,把MerkleProof发过去。
- 以太坊中用的是Modified MPT。系统中不只维护一棵MPT,而是系统中每出现一个新的区块,就要构建一棵MPT。大部分节点是共享的,只有少数发生变化的节点。
- 为什么不直接在原地修改?①当前交易可能要undo
- 比特币可以通过反向推测来推理:A-->B(10 BTC),假设这个交易要回滚,只要把B减少10个BTC,A加上10BTC
- 以太坊中有智能合约,如果不保存以前的状态,就不能回 滚了。
【ps】比特币和以太坊中的地址是不通用的,格式和长度都不一样。
- block Header中的数据结构
-
- Coinbase:矿工的地址
- 状态树根哈希Root:
- 交易树根哈希值TxHash:
- 收据树根哈希值ReceiptHash:
- Bloom:提供一种高效的查询执行结果
- Difiiculty:挖矿难度,根据需要调整
- GasLimit、GasUsed:汽油费相关
- Time:区块的产生时间
- MixDigest、nonce:与挖矿相关,MixDigest是nonce经过计算,算出的哈希值。
- 区块的结构:
- 真正在网上发布的就是这个:
- 账户的状态是怎么存储在状态树中的
- 要经过一个序列化的过程:RLP(Recursive Length Prefix)
- Protocol buffer(protobuf):很常用的做序列化的库,它的理念是越简单越好,只支持一种类型,nested array of bytes
4.ETH——交易树和收据树
(1)交易树
- 概念:每出一个新的区块的时候,区块中所包含的交易会组成一棵交易树,也是Merkle Tree,类似比特币
- 交易树也是MPT,与比特币有区别
- 向轻节点提供MerkleProof
(2)收据树
- 概念:以太坊还新增了一棵收据树,每个交易完成后会形成一个收据,记录交易的相关信息。
- 作用:考虑到智能合约执行较复杂,收据树有利于快速查询执行结果
- 收据树也是MPT
- 要证明某个交易的执行结果,也可以提供MerkleProof
(3)区别
- MPT支持查找操作
- 对于状态树,查找的键值:交易的地址
- 对于交易树和收据树,查找的键值:这个交易发布到区块里的序号
- 状态树是把系统中所有账户的状态都要包含进去,交易树和收据树只把当前发布区块的交易组织起来
- 状态树共享节点,交易树和收据树是独立的
- 数据结构
- 交易树:
-
- 收据树:
-
- 处理叔父区块:
-
- DeriveSha函数:
-
- Receipt:
-
- Bloom:
(4)bloom filter
- 支持比较高效的查找,比如你要在一个很大的集合中找到某个元素
- 思想:给大的集合计算出一个很紧凑的摘要
-
- 有可能出现false positive(误报),但是不会出现false nagetive(漏报)
- 如果要删除一个元素,怎么删?——一般不支持删除操作。(只有0,1),除非用一个计数器,还要确保计数器不会overflow,这样数据结构机会很复杂,与bloom Filter的初衷相违背
(5)其他
- 你想找到过去10天和某个智能合约相关的所有交易
- 方法一:把过去10天产生的区块都扫描一遍,复杂度高(轻节点没有交易列表,只有交易信息)
- 方法二:查找一下哪个区块的块头里的bloom filter有我要的区块的类型,如果没有的话,则这个区块不是我们想要的;如果有的话,再去查找这个区块里包含的交易所对应的收据树的bloom filter
- 好处:能快速过滤掉很多无关的信息
- 以太坊是一个交易驱动的状态机:通过执行交易会驱动系统从当前的状态转移到下一个状态
- 状态:所有账户的状态
比特币也可以认为是一个交易驱动的状态机,每次新发布一个区块会从UTXO用掉/新增一些输出,所以发布区块会驱动状态机从当前状态转移到下一个状态
- 状态:UTXO,没有被花掉的输出
- 共同点:状态转移是确定性的,一组给定的状态+一组给定的交易——>转移到确定的状态
- 例子1:有人在以太网上发布一个交易,某个节点收到这个交易,说转账从A到B,有没有可能收款人的地址未知?——可能,因为以太坊中创建一个账户是不用告知所有人的,只当它发生某个交易时,才要插入到状态树中
- 例子2:可以修改状态树,把状态树中的账户修改成与当前交易有关的账户吗?——这样查找某个账户的状态就不方便了。如果是个新建的账户,要从当前账户找到创世纪块,才发现没有这个账户。
5.ETH——GHOST(以太坊中的共识机制)
(1)只有包含在最长合法链上的区块里面所包含的区块奖励才是真正有用的。
(2)GHOST
- 以太坊出现以前就有了GHOST协议
- 核心思想:你挖到了矿,发布了区块,但是区块最后作废了,我们给你一些奖励。有利于鼓励系统中出现分叉之后,及时进行合并。
- 缺陷:
- 如果有三个叔父区块呢?
- 叔父区块成为后面最长合法链后面的那个区块的叔父的前提是在它发布前已经知道叔父区块的存在了,如果叔父区块在它产生之后才发布,那么叔父区块也得不到奖励。
-
- 叔父区块的定义:必须跟当前区块在七代以内有共同的祖先,有利于鼓励出现分叉后及时合并,一出块就合并的时候得到的奖励是最多的(7/8)。
- 把叔父区块包含进来的时候,叔父区块里的交易要不要执行?——父区块可能和叔父区块中的交易有冲突。不会检查叔父区块交易的合法性,只检查叔父区块是否符合挖矿难度。
- 叔父区块都是分叉后的第一个区块,那叔父区块后面跟着的区块怎么办?——
- 目的:为了解决系统中出现的临时性分叉,最长合法链的出现是为了降低被篡改的可能性。
- 出块奖励
- 比特币:静态的block reward、动态的tx fee
- 以太坊:静态的block reward(3个以太币)、动态的gas tee(输入区块得不到汽油费)
- 一个区块最多包括两个叔父区块uncle block。