【区块链基础】4——ETH区块结构
账户
与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种,value是RLP编码的数据;
- 空白节点 NULL
ETH对MPT做了略微的改进:
- Extension Node 和 Branch Node 与原生的MPT不同;
- prefix 分奇偶数个nibbles(16进制数);
具体以官方的下图为例:
MPT作用如下:
- 防止篡改
只要根哈希值不变,整个树的任何部分都无法被篡改,每个账户的状态不会被篡改。 - 证明账户余额
账户所在的分支自下而上作为merkle proof发给轻节点,轻节点进行验证。
交易树
用于记录交易的数据信息,其结构也为MPT,其键值为交易在发布的区块中交易的序号。
收据树
每笔交易完成后形成一个收据,用于记录交易的相关信息与执行结果,其数据结构也为MPT,其键值为交易在发布的区块中交易的序号,与交易树中的节点一一对应,。由于ETH智能合约执行过程比较复杂,增加收据树有利于快速查询执行结果。
布隆过滤器 bloom filter
bloom filter可以比较高效的查找某个元素是否包含在比较大的集合之内。直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。
算法:
- 首先需要k个hash函数,每个函数可以把key散列成为1个整数
- 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
- 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
- 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中。
在查找某一交易时可快速过滤掉大量无关的区块
区块
header
// Header represents a block header in thr Ethereum blockchain.
type Header struct {ParentHash common.Hash `json:"parentHash" gencodec:"required"`UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`Coinbase common.Address `json:"miner" gencodec:"required"`Root common.Hash `json:"stateRoot" gencodec:"required"`TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`Bloom Bloom `json:"logsBloom" gencodec:"required"`Difficulty *big.Int `json:"difficulty" gencodec:"required"`Number *big.Int `json:"number" gencodec:"required"`GasLimit uint64 `json:"gasLimit" gencodec:"required"`GasUsed uint64 `json:"gasUsed" gencodec:"required"`Time *big.Int `json:"timestamp" gencodec:"required"`Extra []byte `json:"extraData" gencodec:"required"`MixDigest common.Hash `json:"mixHash" gencodec:"required"`Nonce BlockNonce `json:"nonce" gencodec:"required"`
}
- ParentHash:前一个区块header的哈希
- UncleHash:叔块的哈希,可能比Parent大好几辈
- Coinbase:挖出区块的矿工地址
- Root:状态树的根哈希
- TxHash:交易树的根哈希,类似于比特币中的merkle root
- ReceiptHash:收据树的根哈希
- Bloom:布隆过滤器,和收据树相关,提供高效的查询符合某种条件的交易的执行结果
- Difficulty:挖矿难度
- GasLimit,GasUsed:和汽油费相关,智能合约消耗汽油费,类似于比特币中的交易费
- Time:区块产生时间
- MixDigest:nonce经过计算得到的哈希
- Nonce:符合难度要求的随机数
block
// Block represents an entire block in the Ethereum blockchain.
type Block struct {header *Header //区块头uncles []*Header //叔块transactions Transactions //区块打包的一批交易数据// cacheshash atomic.Valuesize atomic.Value// Td is used by package core to store the total difficulty// of the chain up to and including the block.td *big.Int //总难度值// These fields are used by package eth to track// inter-peer block relay.ReceivedAt time.TimeReceivedFrom interface{}
}
- header:指向header的指针
- uncles:指向叔块的header的指针数组
- transactions:交易列表
extblock
// "external" block encoding. used for eth protocol, etc.
type extblock struct {Header *HeaderTxs []*TransactionUncles []*Header
}
extblock为真正发布的区块信息,即为block结构的前三项。
新区块发布
多个区块的状态树共享节点,每次发布新区块,MPT树中部分节点状态会改变,但改变并非在原地修改,而是新建一些分支,保留原本状态。当仅仅有新发生改变的节点才需要修改,其他未修改节点直接指向前一个区块中的对应节点。而交易树与收据树只将当前区块内发布的交易组织起来,如图所示:
由于以太坊中出块时间15s左右,会产生很多的分叉,保持历史记录的一个好处是,当某些分叉需要回滚时可以更好的查看历史记录。
交易驱动的状态机 transaction-drived state machine
ETH为一个交易驱动的状态机,其状态为状态树中账户的状态,通过执行交易树的交易,可驱动系统由当前状态转移到下一个状态,其状态转移时确定性的,即通过给定的当前状态和交易,能确定性的转移到下一个状态。
参考资料
- 北京大学肖臻老师《区块链技术与应用》公开课
区块链基础系列
- 【区块链基础】1——密码学基础
- 【区块链基础】2——BTC区块结构
- 【区块链基础】3——BTC协议
欢迎打赏Σ(っ°Д°;)っ
【区块链基础】4——ETH区块结构相关推荐
- 【区块链基础】5——ETH协议
GHOST协议 以太坊系统将出块时间降到了15秒左右,相比于比特币系统大幅度提升了出块的速度,但由于P2P网络延迟,会导致出现大量的临时性分叉,间接造成算力的分散,若沿用比特币系统中最长合法链原则,将 ...
- 区块链基础与网络安全
区块链基础与网络安全 区块链定义 什么是比特币 比特币信任来源 比特币原理 比特币->区块链 区块链核心技术 区块链的特征 区块链核心技术 区块链攻击对象 1. 数据层 2.网络层 3.激励层 ...
- 区块链指南 第2章 区块链基础
目录: 2.1 区块链技术 区块链本质上是一个对等网络(peer-to-peer)的分布式账本数据库.区块链本身其实是一串链接的数据区块,其链接指针是采用密码学哈希算法对区块头进行处理所产生的区块头哈 ...
- 【问链财经-区块链基础知识系列】 第三十二课 从区块链溯源来看农产品链的设计
在区块链的应用场景中,农产品溯源和食品溯源一直是翻来覆去讲的故事,但实际上溯源是一个伪命题,农产品和食品的加密上链实现溯源看起来很丰满,然而现实却很骨干.我们经常忘记了初心:溯源的目的是为了什么? 农 ...
- 【问链财经-区块链基础知识系列】 第二十七课 区块链与分布式账本的异同
编者按:在加密货币和区块链领域,有一个业内人士常挂在嘴边的新术语:分布式账本技术(简称DLT).但具有讽刺意味的是,恰恰是比特币和各种区块链试图颠覆的实体们,例如银行,政府和大公司,对分布式账本技术情 ...
- 区块链基础学习(一)
一.区块链简介 1.1.区块链与区块链技术 区块链是将记录(区块)通过密码学串联并加密的链式数据结构.而区块链技术,是通过P2P网络和区块链来实现数据存储的去中心化.不可逆和不可篡改.比特币正是构建在 ...
- 【问链-区块链基础知识系列】 第十课 首席架构师谈区块链技术演进
一.区块链和比特币,都有"币-链-网"三层含义 1.第一层含义是"币".这个"币"并不是刚才王行长所说的真正意义上的"货币&quo ...
- 区块链基础知识与关键技术解析
区块链基础 1. 区块链的来龙去脉 1.1 区块链技术起源 1.2 比特币产生背景与现状 1.3 数字货币概念 1.4 比特币技术原理 2. 区块链概念与产业现状 ...
- java玩转区块链-基础篇-账户
java玩转区块链-基础篇--账户 java环境配置 基础概念 账户 maven包引用 创建账户代码 代码解释 (1) (2) (3) (4) 可以不让搞,但是不允许你不会 java环境配置 jdk版 ...
最新文章
- sqlserver存储过程循环写法
- 浅析 React Fiber
- 【英语天天读】I want I do I get
- 《ASP.NET Core项目开发实战入门》送书活动结果公布
- html 跟随鼠标移动线条,canvas跟随鼠标移动的随机线条
- 数据结构之平衡树:2-3查找树的介绍——16
- 【HANA系列】SAP HANA Studio出现Fetching Children...问题
- 为什么要在JavaScript中使用静态类型? 我们是否应该使用它们?
- 事件CEvent的使用
- P1181 数列分段Section I
- IP数量就是计算机数量吗,如何利用bash/python计算IP子网容纳计算机数量
- html 页面缩放事件,浏览器缩放不触发window.onresize事件的BUG
- ROS安装教程(详细)
- Odoo12功能增强模块
- php远程登录linux,如何远程连接linux桌面
- 笔记本电脑连接(扩展)外接显示器之后桌面图标乱放位置解决办法-以win10系统为例
- 使用python绘制标准心形线
- 3.3 费马质数测试
- Altium Designer之PCB库部分名称区分
- lda主题模型python实现篇_主题模型TopicModel:通过gensim实现LDA
热门文章
- 合格的CTO应该是什么样?雷军王海峰王小川等共谈「技术创新」| CNCC2020-1
- 使用脚本更改计算机名
- 转贴:粒子在施瓦西黑洞内部是如何运动的?
- 大数据——Flink Window(窗口)机制
- SwiftUI的多列列表
- [HDF5] 封装了一个简单的C++ HDF5工具库,实现常用数据类型的读写
- 危与机并存 保险业如何走好线上线下业务并举转型之路?
- R语言read.csv()读入行不规则数据
- IntelliJ IDEA项目正常编译,但是代码部分飘红
- css 根据不同屏幕设置间距_CSS根据屏幕分辨率宽度自动适应的办法