账户
与BTC不同,ETH使用的是基于账户的账本(account-based ledger),账本中记录了各个用户的的余额,交易时不必追溯币的来源。
基于账户的账本对双花攻击(duoble spending attack)有着天然的防御作用,账户余额是系统中全节点维护的一个状态,称为balance,交易发生时余额随机改变,但与之而来的问题便是重放攻击(reply attack):若将已发布的交易再一次进行广播发布,造成支付者多次支付,接收者将因此获利。
ETH中使用nonce解决这一问题,nonce作为账户状态中的一个字段,有着计数器的功能,记录了账户有史以来交易的次数,转账时,nonce成为交易内容的一部分,受支付者的签名保护。
ETH有两类账户:
- 外部账户(externally owned account)
也称普通账户,由公私钥对进行控制,包含之前所述的balance和nonce;另外一类账户为合约账户; - 合约账户(smart contract account)
合约账户不是通过公私钥对进行控制。在创建合约时,合约将返回一个地址,由此地址可调用合约,但合约账户不能主动发起一次交易,所有的交易只能由外部账户发起,之后可能会引起合约间的相互调用。另外,除了balance和nonce,合约账户还有代码code和存储storage。
由于ETH支持智能合约,要求参与者有比较稳定的身份,这与BTC的设计有所不同。
状态树
ETH的账户地址是160bits,共20个字节,账户地址到账户状态为一对映射,账户状态为前述的包括balance,nonce,code,storage等。所有的账户组织成一个改进的Merkle Patricia Tree。
存储账户状态的结构为状态树,其基本数据结构为Merkle Patricia Tree。MPT是一种融合了merkle tree和patricia tree两种树结构优点的数据结构,用路径压缩提高效率,并可计算出一个账户状态的根哈希值, 保存于block header中。
merkle tree可参考:【区块链基础】2——BTC区块结构
patricia tree可参考:patricia-tree
MPT丰富了节点类型,共有如下4个类型的节点:
- 扩展节点 extension Node: [key, value],只能有一个子节点。这里的value值存储的是孩子节点的哈希值;
- 分支节点 branch Node [0,1,…,16,value],可以有多个节点。因为MPT树中的key被编码成一种特殊的16进制的表示,再加上最后的value,所以分支节点是一个长度为17的list,前16个元素对应着key中的16个可能的十六进制字符,如果有一个[key, value]对在这个分支节点终止,最后一个元素为value值,存储的是刚好在分支节点结束时的值,若没有节点在分支节点中结束时,value值没有存储数据,即分支节点既可以搜索路径的终止也可以是路径的中间节点。分支节点的父亲必然是extension node;
- 叶子节点 leaf Node : [key, value],这里的key都是16编码出来的字符串,每个字符只有0-f 16种&