精华内容
下载资源
问答
  • 2022-04-22 13:47:57

    以太坊基本原理包括:以太坊账户、以太坊虚拟机、钥匙文件、交易、Gas、以太坊区块、以太币

    1.以太坊基本原理

    1.1 以太坊简介

    以太坊是一个开源的有智能合约功能的公共区块链平台,它提供了一个虚拟机来处理点对点的合约。以太坊概念最早是由Vitalik Buterin在2013年到2014年被提出的,2014年通过ICO众筹开始得以发展

    以太坊的本质就是一个状态机(读取输入并且输出)

    相比比特币的10分钟产生一个区块,以太坊每产生一个区块大约是15s,以太坊把30000个区块当做一个纪元,每个纪元的耗时为125h,这个也是通过难度调整算法来实现的

    GHOST协议

    以太坊区块产生的时间区间是15s,在此期间,如果不同节点都打包好了区块,那此时无法确定应该纳入哪个节点的区块,接着让接节点比赛谁先打包好下一个区块,谁先挖出谁获胜,但是以此类推,算力最强的节点将会控制整个链,因为在更长的时间内,它一定能够产生更长的链,算力小的节点的打包区块将不会被算力强的节点采用

    为了解决上述问题,以太坊使用了GHOST协议

    1.每个区块必须有一个父块,有0个或者多个叔块

    2.叔块必须是当前区块的k代祖先的直系区块,2 <=k <=7

    3.叔块不能是当前区块的祖先

    4.叔块必须有合法的区块头,但是可以不经过验证,甚至不是合法的区块

    5.叔块不能被重复包括

    挖出一个叔块的奖励

    (uncle.numer + 8 - header.number)/8*blockReward
    

    挖出一个叔块最少可获得1/4*blockReward

    引用n个叔块的奖励

    n*1/32*blockReward
    

    最多可以引用2个,也就是说可以拿到1/16分之一的奖励

    打包一个有效区块的奖励

    Gas费用 + 引用n个叔块的奖励 + 静态奖励
    

    总结:GHOST协议本质上是促使挖到叔块的节点尽快把挖到的节点交出去让主链节点引用,并且接着最新的区块挖,这样在利益最大化的驱使下,节点会尽可能的在一条链上打包区块

    1.2 以太坊账户

    以太坊有两种账户类型:合约账户和外部账户

    外部账户功能上和比特币的账户模型是一样的:发送交易,查看余额等,但是产生的机制不同:具体而言就是:私钥-公钥-地址-取最后的20位

    合约账户:合约账户在合约部署时生成,用来收取gas费用,调用者需要支付一定的Gas费来执行,这些交易费用到时候会奖励给产生区块的节点

    账户状态

    type Account struct {
       Nonce    uint64
       Balance  *big.Int
       Root     []byte
       CodeHash []byte
    }
    

    nonce:代表外部账户的交易数量,代表合约账户创建的合约序号

    balance:余额(单位wei)

    storageRoot:Merkle Partricia树的根节点hash值

    codeHash:外部账户是空字符串的哈希值,合约账户是EVM代码的哈希值(合约代码的哈希值)

    每个区块都有一个header,header里包含三个树,状态树,交易树,收据树

    节点类型:全节点和轻节点,下载全节点数据量比较大,截止此刻,区块高度是14628886,轻节点只包含区块头

    1.3 Gas和费用

    以太坊中各种操作都需要支付gas,如存储数据、创建合约以及执行哈希计算等

    gas = gasPrice * gasLimit: 操作发起方在某次操作中愿意支付的最高手续费

    gasPrice通常等于1gwei = 1亿分之一ETH(1ETH = 一亿亿分之一wei),当网络中的算力下降时,gasPrice就会上升,以吸引更多的节点参与区块打包。另外,gasPrice会直接影响成交速度

    gasLimit:某次操作中gas消耗上限

    此机制主要是防止由未知错误带来的gas浪费,需要尽可能的减少损失。如某次合约调用过程中,未知错误导致了循环,导致合约一直执行,这将会消耗很多gas,设置gasLimit可以减少这种损失

    以太坊中对于常见操作需要的gas的规定
    交易基本费用:500gas

    创建合约:53000gas

    交易每个字节:5gas

    费用机制的核心在于维护网络的安全及繁荣

    1.4 交易和消息

    两种交易类型:交易和消息

    交易由外部账户发起,指向另一个账户发送存储消息的签名数据包(此处可理解为转账)

    消息是内部合约发起的,本质上还是一个交易

    交易和消息都包含:

    nonce:此处的nonce和账户中的nonce(该账户已完成的交易数量)不同,它是一个累加整数,可选指定,它需要大于账户中的nonce值,会影响交易的被打包进区块的时间。例如,账户中的nonce是2,发送交易时,指定其为4,那此笔交易不会被马上打包进区块,而是会被放入交易池等待,直到缺失的nonce被提交到交易池中。在实际转账时可以通过提交相同nonce的交易来覆盖之前的那一笔

    gasPrice:一般钱包会计算出一个均值

    gasLimit:

    to: 收款方地址

    value: 转账金额

    v,r,s:数据签名,验证交易的合法性

    init:初始化新合约账户的EVM代码片段

    data :对于外部账户交易来说,是可选项。对创建合约而言是编译后的合约字节码,对于合约方法调用来说,是合约方法签名和参数编码

    合约与合约之间可以相互调用执行,并不需要Gas费用

    有效交易

    交易必须是正确格式化的RLP

    签名有效

    交易序号有效

    gas limit 大于等于交易使用的intrinsic gas

    1.5 区块

    包含区块头,交易信息以及其他信息

    type Block struct {
    	header       *Header
    	uncles       []*Header
    	transactions Transactions
    
    	// caches
    	hash atomic.Value
    	size 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.Time
    	ReceivedFrom interface{}
    }
    

    区块头,区块头中包含了三棵树:状态树、交易树和收据树

    // Header represents a block header in the 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        uint64         `json:"timestamp"        gencodec:"required"`
    	Extra       []byte         `json:"extraData"        gencodec:"required"`
    	MixDigest   common.Hash    `json:"mixHash"`
    	Nonce       BlockNonce     `json:"nonce"`
    
    	// BaseFee was added by EIP-1559 and is ignored in legacy headers.
    	BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
    
    	/*
    		TODO (MariusVanDerWijden) Add this field once needed
    		// Random was added during the merge and contains the BeaconState randomness
    		Random common.Hash `json:"random" rlp:"optional"`
    	*/
    }
    

    日志

    日志可以跟踪各种交易和信息

    合约可以通过定义事件来显示生成的日志

    日志实体包含:

    记录器的账户地址

    代表本次交易的执行的各种事件的一些主题以及与这些事件相关的任何数据

    日志被被保存在bloom过滤器中,过滤器能够高效的保存无尽的日志数据

    交易收据

    包括:区块号、区块哈希、交易哈希、当前交易使用了的gas、执行完当前交易之后该区块累计使用的gas,当前交易日志

    区块难度

    nonce <= 2的256次方 / 区块难度

    区块难度算法

    /*
    		Algorithm
    		block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2))
    
    		Where:
    		- pdiff  = parent.difficulty
    		- ptime = parent.time
    		- time = block.timestamp
    		- num = block.number
    	*/
    

    1.6 执行模式

    EVM以太发虚拟机

    是图灵完备的虚拟机

    基于堆栈的架构

    每个对栈顶的大小为256位,堆栈有一个最大的大小,为1024位

    有一个存储器

    有专用语言:”EVM字节码”

    1.7 以太坊网络

    对于分布式的DApp来说,网络模式是P2P方式。以太坊也是一个分布式的系统,使用了分布式哈希表拓扑结构,具体的实现是类Kademlia算法

    节点与节点之间需要进行数据交互

    KAD算法与节点发现

    以太坊中定义了节点发现协议,节点使用此协议标准来发现彼此

    KAD算法

    distance(A,B) = keccak256(NODEIDA) XOR keccak256(NODEIDB)

    每一个节点都按照距离维护着一张路由表,路由表中维护着256个bucket,每个桶存放着k个Node(k=16,指定距离范围最多能存放16个节点,此举可以增加整个网络的稳定性),每个Node用NODEID作为唯一标识符

    type Node struct {//节点的类似实现
    	NODEID int
    	IP     string
    	Port   string
    }
    

    任意一个节点B与当前节点A的公式

    distance(A,B) = keccak256(NODEIDA) XOR keccak256(NODEIDB)

    当前节点维护的路由表中的距离区间:

    [2 ^ i, 2 ^(i+1))
    

    注意:是左开右闭区间

    [ bucket0   ] : [1]
    
    [ bucket1    ] :[2,3]
    
    [ bucket2    ] : [4,5,6,7]
    
    [ bucket i     ] : [2^i : 2 ^ (i+1))
    
    [ bucket i+1 ] : [...]
    
    [ bucket ...   ] : [...]
    
    [ bucket255 ] : [2^255: 2^256)
    

    节点启动时怎么初始化路由表,以太坊在源码中包含了一些节点,当节点启动时,自动先同步这些节点的信息完成自己的路由表构造

    1.8 Ethash算法

    以太坊区块的打包也是同比特币一样使用的是工作量证明的机制,但是过程有所区别,大致伪代码过程如下

    比特币:hash(nonce + preBlockHash + … )< target

    以太坊:hash (nonce + preBlockHash + DAG… )< target

    解释:以太坊在计算满足条件的哈希值时,使用了nonce 、前一个区块的哈希以及dataset中的数据

    datasset其实是一个DAG,并且DAG数据每3000个区块生成一次,并且只依赖区块号

    DAG生成过程:blockNumber -> seedHash -> 16MB大小的 cache -> 1GB大小的DAG

    具体过程:

    一个seedHash为64字节,16MB =16777216byte / 64byte = 262144 ,也就是说一个cache中有16777216字节(262144段64字节的数据,后一段是前一段的哈希值)

    DAG由cache生成:具体是从头到尾依次遍历cache,并将每一个字节进行fnvHash256然后再次哈希,得到64字节

    并将其填充到DAG中,整个过程需要执行16777216 * 256次,16777216 * 64 = 1GB

    注意:上述DAG是初始状态,DAG每3000区块生成一次,随着时间的推移会变大

    DAG的作用:限制专业机器打包区块对网络的影响。因为每打包一个区块就需要从DAG中循环64次获取64*128字节的数据,而获取的速度取决于显卡的带宽。所以最终打包区块的速度就取决于算力以及带宽

    更多相关内容
  • 本文是本系列的第一篇文章,主要介绍以太坊机制和存在的安全问题的分类。 01 什么是以太坊智能合约? 以太坊智能合约基于区块链(Blockchain)技术,作为一种旨在以信息化方式传播、验证或执行的计算机...

    在本系列中,我们将对以太坊现有的安全问题和前沿的各类型漏洞挖掘方法进行综述。本文是本系列的第一篇文章,主要介绍以太坊的机制和存在的安全问题的分类。

    01 什么是以太坊智能合约?

    以太坊智能合约基于区块链(Blockchain)技术,作为一种旨在以信息化方式传播、验证或执行的计算机协议,为各类分布式应用服务提供了基础。简单来讲:如果把比特币看作是分布式的记账本;以太坊便是可以运行程序的分布式计算平台,程序运行的基础则是Solidity智能合约。

    智能合约早在1995年就由尼克萨博提出,目的在于以数字形式定义一个合同,当参与方执行且满足合同所需的条件时,计算机自动执行该合同内容。但是由于技术条件等限制,这一概念当时并未实现。随着近年来区块链(Blockchain)技术的逐渐成熟以及加密货币的快速发展,由此进入了以智能合约技术为标志的区块链2.0时代。

    智能合约不只是一个可以在区块链上被自动执行的程序,它本身就是一个系统参与者,可以对信息进行接收和回应,也可以存储和收发资产。支持智能合约运行的区块链平台很多,比如EOS,BCOS,Fabric,CITA等,其中规模最大,历史最久也最具影响力的是以太坊(Ethereum)。以太坊通过建立一个图灵完备的,可以允许开发人员编写任意智能合约和去中心化应用(Dapps)的平台而广受欢迎。

    02 为什么需要关注智能合约的安全问题

    随着智能合约应用场景的丰富,如金融、保险、游戏、能源等领域,其中控制的重要金融资产不可避免地成为吸引人攻击的目标。此外,由于智能合约本身编程语言的不安全性以及合约整个生命过程的复杂性,再加上以太坊中每个用户都可以在没有可信赖第三方的情况下参与合约,都为智能合约的安全性带来了巨大的风险和隐患。

    比如2017年6月18日,智能合约The DAO中的可重入漏洞最终造成了亿万美元的损失,影响了整个以太坊网络。2020年1月16日,攻击者通过开源项目为RVN加了功能,并通过一些条件判断来绕过审查,从而拥有发币功能,最终获利千万人民币,使得平台遭遇巨大损失。

    以太坊智能合约安全漏洞事件的频繁爆发,造成了巨大的经济损失,需要我们对其安全性检查方面进行研究。

    03 智能合约有着怎样的架构

    智能合约作为一段脚本,可以使用多种高级语言进行开发,比如Solidity,Serpent,Vyper等,其中针对以太坊的智能合约通常采用Solidity编写,其语法类似于JavaScript。智能合约的编译和解释执行则通过安装在每个以太坊节点上的以太坊虚拟机(Ethereum Virtual Machine, EVM)来完成,根据以太坊白皮书,以太坊系统架构如图1所示。每个以太坊节点架构自底向上分别是操作 系统、区块链节点客户端、以太坊虚拟机和智能合约脚本。

    图片

    图1 以太坊系统架构

    以太坊正是通过运行在不同主机上的以太坊客户端节点之间的通信来完成各种操作。编写好的合约首先通过EVM编译器编译生成一个ABI文件和一个bin文件,其中ABI文件是合约的接口描述,包括了字段名称、字段类型、参数名称、参数返回值等信息,而bin文件是最终运行在虚拟机上的字节码(bytecode),即一段EVM指令集合。

    合约的部署是将编译后的字节码上传到以太坊区块链平台上,其过程与发送一笔交易类似,发起地址为发布者的地址,目标地址为零,交易数据被替换为合约对应的字节码。在进行交易打包时,将根据发布者的地址和交易序列号通过加密算法重新计算出一个地址作为这个合约的地址,调用者可通过合约地址对合约进行调用。以太坊中存在两类账户:外部账户和合约账户,外部账户由私钥控制,有账户余额,可以触发交易但没有代码;而合约账户则包含不可修改的智能合约代码,有账户余额,但不能主动发起交易,只能在被触发后执行预先编写的逻辑。

    因此,合约调用也分为两种类型,一种由外部账户发起称为交易调用,另一种则是由一个合约发起对另一个合约的调用,称为消息调用。此外,智能合约还具有自毁操作,这也是唯一能从区块链上将合约代码移除的方式,它需要在合约编写中执行selfdestruct操作,之后合约账户上剩余的以太币(Ether)会被发送给指定目标,其存储的相关状态和代码也会被移除。而所谓以太币是以太坊中的通用货币,类似于比特币。

    04 与传统程序比,智能合约有哪些特殊机制?

        gas机制

    合约需要矿工的强制执行和证明,因此在打包一项交易时,即将其添加到一个区块上时,为了避免交易中包含大量循环等操作导致节点资源的浪费,合约需先行向矿工支付一笔费用(Gas)。在以太坊执行一份合约本身也需要根据内部制定的规则消耗一定量的gas,如果交易执行后,提前支付的gas还有剩余,则按照原路返还;如果没有执行结束gas就被耗尽,则会触发一个out-of-gas异常,当前合约程序的所有执行状态都会被回滚,但是因为矿工为了执行相应计算已经付出了算力,所以已经消耗的gas不会被退回。

        委托调用机制

    合约可以通过消息调用的机制来调用其他合约,委托调用(delegatecall)就是一种特殊类型的消息调用。它和普通的call指令的区别在于,普通call指令的行为是跳转到被调用合约并在该合约中执行完相应代码再返回执行后续代码,对于调用发起者上下文无影响;而委托调用则相当于把被调用合约中的一段代码拷贝到调用发起者合约的上下文环境中执行,会对调用发起者中的信息作出修改。

        异常传递机制

    智能合约的函数调用方式分为内部调用和外部调用,内部函数调用是指直接调用当前合约或者父合约的内部函数,这些函数调用在EVM中会被直接转换为简单的跳转指令;而外部函数调用是指对于指定地址的外部合约函数的调用,需要靠消息调用完成。其中外部调用中的一些低级调用如call,callcode,delegatecall在执行中如果出错抛出异常,该异常不会沿着函数调用栈被传递,而是只能获取一个布尔值来表示成功或者失败。此外,一些转账函数如call.value, send等,当发生转账异常时,也仅返回一个布尔值而不是回滚这个操作。

    05 智能合约有哪些安全问题?

    智能合约的源码公开透明虽然提升了用户对合约的信任度,但也使每一份公开的合约都有可能成为黑客的攻击目标。智能合约的可信度来源于其不可篡改性,但正因如此也使得智能合约无法像传统程序那样通过打补丁等措施修复漏洞。

    本文接下来将对当前典型的智能合约漏洞类型进行总结。

    根据Atzei等人的一份调查报告,智能合约的安全漏洞可以按照高级语言Solidity、EVM和区块链三个层面进行分类,高级语言Solidity层面的漏洞主要为语言自身设计的缺陷以及开发者在开发过程中引入的错误,EVM层面的安全威胁主要由以太坊智能合约字节码规范和运行机制本身的一些缺陷带来,区块链层面的问题是由区块链本身的很多特性引入。具体如表1中所列。

    表1   漏洞分类

    分类安全漏洞

    高级语言Solidity

    整数类型错误

    未校验返回值

    权限控制问题

    拒绝服务

    资产冻结

    EVM

    重入漏洞

    短地址攻击

    代码注入

    区块链

    交易顺序依赖漏洞

    时间戳依赖漏洞

    可预测的随机处理

            可以采取一些措施规避潜在的重入漏洞:先保证改变状态变量的逻辑发生后再允许以太币从合约中转出去;或将以太币发送至外部合约时,使用内置的transfer函数代替call、send函数实现安全的转币操作。

    06 智能合约安全漏洞介绍

    1)整数类型错误

    整数类型错误主要包含算数错误、截断错误和符号错误。算术错误包括整数溢出、除数为零和模数为零这三种错误。EVM使用几种固定的长度来表示整数,这代表只能表示一定范围内的数字,一旦整数运算结果超出这个范围就会发生整数溢出。攻击者可以利用整数溢出漏洞跳过某些条件判断或者篡改数据,著名的BEC漏洞事件就是由于在转账过程中发生了整数溢出导致了巨额的代币蒸发。使用提供安全检查的SafeMath数学计算库可以有效避免溢出漏洞。在EVM和Solidity旧版本中,除数为零和模数为零只会导致运算结果为0,并不会触发异常。截断错误是指将一个整数类型数据转换为宽度更短的整数类型数据导致精度的丢失。符号错误是指将一个有符号整数类型数据转换为相同宽度的无符号整数类型数据,可能会导致一个负数变为一个很大的整数。

         2)未校验返回值

    以太坊Solidity语言的函数调用和其他高级语言一样一般都会设置返回值,但是对send、call、delegatecall等低级别函数调用失败时不会引起事务回滚操作,而只是在返回值中表示是否发生了异常。攻击者可以通过故意发送失败的操作来导致程序执行与预期设定不同,从而造成智能合约的状态混乱。开发者在开发合约时可以通过对低级别函数调用的返回值校验来确定调用是否成功,从而确保合约能以预先设定的逻辑执行。

    3)权限控制问题

    Solidity中可以使用四种说明符设置函数和状态变量的可见性,分别为external、internal、public和private。未声明可见性的函数会被默认为public,即该函数不仅允许内部调用还会作为合约对外接口被外部合约调用。如果一些涉及到转账等敏感操作的函数没有声明可见性,就可能使攻击者有机可乘。

    4)拒绝服务

    拒绝服务(Denial-of- Service, DoS)一般指不可恢复的恶意操作或者可控制的无限资源消耗。针对以太坊合约的 DoS 攻击会导致以太币和Gas的大量消耗,更严重则会导致永久性地无法使用合约。2016年的以太坊游戏The King of the Ether Throne, 攻击者利用了外部函数调用的漏洞,并通过(Unexpected)Revert 发动DoS攻击,导致该游戏运营出现重大问题。

    5)资产冻结

    由于合约的不可篡改性,如果开发者在进行智能合约开发时,仅设置了接收以太币的功能,但没有设置任何允许以太币转出的操作,或由于某些原因导致以太币无法转出,就会导致合约内的资产被永久冻结。

    6)重入漏洞

    虽然以太坊智能合约的执行是一个具有原子性和顺序性的事务操作,但是当用户在调用智能合约时,如果被调用合约没有找到被调用的函数或者该合约只接收到以太币而没有其他任何消息时就会调用回退函数(fallback)。攻击者可以通过构造特殊的回退函数来攻击存在重入漏洞的智能合约例如回退函数中包含重新调用被攻击合约中之前向攻击者转账函数的代码,从而实现递归调用并耗尽被攻击合约的资产。著名的导致以太坊硬分叉(ETH/ETC)的 The DAO 事件就跟重入漏洞有关。

    7)短地址攻击

    短地址攻击漏洞是一种由于未校验用户输入导致的漏洞,攻击者利用虚拟机的自动补全机制,构造末尾为零的地址进行合约调用,并在传入参数时故意将地址(address)末尾的零省去,虚拟机会取发送代币的金额(amount)高位的0对地址补全,同时会将amout低位补0,这样就等效于amount左移翻倍,导致转移的代币数量超出了原来的设定。通过严格检查用户输入,拒绝接受畸形地址,可以有效避免短地址攻击。

    8)代码注入

    代码注入漏洞由以太坊的委托调用机制引入,委托调用机制中使用的delegatecall指令允许合约在自己的上下文执行其他合约的代码片段。攻击者可以利用该漏洞向合约注入修改合约中重要状态变量等恶意操作的代码。

        9)交易顺序依赖漏洞

    一笔交易被传播出去并被矿工认同写入一个区块内需要一定的时间,攻击者可以通过监视网络上依赖于交易顺序的合约,并通过发出他自己的交易来改变当前的合约状态。例如,攻击者可以提交一个悬赏合约,允许用户通过提交难题的答案从该合约获得丰厚的奖励,攻击者可以在提交完悬赏合约后持续监听网络,若有人提交了答案并且此时提交答案的交易还未被确认,攻击者可以立刻发起一个将奖金降低到无限接近于0的交易并提供较高的gas使自己的交易先被矿工处理,提交答案的交易后被处理,这样攻击者支付很少的奖金就可以获得问题的答案。

        10)时间戳依赖漏洞

    一些智能合约可以通过参数block.timestamp获得当前区块的时间戳并将其作为判断依据,而时间戳一定范围内可以由矿工来决定。因此,一般情况下认为智能合约中依赖于时间戳的代码若可以允许12分钟的误差,那么该种使用时间戳的方式就是安全的。

    11)可预测的随机处理

    合约开发者编写随机数生成函数时,有时会利用时间戳(block.timestamp)、区块号(block.number)等与区块有关的一些参数产生随机数,但是区块链上的上述数据都是公开的,这使得生成的随机数是可预测的,从而可能会被攻击者利用。智能合约的开发人员可以使用例如Oraclize等第三方服务获取随机数来避免该问题。


     

     

    展开全文
  • 18 以太坊的共识机制

    2021-01-08 04:26:18
    以太坊的共识机制 以太坊把出块时间降低到十几秒,但是这样也带来了很多问题,较频繁的出现分叉,这对于共识协议来说有什么影响呢? 在比特币中,只有最长合法链的中才是合法链, GHOST协议:假如一条区块链没有成为...
  • 工作量证明(PoW)被大家诟病的是能耗太大,比特币一笔交易需要1000度电左右,以太坊因出块时间短,一笔交易大概是67度电左右。 工作量证明中矿工通过购买矿机、GPU等来挖矿,从而获得出块奖励,获得的奖励由算力...
  • 本书用来描述以太坊网络发现的实现原理。很适合相关从事和学习以太坊技术的同学。
  • 以太坊概述

    2021-01-07 21:07:38
    以太坊在系统设计上,针对比特币运行过程中出现的一些问题进行了改进,比如说出块时间调整至15s,这是基于ghost协议的共识机制;另外一个改进是挖矿使用的mining puzzle,比特币的mining puzzle是计算密集型的,比拼...
  • 以太坊完整工作原理和运行机制

    万次阅读 多人点赞 2018-04-30 22:59:45
    以太坊完整工作原理和运行机制!2018年04月28日 00:00:00阅读数:26作者 | Preethi Kasireddy编译 | 老曹、Aholiab链圈的人提起「以太坊」三个字想必是如雷贯耳。无论是以太币,还是其天才创始人Vitalik Buterin,...
    以太坊完整工作原理和运行机制!

    640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1


    作者 | Preethi Kasireddy

    编译 | 老曹、Aholiab



    链圈的人提起「以太坊」三个字想必是如雷贯耳。无论是以太币,还是其天才创始人Vitalik Buterin,还是关于它的各种新闻,想必闭着眼都能看看而谈。


    即使如此,你可能还是不知道以太坊到底是个什么东西?它包含了哪些部分?又是基于哪些原理运作的?这些你真的都知道吗?


    本文对以太坊的原理进行一次大起底,尽量深入浅出且全面的让你理解以太坊的本质到底是什么。让你对以太坊有一个整体而深刻的认识。



    本质上来说,以太坊就是一个保存了数字交易永久记录的公共数据库。重要的是,这个数据库不需要任何中间方来维护和双方的权益。相反,它可以作为一种「无需信任」交易系统来运作,也就是你可以在不需要第三方的情况下进行点对点交易。


    说来说去,还是这些啊?别急,今天就从技术层面来更深入的看看以太坊的机制到底是什么。在解释这一概念时,我们尽量不去用复杂或看着吓人的数学公式,即使不是程序员,也能在阅读后对以太坊的运营原理有更清晰的认识。在阅读的时候,你没必要去理解文中的每一个细节,可以聚焦在宽泛的层面上来理解以太坊。



    区块链的定义


    区块链是具有「共享状态的加密安全交易单机」。听起来有点拗口,我们来分析一下。

    • 加密安全」是指,数字货币的创造是通过复杂的数学算法来保证的,而这些算法很难破解,类似于系统的防火墙,你无法在区块链中创建虚假的交易或删除交易等。

    • 交易单机」是指,有一个机器的单个实例,就可以负责系统中产生的所有交易。 换句话说,每个人都相信「一个单一的全局真相」。

    • 共享状态」意思是,在这一系统中所存储的状态对每个人都是透明和开放的。


    知道了区块链的定义,我们就来看看以太坊区块链到底是什么?



    以太坊区块链算法


    以太坊区块链本质上是一个为交易服务的状态机。在计算机科学中,一个状态机指的是这样一种东西,它可以读取一系列的输入,并基于这些输入产生一个新的状态。

    640?wx_fmt=png


    以太坊状态机的运行从一个「元状态」开始,这类似于在网络上没有发生任何交易之前的一块空白石板。当交易执行时,这个元状态就转变为一些最终状态。在任何时候,这个最终状态都代表着以太坊区块链的现状。


    640?wx_fmt=png

    以太坊系统中运行着数百万笔交易,这些交易被分组归类为「区块」。一个区块包含一系列交易,每个块与其前面的区块串联在一起。

    640?wx_fmt=png

    要从一个状态转到另一个状态,必须证明交易是有效的。如果一个交易被认为是有效的,就必须通过一个验证过程,这一过程称为「挖矿」。挖矿是指一组节点(即计算机)消耗它们的计算资源来创建一个有效交易的区块。


    网络中任何声明自己是「矿工」的节点都可以尝试创建和验证区块,全世界有许多矿工试图同时创建和验证区块。每个矿工在向区块链提交一个区块时同时,都要提供一个数学的「证明」,且把这个证明作为一个保证:如果这个数学证明存在,则该区块必然是有效的。


    如果要在主区块链上添加一个区块,矿工必须比其他竞争对手更快地对其证明。通过让矿工提供数学证明来验证每个区块的过程被称为「工作量证明」。


    一个矿工如果验证了一个新的区块,这个验证工作就会得到一定数额的价值回报。这个价值是多少呢?以太坊区块链使用了一种内部数字令牌,叫做「以太币」。 每当一个矿工证明了一个区块,就会生成并得到一个新的以太币。


    你可能会想:什么每个节点都在一条链上?矿工如果想创造新的的区块链怎么办?


    正如我们在上文给区块链的定义,区块链是一个具有共享状态的交易单机。这个定义决定了,区块链的当前状态是一个单一的全局状态,每个人都必须接受。如果拥有多个状态(或链条)会破坏整个系统,因为人们不可能就哪个状态是正确的状态达成一致意见。如果这些链条是分开的,就会出现一个人在一条链上有10个以太币,在另一条链上有20个的情况。在这种情况下,我们没有办法确定哪一个链条最「有效」,无法确定哪个人有多少硬币。


    多条链的产生,被称为「分叉」。因为分叉会破坏系统,因此我们通常会避免分叉,迫使人们选择他们「相信」的链条。

    640?wx_fmt=png

    为了确定哪个路径是最有效的,并防止分叉的发生,以太坊使用了一种叫做「GHOST协议」的机制。


    GHOST = Greedy Heaviest Observed Subtree


    简单地说,GHOST协议让我们必须选择在链上做最多计算的路径。确定该路径的一种方法是使用最新区块的数量,来表示当前路径中的区块总数(不计算起源块)。块数越多,路径越长,挖矿的难度越大,最终就一定会到达最新区块。使用这个方式让我们对当前区块链状态的唯一版本达成一致。

     

    640?wx_fmt=png



    到这里,我们就对以太坊区块链就有了一个宏观的认识,接下来我们就更深入地看看以太坊系统的主要组成部分:


    • 帐户;

    • 状态;

    • Gas与费用;

    • 交易;

    • 区块;

    • 交易执行;

    • 挖矿;

    • 工作量证明。



    以太坊的帐户


    以太坊的全球「共享状态」是由许多账户组成的,它们能够通过一个消息传递框架相互通信。每个帐户都有一个与它关联的状态和一个20字节的地址。以太坊的地址是一个160位比特的标识符,用于识别帐户。


    以太坊有两种账户类型:

    • 外部帐户由私人密钥控制,没有与之相关的代码。

    • 合约账户由其合约代码控制,并具有与其相关的代码。

     


    外部账户与合约账户


    外部账户可以通过创建和使用其私人密钥签署一项交易,向其他外部账户或其他合约账户发送消息。两个外部账户之间的消息只是一种价值转移。但从一个外部帐户到一个合约账户的消息会激活合约账户的代码,使它能够执行各种操作(例如转移代币、写入内存、生成新的代币、执行一些计算、创建新合约等)。


    与外部账户不同,合约账户不能自行启动新的交易。相反,合约账户只能根据它们收到的其他交易(从外部账户或从另一个合约账户)进行交易,这点我们会在下文进行探讨。

     

    640?wx_fmt=png

    因此我们可以得出结论:在以太坊区块链上发生的任何操作都是由外部控制账户的交易引起的。

     

    640?wx_fmt=png



    帐户状态


    无论帐户是哪种类型,帐户状态都由以下四个部分组成。


    • nonce:如果帐户是一个外部帐户,这个数字代表从帐户地址发送的交易数量。如果帐户是一个合约帐户,nonce是帐户创建的合约数量。

    • balance:这个地址拥有的Wei(以太坊货币单位)数量,每个以太币有1e+18 Wei。

    • storageRoot :一个Merkle Patricia树根节点的哈希,它对帐户的存储内容的哈希值进行编码,并默认为空。

    • codeHash:EVM(以太坊虚拟机)的哈希值代码。 对于合约帐户,这是一个被哈希后并存储为codeHash的代码。对于外部帐户,codeHash字段是空字符串的哈希。

    640?wx_fmt=png



    全局状态


    我们知道以太坊的全局状态包括帐户地址和帐户状态之间的映射,这个映射存储在一个数据结构中,这种结构被称为Merkle Patricia树。


    Merkle Patricia树是一种由一组树状节点构成的二进制结构,它包括:


    • 底层有大量的叶子节点,其中包含了潜在的数据;

    • 一组中间节点,其中每个节点是其两个子节点的哈希;

    • 一个单个的根节点,也是由它的两个子节点的哈希形成的,代表树的顶部。

     

    640?wx_fmt=png


    树的底部数据是通过把我们想要存储的数据分割成块后而生成的,然后将这些数据块分成几个桶,然后对每个桶的进行哈希迭代,值到剩下的哈希总数变为一个根哈希。  


    640?wx_fmt=png



    此外,树需要存储在里面的每一个值的密钥。从树的根节点开始,密钥告诉你要遵循哪个子节点来获取相应的值,这些值存储在叶子节点中。在以太坊中,状态树的键值对是地址和相关帐户之间的映射,包括每个帐户的balance、nonce、codeHash和storageRoot(storageRoot本身就是一棵树)。

     

    640?wx_fmt=png

    同样的树结构也用于存储交易和收据。更具体地说,每个块都有一个「header」,它存储三个不同Merkle树结构根节点的哈希,包括:

    1. 状态树;

    2. 交易树;

    3. 收据树。

     

    640?wx_fmt=png

    Merkle树能够高效存储信息的特性在以太坊系统中十分被看重,我们可以称之为「轻节点」或「轻客户端」,其实区块链的节点有两种:完整节点和轻节点


    一个完整的节点需要下载完整的链,从元区块到当前的头部块,执行所有的交易也都包含其中。通常情况下,矿工储存完整的档案节点,因为他们必须这样做才能完成挖矿的过程。当然,也可以在不执行交易的情况下下载完整的节点。无论如何,任何完整的节点都包含整条链。


    轻节点的概念与之相对,除非一个节点需要执行每个交易或查询历史数据,否则就没有必要存储整个链。这就是轻节点的意义所在。轻节点并不下载和存储完整链并执行所有的交易,而是只下载从元区块到当前头部区块的信息,而不执行任何交易或检索任何关联状态。因为轻节点可以访问包含三个树的区块头部哈希,所以仍然可以很容易地生成和接收关于交易、事件、余额等可验证的结果。


    这样做的原因是因为Merkle树中的哈希会向上传播ーー如果一个恶意用户试图将一个伪造的交易交换到Merkle树的底部,这种变化将导致上面节点的哈希变化,也将改变上面节点的哈希值。

     

    640?wx_fmt=png

    任何想要验证一段数据的节点都可以使用所谓的「Merkle证明」来执行。一个Merkle 证明包括:


    1. 需要验证的大量数据及其哈希值;

    2. 树的根哈希;

    3. 「分支」(所有的参与者的哈希沿着路径上升,一直到「树根」)。

     

    640?wx_fmt=png

    任何读取该证明的人都可以验证树上所有的分枝是否一致,因此给定的数据块实际上位于树中的某个位置。


    总之,使用Merkle树的好处是,该结构的根节点依据树中存储的数据进行加密,因此根节点的哈希可以作为该数据的安全证明。由于区块头包括状态、交易和收据树的根哈希。因此任何节点都可以在不需要存储整个状态的情况下,验证以太坊的一小部分状态,而整个状态的大小可能是无限的。



    Gas和支付


    在以太坊中,费用的计算是一个非常重要的概念。在以太坊网络上进行的每一笔交易都会产生费用ーー没有免费的午餐!这笔费用被称为「Gas」。


    Gas Price是指:你愿意花在每一个单位Gas上的以太币数量,是用「gwei」来计算的。Wei是以太币中最小的单位,其中1018 Wei代表1个以太币。一个gwei是1,000,000,000 Wei。


    每次交易,发送方都要设置一个Gas Limit和Gas Price。Gas Limit和Gas Price代表发送方愿意为执行交易支付的最大金额。


    例如,发送方将Gas Limit设置为50,000,一个Gas Price设置为20 gwei。这意味着发送者愿意花费最多50,000 x 20 gwei,也就是:1,000,000,000,000,000 Wei(0.001以太币)来执行这一交易。

     

    640?wx_fmt=png

    这里需要留意的是,Gas限额是发送方愿意花钱的最大限度。如果他们的账户余额中以太币的数量大于这个最大值,那么他就可以进行交易。在交易结束时,发送方将被退还的那些未使用的Gas,按原来的价格进行兑换。

     

    640?wx_fmt=png

    如果发送方没有提供执行交易所必需的Gas,则该交易运行的结果会是「余额不足」,并被认为无效。在这种情况下,交易处理中止,其间的产生的任何状态都会发生逆转,这样就可以在交易发生之前返回到以太坊区块链。此外,交易失败的记录会被记录下来,显示尝试过哪些交易,失败了哪些交易。由于系统已经在Gas用光之前做完了运算工作,所以从逻辑上看,Gas不会被退还给发送方。

    640?wx_fmt=png


    那么,这些Gas的钱到底去哪了呢?发送方花在Gas上的所有钱都寄给了「受益人」地址,也就是矿工地址。由于矿工们正在努力运行计算和验证交易,所以收到了Gas作为奖励。

     

    640?wx_fmt=png

    通常情况下,发送方愿意支付的Gas价格越高,矿工从交易中获得的价值就越大,矿工们也就越有可能选择这个交易。通过这种方式,矿工可以自由地选择交易。为了给发送者设置Gas Price做参考,矿工们可以直接提出他们执行交易所需的最低Gas Price。



    存储费用


    Gas不仅用于支付计算的费用,还用于支付存储的使用费用。存储的总费用与使用的32字节的最小倍数成正比。


    存储费用与交易费用有一些不同。由于增加的存储量增加了所有节点上的以太坊状态数据库的大小,所以存储数据的数量会变小。由于这个原因,如果一个交易有一个步骤可以清除存储中的条目,则可以免除执行该操作的存储费用,并且还能因此得到退款。



    费用的目的是什么?


    以太坊工作方式的一个重要方面是,网络执行的每一个操作都同时受到每个完整节点的影响。然而,在以太坊虚拟机上的计算步骤非常昂贵。因此,以太坊智能合约更适合简单的任务,比如运行简单的业务逻辑或验证签名和加密其他对象,而不适合更复杂的用途,比如文件存储、电子邮件或机器学习,这些都会给网络带来压力。收费的目的就是使整个网络不会因用户的不当使用而变得负担过重。


    除此之外,以太坊是一种图灵完整语言(图灵机是一种能够模拟任何计算机算法的机器)。这就允许了循环,使得以太坊区块链容易受到暂停问题的影响,因为在这个问题中,无法确定一个程序是否会无限运行。如果没有费用,意图不良的人可以通过在交易中执行一个无限循环来扰乱网络,从而产生不良的影响。因此,费用保护了网络免受蓄意攻击。


    那么,为什么我们还要支付存储费用呢?就像计算一样,在以太坊网络上的存储也是整个网络必须承担的一个成本。



    交易与消息


    我们在上面说到,以太坊是一个基于交易的状态机。换句话说,不同账户之间发生的交易正是以太坊从一个状态转移到另一个状态的原因。


    因此,交易可以看做是一个由外部拥有的帐户生成的序列化加密签名指令,然后提交给区块链。


    交易分为两类:「消息调用」和「合约创建」(创建新的以太坊合约的交易)。不管哪一类,所有交易都包含以下组件:


    • Nonce:发送方发送的交易数量的计数;

    • gasPrice:发送方愿意支付每单位Gas所需执行交易的Wei数量;

    • gasLimit:发送方愿意支付的执行这一交易的Gas最大数量。这个数额是预先设定和支付的;

    • to:接收方的地址,在创建合约的交易中,合约帐户地址还不存在,因此使用了空值;

    • Value:从发送方转移到收件方的金额,在创建合约的交易中,这个Value作为新创建合约账户内的起始余额;

    • v, r, s:用于生成识别交易发送方的签名;

    • Init(只存在于创建合同的交易中):用于初始化新合约帐户的EVM代码片段,它只运行一次,然后被丢弃,当init第一次运行时,它会返回帐户代码的主体,这个代码是与合约帐户永久关联的一段代码;

    • data(只存在于消息调用中的可选字段):消息调用的输入数据(即参数)。例如,如果一个智能合约充当域名注册服务,那么对该合约的调用可能会有诸如域名以及IP地址等输入字段。

     

    640?wx_fmt=png


    在说「账户」的时候,我们看到,交易(包括消息调用和合约创建的交易),总是由外部账户启动并提交给区块链的。另一种思考方式是,交易是连接外部世界与以太坊内部状态的桥梁。

     

    640?wx_fmt=png

    但这并不意味着一个合约不能与其他合约对话。在全局范围内存在的合约,可以与同一范围内的其他合约进行交流。它们是以通过「消息」或「内部交易」的方式来实现的。我们可以认为消息或内部交易类似于交易,其主要区别在于它们不是由外部账户所产生的,相反,是由合约产生的,是虚拟对象。与交易不同,合约不是序列化的,而是只存在于以太坊的执行环境中。


    当一个合约将一个内部交易发送到另一个合约时,存在于接收方合约账户上的关联代码就会被执行。

     

    640?wx_fmt=png

    需要注意的一点是,内部交易或消息不包含Gas Limit。这是因为Gas Limit是由原始交易的外部创建者(即部分外部帐户)来决定的。外部账户集合的Gas Limit必须足够高,以便进行交易,这包括由这一交易而导致发生的任何次级处理运行,例如合约对合约的消息。如果在交易和消息链中,特定的消息执行耗尽了Gas,那么该消息的执行将与执行引发的所有后续消息一起恢复。不过,上一级的执行不需要恢复。



    以太坊的区块


    所有的交易都被组合成「区块」,区块链则包含一系列这样被链接在一起的区块。在以太坊中,一个区块包括「区块头」、关于包含在此区块中交易集的信息,与当前块的ommers相关的一系列其他区块头Ommer解释



    Ommer是什么?


    比起比特币之类的区块链,以太坊的构建方式使区块生成时间要低很多。这样可以更快地处理交易。然而,缩短区块生成时间的一个缺点是,矿工们要找到更多相互竞争的区块解决方案。这些相互竞争的区块也被称为「孤儿区块」,不能进入主链。


    Ommer的目的是帮助奖励矿工,也包括这些孤儿区块。矿工的ommer必须是「有效的」,也就是说在目前区块的第六代或更小的范围内。六代之后,陈旧的孤儿区块就不能再被引用。比起完整的区块,Ommer块获得的奖励要小一些。尽管如此,矿工们仍然有一定的动力去挖掘这些孤儿区块并获得回报。



    区块头


    回到区块本身,之前提到每个区块都有一个区块头,但到底什么什么是区块头?区块头是区块的一部分,包括:


    • Parenthash:一个父区块头的哈希(这就是为什么区块链被称为区块「链」);

    • Ommershash:当前区块ommer列表的哈希;

    • beneficiary:收取采矿费用的帐户地址;

    • Stateroot:状态树的根节点哈希;

    • transactionsRoot:包含在此区块中列出的所有交易树根节点的哈希值;

    • receiptsRoot :包含本区块中列出的所有交易树根节点的哈希的收据;

    • logsBloom:一个由log组成的Bloom过滤器(数据结构);

    • difficulty:这个区块的难度水平;

    • 编号:当前区块的记数(元区块的编号为0;每个后续区块的块数增加1);

    • gasLimit:当前每个区块的Gas限制;

    • gasUsed:本区块交易所使用的总Gas之和;

    • 时间戳:这个区块注入的unix时间戳;

    • extraData:与此区块相关的其他数据;

    • mixHash:当与nonce结合时,证明这个区块执行了足够计算的哈希值;

    • Nonce:当与mixHash结合时,证明这个区块已经执行了足够计算的哈希值;

    640?wx_fmt=png


    每个区块头包含三个树结构:


    • 状态根(stateRoot);

    • 交易根(transactionsRoot);

    • 收据根(receiptsRoot)。


    这些树结构只不过是之前讨论过的Merkle树而已,没有什么特别的。不过,从上面的描述中可以看到,有一些术语还需要进一步说说。



    日志(Log)


    以太坊允许log跟踪各种交易和消息。合约也可以通过定义需要记录的「事件」来显式生成log。


    一条log包含:


    • 记录器的帐户地址;

    • 一系列主题,它们表示此交易所进行的各种事件,以及,

    • 任何与这些事件有关的数据。


    log存储在一个bloom过滤器中,它以有效的方式存储海量的日志数据。



    交易收据


    区块头中存储的日志来自于交易收据中包含的日志信息。就像在商店买东西时收到收据一样,以太坊会为每笔交易生成一张收据。不出所料,每张收据都包含有关交易的某些信息。 这样的收据包括以下内容:


    • 区块编号;

    • 区块哈希;

    • 交易哈希;

    • 当前交易所使用的Gas;

    • 在当前交易执行后,当前区块中使用的Gas;

    • 执行当前交易时创建的日志。



    区块的难度


    区块的「难度」用于在验证区块的时间内来加强一致性。元区块的难度为131,072,并用一个特殊的公式来计算后面每个区块的难度。如果某个区块比前一个区块更快地被验证,那么以太坊协议会增加该区块的难度。


    该区块的难度会影响nonce,这是一个哈希,必须在挖矿时使用工作量证明算法来计算。


    区块的难度与nonce之间的关系在数学上表示为:


    640?wx_fmt=png


    这里Hd代表了难度。找到满足难度阈值的nonce的唯一方法是使用工作量证明算法来枚举所有的可能性。 寻找解决方案的预期时间与难度成正比,难度越大,找到nonce就越困难,因此验证区块的难度就越大,这反过来增加了验证新区块的时间。通过调整区块的难度,协议可以调整验证区块的时长。


    另一方面,如果验证时间变慢,那么协议就会减少难度。通过这种方式,验证时间可以自我调整从而保持一个常量ーー平均每15秒一个区块。



    交易的执行


    看到这,你已经来到了以太坊协议中最复杂的部分之一。假设将一个交易发送到以太坊网络进行处理,如果以太坊状态要将你的交易包括在内,会发生什么?

    640?wx_fmt=png

    首先,所有交易都必须满足初始的一组需求才能执行。 其中包括以下几个部分。


    • 交易必须是正确的RLP格式(RLP是「递归长度前缀」的缩写,是用于二进制数据编码嵌套数组的数据格式,RLP是以太坊使用的序列化对象的格式)。

    • 有效的交易签名。

    • 有效的交易nonce,回想一下,一个帐户的nonce是从该帐户发送的交易的统计,为了有效,交易nonce必须与发送方帐户的nonce相等。

    • 交易的Gas限额必须等于或大于交易所使用的内部Gas, 内部Gas包括:1)为执行交易预先确定的费用为21,000 Gas;2)与该交易一起发送的数据Gas费用(对于每一个等于零的数据或代码的每个字节收取4个Gas,每个非零字节的数据或代码为68个Gas);3)如果这笔交易是一笔合约创建交易,则额外收取32,000 Gas。

     

    640?wx_fmt=png

    • 发送方的账户余额必须有足够的以太币来支付前期的Gas费用。前期Gas成本的计算很简单:首先,交易的Gas Limit乘以交易的Gas Price,以确定最大的Gas成本。 然后,这个最大的成本被算在从发送方转移到接收方的总额中。

    640?wx_fmt=png

    如果交易符合上述有效性的所有要求,那么,就可以进入下一个步骤。


    首先,从发送方的余额中扣除执行的前期成本,并将发送方帐户的nonce加1。我们可以计算剩余的Gas,因为交易的Gas Limit要减去所使用的内在Gas。


    640?wx_fmt=png

    然后,交易开始执行。在交易的整个执行过程中,以太坊都跟踪「子状态」。子状态记录交易中产生的信息,这些信息也是交易完成后所马上需要用到的。具体来说,它包含:


    • 自毁集合:交易完成后将丢弃的一组帐户(如果有的话);

    • 日志序列:虚拟机代码执行的存档和可索引的检查点;

    • 退款余额:交易完成后退还给发送者账户的余额。


    一旦处理完交易中的所有步骤,并假定没有无效状态,则通过确定向发送方退还未使用的Gas数量,来最终判定最终状态。除了未使用的Gas外,发送方还从上文所述的「退款余额」中退还了一些余额。


    一旦发送者获得退款:


    • Gas(以太币)就会给到给矿工;

    • 该交易所使用的Gas被添加到区块的Gas计数器(该计数器记录该区块中所有交易使用的总Gas);

    • 删除自毁集合中的所有帐户(如果有的话);


    最后,只剩下了新的状态和已创建交易的一组log。至此,我们就讲完了交易执行的基本原理,下面再来看看合约创建的交易和消息调用之间的一些差异。



    合约创建


    前面说过,以太坊的账户分为两类:合约帐户和外部账户。当交易是「契约创建」(Contract Creating)时,意思是,交易的目的是创建一个新的合约账户


    为了创建一个新的合约帐户,我们首先使用一个特殊的公式来声明新账户的地址,然后通过以下方式初始化新帐户:


    • 将nonce设置为零;

    • 如果发送方在交易中发送了一定数量的以太币作为价值,则将帐户余额设置为该价值;

    • 从发送方的余额中扣除这个新账户余额的增加部分;

    • 将存储设置为空;

    • 将合约的codeHash设置为空字符串的哈希值;


    一旦帐户完成了初始化就可以创建帐户了,使用与交易一起发送的init代码。在执行这个init代码的过程中,可能发生很多情况。根据合约的构造函数,它可能更新帐户的存储,创建其他的合约账户,或其他的消息调用,等等。


    一旦初始化合约的代码被执行就将开始消耗Gas,交易使用的Gas不能超出账户的余额,一旦超出,将会出现「Gas耗光」的异常并且退出。如果交易由于Gas耗光的异常而退出。


    但是,如果发送方在交易中发送了一些以太币,这时合约创建失败也会退还以太币吗?答案是,不会。


    如果初始化代码执行成功,则支付最终的合约创建成本。这是一个存储成本,并且与创建合约代码的大小成正比。如果剩余的Gas不足以支付这笔最终成本,那么这笔交易将再次声明为一个「Gas耗光」异常。


    如果一切顺利,而且没有遇到任何异常,那么剩余的Gas都会退还给交易的原始发送方,并允许改变状态继续存在!



    消息调用


    消息调用的执行类似于合约创建,但有一些不同之处。


    消息调用的执行不包含任何init代码,因为没有创建新的帐户。但是,如果这些数据是由交易发送方提供的,它可以包含输入数据。一旦执行,消息调用也有一个额外的组件,其中包含输出数据,如果后续执行需要此数据,则使用这些数据。


    如同合约创建一样,如果由于Gas耗尽或交易无效(例如堆栈溢出、无效的跳转目的地或无效指令),则所使用的任何Gas都不会退还给原来的调用者,取而代之的是,所有剩余的Gas都会被消耗掉,并且状态被重置到余额转移之前的情况。



    执行模式


    现在,我们来看看在VM中,交易实际上是如何执行的。


    实际处理交易的部分是以太坊自己的虚拟机,被称为EVM。就像之前定义的那样,EVM是一个「图灵完备」的虚拟机。唯一的不同是EVM有内在Gas的约束。因此,可以完成的计算总量本质上受到所提供Gas数量的限制。

     

    640?wx_fmt=png

    此外,EVM 有一个基于栈机器的架构。栈机器是一种使用「后入先出」的堆栈来保存临时值的计算机。EVM中每个栈条目的大小为256位,最大为1024位。


    EVM具有内存,其中存储的条目是字地址字节数组(word-addressed byte arrays)。 内存是易失性的,这意味着它不是永久性的。


    EVM还有存储空间。与内存不同,内存的存储是非易失性的,并作为系统状态的一部分来维护。EVM在一个虚拟ROM中独立存储程序代码,只能通过特殊的指令访问虚拟ROM。这就是EVM与典型的冯·诺伊曼结构的不同,冯·诺伊曼结构中程序代码是在内存或存储中。

     

    640?wx_fmt=png

    EVM也有自己的语言——EVM字节码。当程序员在以太坊上写智能合约的时候,通常用高级语言写代码,比如Solidity。然后,可以编译成EVM字节码,以便EVM可以理解执行。


    接下来我们来看看EVM如何运行。在执行特定的计算之前,处理器要确保以下信息是可用且有效的:


    • 系统状态;

    • 用于计算的剩余Gas;

    • 拥有执行代码的帐户地址;

    • 产生此执行交易的发送方地址;

    • 引发代码执行的帐户地址(可能与原始发送方不同);

    • 产生此次执行交易的Gas Price;

    • 此执行的输入数据;

    • 作为当前执行的一部分,价值(以Wei为单位)传递到这个帐户;

    • 要执行的机器码;

    • 当前块的区块头;

    • 当前消息调用或合约创建的栈深度;

    • 在执行开始时,内存和栈是空的,程序计数器归零。


    640?wx_fmt=png


    然后,EVM递归执行交易,计算系统状态和每个循环的机器状态。简单地说,这个系统状态就是全局状态。机器状态包括:


    • 可用的Gas;

    • 程序计数器;

    • 内存的内容;

    • 内存中的字活跃数;

    • 栈内容。


    栈中条目是从该系列最左边的部分中添加或删除。表现为,在每个循环中,从剩余的Gas中减少适当的Gas,并且程序计数器递增。


    在每个循环的结束时,有三种可能性:


    1. 机器达到一个特殊状态(例如Gas不足、指令无效、栈条目不足、栈条目溢出超过1024、无效的JUMP/JUMPI等),因此必须停止,任何更改都将被丢弃;

    2. 这个序列继续进入下一个循环;

    3. 系统被迫停止。


    假设执行没有达到一个特殊状态,并达到一个「可控制的状态」或正常停止,那么机器就会生成结果状态、保留执行后剩余的Gas。


    说了这么多,终于结束了以太坊中最复杂的部分。即使没有完全理解这部分,也没关系,除非是从事底层的开发工作,否则并不需要真正理解这些细节。



    一个区块的最终完成


    最后,来看看多个交易块是如何最终完成的。


    这里所说的「最终」可能是指两种不同的东西,这取决于区块是新的还是已经存在的。如果是一个新区块,「最终」指的是挖掘这个区块所需要的过程。如果是一个现有的区块,那么「最终」指的是验证块的过程。在这两种情况下,对于要到「最终」状态的区块有以下四个要求。


    1. 验证(如果是挖矿,就是判定)ommer:每个区块头中的每个ommer区块都必须是一个有效的区块头,并且在当前区块的六代以内。

    2. 验证(如果是挖矿,就是判定)交易:区块上的gasUsed数字必须等于该区块中所列交易所使用Gas的累积。

    3. 申请奖励(只限于挖矿的情况):受益人地址被授予5以太币,用于开采该区块。 (根据以太坊EIP-649,这5个ETH的报酬将很快减少到3个)。此外,对于每一个 ommer,当前区块的受益者将额外获得当前区块奖励的1/32。最后,ommer区块的受益人也可以得到一定数额的赔偿。

    4. 验证(如果挖矿,计算一个有效的)状态和nonce:确保应用所有交易和由此产生的状态更改,在区块奖励应用于最终交易的结果状态之后,定义新区块的状态。通过检查这个最终状态来验证存储在区块头中的状态。



    挖矿的工作量证明


    将区块难度赋予意义的算法叫做「工作量证明」(PoW)。以太坊的工作量证明算法被称为「Ethash」(之前被称为Dagger-Hashimoto)。


    该算法的公式如下:


    640?wx_fmt=png


    这里m是mixHash、n是nonce、Hn是新区块的头(不包括nonce和mixHash组件)、Hn是块头的nonce、d是DAG(一个大数据集)。


    还记得上面谈到的在区块头中存在的mixHash和nonce两个字段吗?


    • mixHash是一个哈希,当与nonce结合时,可证明这个区块执行了足够的计算;

    • nonce是一个哈希,当与mixHash结合时,可证明这个区块已经执行了足够的计算


    PoW的功能就是评估这两个字段。至于如何使用的PoW函数来精确计算mixHash和nonce说起来有点复杂,但从总体上看,它的工作原理是这样的。


    每个区块都算出一个「seed」,每个「epoch」对应的seed都不相同,一个epoch相当于3万个区块的长度。在第一个epoch,seed是一系列32字节零的哈希。对于后来的每一个epoch来说,它都是以前seed哈希的哈希。使用seed,一个节点可以计算一个伪随机的「缓存」。


    这个缓存非常有用,因为它使之前讨论过的「轻节点」成为可能。轻节点的目的是为了使某些节点能够有效地验证交易,而没有存储整个块环链数据集的负担。一个轻节点可以完全基于这个缓存来验证交易的有效性,因为缓存可以重新生成需要验证的特定区块。


    使用缓存,节点可以生成DAG数据集,数据集中的每个项都依赖于缓存中的少量伪随机选择(pseudo-randomly-selected)的项。为了成为一名矿工,必须生成这个完整的数据集;所有客户和矿工都存储这个数据集,并且数据集随时间线性增长。


    然后,矿工们可以随机抽取数据集的片段,然后通过数学函数将它们混合成一个mixHash。矿工将反复生成mixHash,直到输出低于预期目标的nonce。当输出满足这个要求时,这个nonce被认为是有效的,并且块可以添加到链上。



    挖矿作为一种安全机制


    总体而言,PoW的目的是以一种安全加密方式证明工作量,基于特定的计算量生成某些输出(即nonce)。这是因为除了穷举所有可能性之外,没有更好的办法来找到低于要求阈值的nonce。重复应用哈希函数的输出具有均匀分布,因此我们可以确信,找到这样一个nonce所需的平均时间取决于难度阈值。难度越大,解决问题的时间就越长。这样,PoW算法对难度概念赋予了真实的意义,这个概念被用来增强区块链的安全。


    那么,区块链安全又是指什么?很简单:就是要创建一个每个人都信任的区块链。正如先前在本文中讨论的那样,如果存在一个以上的链,用户将对其失去信任,因为他们无法合理地确定哪一个链是「有效的」链。为了让一组用户接受存储在块环链上的基本状态,需要一个大家都相信的且单一规范的区块链。


    而这正是PoW的作用:它确保一个特定的区块链可以保持规范,使攻击者难以创建新的区块,或者覆盖历史的某一部分(例如擦除交易或创建虚假的交易),或者对一个分叉进行维护。为了验证他们的区块,攻击者需要比网络中的其他任何人都更快地解决nonce问题,这样网络就会相信他们的链条是最重链(基于之前提到的GHOST协议的原则)。这是基本上不可能的,除非攻击者拥有超过一半的网络挖掘能力,因此这种情况被称为「51%攻击」。


    640?wx_fmt=png



    挖矿作为一种财富分配机制


    除了确保一个安全的区块链环境,对那些为了提供这种安全而消耗算力的人,Pow还是一种分配财富的方式。回想一下,矿工在开采一个区块时会得到奖励,其中包括:


    • 「获胜」区块获得的5以太币(不久将改为3以太币)的奖赏;

    • 该区块所包括的交易在区块内消耗的Gas成本;

    • 将ommer作为区块的一部分的额外奖励。


    从长远来看,为了确保PoW机制在安全和财富分配方面的使用是可持续的,以太坊努力培养它的两个特性:


    • 让尽可能多的人能够接触到它,换句话说,人们不应该需要专门的硬件来运行算法,这样做的目的是使财富分配模型尽可能开放,以便任何人都可以根据自身的情况提供计算能力,以换取以太币。

    • 减少单个节点(或小集)产生不成比例利润的可能性,任何节点,如果能够获得不成比例的利润,就意味着节点对规范区块链的确定有很大的影响,这会降低网络的安全性。


    在比特币区块链网络中,与上述两个属性有关的一个问题是,PoW算法是一个 SHA256哈希函数。这类函数的弱点在于,它可以通过使用专门的硬件更有效地解决问题,也就是所谓的ASIC。


    为了解决这一问题,以太坊选择了将PoW算法按顺序存储到内存硬件中。这意味着这个算法是经过设计的,所以计算nonce需要大量的内存和带宽。大量的内存需求使得计算机很难同时使用它的内存来同时发现多个nonce,而且高带宽的要求使得即使是超级计算机也很难同时发现多个nonce。这减少了集中化的风险,也为正在进行验证的节点创建了一个更公平的机制。


    需要注意的是,以太坊正在从PoW机制过渡到PoS机制,这又是另一个话题了,希望可以在今后的文章中探讨。



    结束语


    终于到底了,这篇文章是不是有很多东西需要消化?


    如果真的对以太坊感兴趣,建议可以多读几次。我也是亲自阅读了以太坊的白皮书和代码,然后才搞清楚以太坊要做的究竟是什么。还是那句话,你无需理解文章的每一个细节,只要力求对整理原理有把握就很不错了。

    展开全文
  • 本文对以太坊的原理进行一次大起底,尽量深入浅出且全面的让你理解以太坊的本质到底是什么。让你对以太坊有一个整体而深刻的认识。 本质上来说,以太坊就是一个保存了数字交易永久记录的公共数据库。重要的是,这个...

    链圈的人提起「以太坊」三个字想必是如雷贯耳。无论是以太币,还是其天才创始人Vitalik Buterin,还是关于它的各种新闻,想必闭着眼都能看看而谈。

    即使如此,你可能还是不知道以太坊到底是个什么东西?它包含了哪些部分?又是基于哪些原理运作的?这些你真的都知道吗?

    本文对以太坊的原理进行一次大起底,尽量深入浅出且全面的让你理解以太坊的本质到底是什么。让你对以太坊有一个整体而深刻的认识。

    本文所有内容来自网络。

    本质上来说,以太坊就是一个保存了数字交易永久记录的公共数据库。重要的是,这个数据库不需要任何中间方来维护和双方的权益。相反,它可以作为一种「无需信任」交易系统来运作,也就是你可以在不需要第三方的情况下进行点对点交易。

    从技术层面来更深入的看看以太坊的机制到底是什么。在解释这一概念时,我们尽量不去用复杂或看着吓人的数学公式,即使不是程序员,也能在阅读后对以太坊的运营原理有更清晰的认识。在阅读的时候,你没必要去理解文中的每一个细节,可以聚焦在宽泛的层面上来理解以太坊。

     

    1.区块链的定义

    区块链是具有「共享状态的加密安全交易单机」。听起来有点拗口,我们来分析一下。

    • 「加密安全」是指,数字货币的创造是通过复杂的数学算法来保证的,而这些算法很难破解,类似于系统的防火墙,你无法在区块链中创建虚假的交易或删除交易等。

    • 「交易单机」是指,有一个机器的单个实例,就可以负责系统中产生的所有交易。 换句话说,每个人都相信「一个单一的全局真相」。

    • 「共享状态」意思是,在这一系统中所存储的状态对每个人都是透明和开放的。

     

    知道了区块链的定义,我们就来看看以太坊区块链到底是什么?

    以太坊区块链算法

    以太坊区块链本质上是一个为交易服务的状态机。在计算机科学中,一个状态机指的是这样一种东西,它可以读取一系列的输入,并基于这些输入产生一个新的状态。

     

    以太坊状态机的运行从一个「元状态」开始,这类似于在网络上没有发生任何交易之前的一块空白石板。当交易执行时,这个元状态就转变为一些最终状态。在任何时候,这个最终状态都代表着以太坊区块链的现状。

    以太坊系统中运行着数百万笔交易,这些交易被分组归类为「区块」。一个区块包含一系列交易,每个块与其前面的区块串联在一起。

    要从一个状态转到另一个状态,必须证明交易是有效的。如果一个交易被认为是有效的,就必须通过一个验证过程,这一过程称为「挖矿」。挖矿是指一组节点(即计算机)消耗它们的计算资源来创建一个有效交易的区块。

    网络中任何声明自己是「矿工」的节点都可以尝试创建和验证区块,全世界有许多矿工试图同时创建和验证区块。每个矿工在向区块链提交一个区块时同时,都要提供一个数学的「证明」,且把这个证明作为一个保证:如果这个数学证明存在,则该区块必然是有效的。

    如果要在主区块链上添加一个区块,矿工必须比其他竞争对手更快地对其证明。通过让矿工提供数学证明来验证每个区块的过程被称为「工作量证明」

    一个矿工如果验证了一个新的区块,这个验证工作就会得到一定数额的价值回报。这个价值是多少呢?以太坊区块链使用了一种内部数字令牌,叫做「以太币」。 每当一个矿工证明了一个区块,就会生成并得到一个新的以太币。

     

    你可能会想:什么每个节点都在一条链上?矿工如果想创造新的的区块链怎么办?

    正如我们在上文给区块链的定义,区块链是一个具有共享状态的交易单机。这个定义决定了,区块链的当前状态是一个单一的全局状态,每个人都必须接受。如果拥有多个状态(或链条)会破坏整个系统,因为人们不可能就哪个状态是正确的状态达成一致意见。如果这些链条是分开的,就会出现一个人在一条链上有10个以太币,在另一条链上有20个的情况。在这种情况下,我们没有办法确定哪一个链条最「有效」,无法确定哪个人有多少硬币。

    多条链的产生,被称为「分叉」。因为分叉会破坏系统,因此我们通常会避免分叉,迫使人们选择他们「相信」的链条。

    为了确定哪个路径是最有效的,并防止分叉的发生,以太坊使用了一种叫做「GHOST协议」的机制。

    GHOST = Greedy Heaviest Observed Subtree

    简单地说,GHOST协议让我们必须选择在链上做最多计算的路径。确定该路径的一种方法是使用最新区块的数量,来表示当前路径中的区块总数(不计算起源块)。块数越多,路径越长,挖矿的难度越大,最终就一定会到达最新区块。使用这个方式让我们对当前区块链状态的唯一版本达成一致。

    到这里,我们就对以太坊区块链就有了一个宏观的认识,接下来我们就更深入地看看以太坊系统的主要组成部分:

    • 帐户;

    • 状态;

    • Gas与费用;

    • 交易;

    • 区块;

    • 交易执行;

    • 挖矿;

    • 工作量证明。

     

    2.以太坊的帐户

    以太坊的全球「共享状态」是由许多账户组成的,它们能够通过一个消息传递框架相互通信。每个帐户都有一个与它关联的状态和一个20字节的地址。以太坊的地址是一个160位比特的标识符,用于识别帐户。

    以太坊有两种账户类型:

    1. 外部帐户由私人密钥控制,没有与之相关的代码。

    2. 合约账户由其合约代码控制,并具有与其相关的代码。

    外部账户与合约账户

    外部账户可以通过创建和使用其私人密钥签署一项交易,向其他外部账户或其他合约账户发送消息。两个外部账户之间的消息只是一种价值转移。但从一个外部帐户到一个合约账户的消息会激活合约账户的代码,使它能够执行各种操作(例如转移代币、写入内存、生成新的代币、执行一些计算、创建新合约等)。

    与外部账户不同,合约账户不能自行启动新的交易。相反,合约账户只能根据它们收到的其他交易(从外部账户或从另一个合约账户)进行交易,这点我们会在下文进行探讨。

    因此我们可以得出结论:在以太坊区块链上发生的任何操作都是由外部控制账户的交易引起的。

    帐户状态

    无论帐户是哪种类型,帐户状态都由以下四个部分组成。

    • nonce:如果帐户是一个外部帐户,这个数字代表从帐户地址发送的交易数量。如果帐户是一个合约帐户,nonce是帐户创建的合约数量。

    • balance:这个地址拥有的Wei(以太坊货币单位)数量,每个以太币有1e+18 Wei。

    • storageRoot :一个Merkle Patricia树根节点的哈希,它对帐户的存储内容的哈希值进行编码,并默认为空。

    • codeHash:EVM(以太坊虚拟机)的哈希值代码。 对于合约帐户,这是一个被哈希后并存储为codeHash的代码。对于外部帐户,codeHash字段是空字符串的哈希。

     

    3.全局状态

    我们知道以太坊的全局状态包括帐户地址和帐户状态之间的映射,这个映射存储在一个数据结构中,这种结构被称为Merkle Patricia树。

    Merkle Patricia树是一种由一组树状节点构成的二进制结构,它包括:

    1. 底层有大量的叶子节点,其中包含了潜在的数据;

    2. 一组中间节点,其中每个节点是其两个子节点的哈希;

    3. 一个单个的根节点,也是由它的两个子节点的哈希形成的,代表树的顶部。

    树的底部数据是通过把我们想要存储的数据分割成块后而生成的,然后将这些数据块分成几个桶,然后对每个桶的进行哈希迭代,值到剩下的哈希总数变为一个根哈希。  

    此外,树需要存储在里面的每一个值的密钥。从树的根节点开始,密钥告诉你要遵循哪个子节点来获取相应的值,这些值存储在叶子节点中。在以太坊中,状态树的键值对是地址和相关帐户之间的映射,包括每个帐户的balance、nonce、codeHash和storageRoot(storageRoot本身就是一棵树)。

    同样的树结构也用于存储交易和收据。更具体地说,每个块都有一个「header」,它存储三个不同Merkle树结构根节点的哈希,包括:

    1. 状态树;

    2. 交易树;

    3. 收据树。

    Merkle树能够高效存储信息的特性在以太坊系统中十分被看重,我们可以称之为「轻节点」或「轻客户端」,其实区块链的节点有两种:完整节点和轻节点

    一个完整的节点需要下载完整的链,从元区块到当前的头部块,执行所有的交易也都包含其中。通常情况下,矿工储存完整的档案节点,因为他们必须这样做才能完成挖矿的过程。当然,也可以在不执行交易的情况下下载完整的节点。无论如何,任何完整的节点都包含整条链。

    轻节点的概念与之相对,除非一个节点需要执行每个交易或查询历史数据,否则就没有必要存储整个链。这就是轻节点的意义所在。轻节点并不下载和存储完整链并执行所有的交易,而是只下载从元区块到当前头部区块的信息,而不执行任何交易或检索任何关联状态。因为轻节点可以访问包含三个树的区块头部哈希,所以仍然可以很容易地生成和接收关于交易、事件、余额等可验证的结果。

    这样做的原因是因为Merkle树中的哈希会向上传播ーー如果一个恶意用户试图将一个伪造的交易交换到Merkle树的底部,这种变化将导致上面节点的哈希变化,也将改变上面节点的哈希值。

    任何想要验证一段数据的节点都可以使用所谓的「Merkle证明」来执行。一个Merkle 证明包括:

    1. 需要验证的大量数据及其哈希值;

    2. 树的根哈希;

    3. 「分支」(所有的参与者的哈希沿着路径上升,一直到「树根」)。

    任何读取该证明的人都可以验证树上所有的分枝是否一致,因此给定的数据块实际上位于树中的某个位置。

    总之,使用Merkle树的好处是,该结构的根节点依据树中存储的数据进行加密,因此根节点的哈希可以作为该数据的安全证明。由于区块头包括状态、交易和收据树的根哈希。因此任何节点都可以在不需要存储整个状态的情况下,验证以太坊的一小部分状态,而整个状态的大小可能是无限的。

     

    4.Gas和支付

    在以太坊中,费用的计算是一个非常重要的概念。在以太坊网络上进行的每一笔交易都会产生费用ーー没有免费的午餐!这笔费用被称为「Gas」。

    Gas Price是指:你愿意花在每一个单位Gas上的以太币数量,是用「gwei」来计算的。Wei是以太币中最小的单位,其中1018 Wei代表1个以太币。一个gwei是1,000,000,000 Wei。

    每次交易,发送方都要设置一个Gas Limit和Gas Price。Gas Limit和Gas Price代表发送方愿意为执行交易支付的最大金额。

    例如,发送方将Gas Limit设置为50,000,一个Gas Price设置为20 gwei。这意味着发送者愿意花费最多50,000 x 20 gwei,也就是:1,000,000,000,000,000 Wei(0.001以太币)来执行这一交易。

    这里需要留意的是,Gas限额是发送方愿意花钱的最大限度。如果他们的账户余额中以太币的数量大于这个最大值,那么他就可以进行交易。在交易结束时,发送方将被退还的那些未使用的Gas,按原来的价格进行兑换。

    如果发送方没有提供执行交易所必需的Gas,则该交易运行的结果会是「余额不足」,并被认为无效。在这种情况下,交易处理中止,其间的产生的任何状态都会发生逆转,这样就可以在交易发生之前返回到以太坊区块链。此外,交易失败的记录会被记录下来,显示尝试过哪些交易,失败了哪些交易。由于系统已经在Gas用光之前做完了运算工作,所以从逻辑上看,Gas不会被退还给发送方。

    那么,这些Gas的钱到底去哪了呢?发送方花在Gas上的所有钱都寄给了「受益人」地址,也就是矿工地址。由于矿工们正在努力运行计算和验证交易,所以收到了Gas作为奖励。

    通常情况下,发送方愿意支付的Gas价格越高,矿工从交易中获得的价值就越大,矿工们也就越有可能选择这个交易。通过这种方式,矿工可以自由地选择交易。为了给发送者设置Gas Price做参考,矿工们可以直接提出他们执行交易所需的最低Gas Price。

    存储费用

    Gas不仅用于支付计算的费用,还用于支付存储的使用费用。存储的总费用与使用的32字节的最小倍数成正比。

    存储费用与交易费用有一些不同。由于增加的存储量增加了所有节点上的以太坊状态数据库的大小,所以存储数据的数量会变小。由于这个原因,如果一个交易有一个步骤可以清除存储中的条目,则可以免除执行该操作的存储费用,并且还能因此得到退款。

    费用的目的是什么?

    以太坊工作方式的一个重要方面是,网络执行的每一个操作都同时受到每个完整节点的影响。然而,在以太坊虚拟机上的计算步骤非常昂贵。因此,以太坊智能合约更适合简单的任务,比如运行简单的业务逻辑或验证签名和加密其他对象,而不适合更复杂的用途,比如文件存储、电子邮件或机器学习,这些都会给网络带来压力。收费的目的就是使整个网络不会因用户的不当使用而变得负担过重。

    除此之外,以太坊是一种图灵完整语言(图灵机是一种能够模拟任何计算机算法的机器)。这就允许了循环,使得以太坊区块链容易受到暂停问题的影响,因为在这个问题中,无法确定一个程序是否会无限运行。如果没有费用,意图不良的人可以通过在交易中执行一个无限循环来扰乱网络,从而产生不良的影响。因此,费用保护了网络免受蓄意攻击。

    那么,为什么我们还要支付存储费用呢?就像计算一样,在以太坊网络上的存储也是整个网络必须承担的一个成本。

     

    5.交易与消息

    我们在上面说到,以太坊是一个基于交易的状态机。换句话说,不同账户之间发生的交易正是以太坊从一个状态转移到另一个状态的原因。

    因此,交易可以看做是一个由外部拥有的帐户生成的序列化加密签名指令,然后提交给区块链。

    交易分为两类:「消息调用」和「合约创建」(创建新的以太坊合约的交易)。不管哪一类,所有交易都包含以下组件:

    • Nonce:发送方发送的交易数量的计数;

    • gasPrice:发送方愿意支付每单位Gas所需执行交易的Wei数量;

    • gasLimit:发送方愿意支付的执行这一交易的Gas最大数量。这个数额是预先设定和支付的;

    • to:接收方的地址,在创建合约的交易中,合约帐户地址还不存在,因此使用了空值;

    • Value:从发送方转移到收件方的金额,在创建合约的交易中,这个Value作为新创建合约账户内的起始余额;

    • v, r, s:用于生成识别交易发送方的签名;

    • Init只存在于创建合同的交易中):用于初始化新合约帐户的EVM代码片段,它只运行一次,然后被丢弃,当init第一次运行时,它会返回帐户代码的主体,这个代码是与合约帐户永久关联的一段代码;

    • data只存在于消息调用中的可选字段):消息调用的输入数据(即参数)。例如,如果一个智能合约充当域名注册服务,那么对该合约的调用可能会有诸如域名以及IP地址等输入字段。

    在说「账户」的时候,我们看到,交易(包括消息调用和合约创建的交易),总是由外部账户启动并提交给区块链的。另一种思考方式是,交易是连接外部世界与以太坊内部状态的桥梁。

    但这并不意味着一个合约不能与其他合约对话。在全局范围内存在的合约,可以与同一范围内的其他合约进行交流。它们是以通过「消息」或「内部交易」的方式来实现的。我们可以认为消息或内部交易类似于交易,其主要区别在于它们不是由外部账户所产生的,相反,是由合约产生的,是虚拟对象。与交易不同,合约不是序列化的,而是只存在于以太坊的执行环境中。

    当一个合约将一个内部交易发送到另一个合约时,存在于接收方合约账户上的关联代码就会被执行。

    需要注意的一点是,内部交易或消息不包含Gas Limit。这是因为Gas Limit是由原始交易的外部创建者(即部分外部帐户)来决定的。外部账户集合的Gas Limit必须足够高,以便进行交易,这包括由这一交易而导致发生的任何次级处理运行,例如合约对合约的消息。如果在交易和消息链中,特定的消息执行耗尽了Gas,那么该消息的执行将与执行引发的所有后续消息一起恢复。不过,上一级的执行不需要恢复。

     

    6.以太坊的区块

    所有的交易都被组合成「区块」,区块链则包含一系列这样被链接在一起的区块。在以太坊中,一个区块包括「区块头」、关于包含在此区块中交易集的信息,与当前块的ommers相关的一系列其他区块头Ommer解释

    Ommer是什么?

    比起比特币之类的区块链,以太坊的构建方式使区块生成时间要低很多。这样可以更快地处理交易。然而,缩短区块生成时间的一个缺点是,矿工们要找到更多相互竞争的区块解决方案。这些相互竞争的区块也被称为「孤儿区块」,不能进入主链。

    Ommer的目的是帮助奖励矿工,也包括这些孤儿区块。矿工的ommer必须是「有效的」,也就是说在目前区块的第六代或更小的范围内。六代之后,陈旧的孤儿区块就不能再被引用。比起完整的区块,Ommer块获得的奖励要小一些。尽管如此,矿工们仍然有一定的动力去挖掘这些孤儿区块并获得回报。

    区块头

    回到区块本身,之前提到每个区块都有一个区块头,但到底什么什么是区块头?区块头是区块的一部分,包括:

    • Parenthash:一个父区块头的哈希(这就是为什么区块链被称为区块「链」);

    • Ommershash:当前区块ommer列表的哈希;

    • beneficiary:收取采矿费用的帐户地址;

    • Stateroot:状态树的根节点哈希;

    • transactionsRoot:包含在此区块中列出的所有交易树根节点的哈希值;

    • receiptsRoot :包含本区块中列出的所有交易树根节点的哈希的收据;

    • logsBloom:一个由log组成的Bloom过滤器(数据结构);

    • difficulty:这个区块的难度水平;

    • 编号:当前区块的记数(元区块的编号为0;每个后续区块的块数增加1);

    • gasLimit:当前每个区块的Gas限制;

    • gasUsed:本区块交易所使用的总Gas之和;

    • 时间戳:这个区块注入的unix时间戳;

    • extraData:与此区块相关的其他数据;

    • mixHash:当与nonce结合时,证明这个区块执行了足够计算的哈希值;

    • Nonce:当与mixHash结合时,证明这个区块已经执行了足够计算的哈希值;

    每个区块头包含三个树结构:

    • 状态根(stateRoot);

    • 交易根(transactionsRoot);

    • 收据根(receiptsRoot)。

    这些树结构只不过是之前讨论过的Merkle树而已,没有什么特别的。不过,从上面的描述中可以看到,有一些术语还需要进一步说说。

     

    日志(Log)

    以太坊允许log跟踪各种交易和消息。合约也可以通过定义需要记录的「事件」来显式生成log。

    一条log包含:

    • 记录器的帐户地址;

    • 一系列主题,它们表示此交易所进行的各种事件,以及,

    • 任何与这些事件有关的数据。

    log存储在一个bloom过滤器中,它以有效的方式存储海量的日志数据。

    交易收据

    区块头中存储的日志来自于交易收据中包含的日志信息。就像在商店买东西时收到收据一样,以太坊会为每笔交易生成一张收据。不出所料,每张收据都包含有关交易的某些信息。 这样的收据包括以下内容:

    • 区块编号;

    • 区块哈希;

    • 交易哈希;

    • 当前交易所使用的Gas;

    • 在当前交易执行后,当前区块中使用的Gas;

    • 执行当前交易时创建的日志。

    区块的难度

    区块的「难度」用于在验证区块的时间内来加强一致性。元区块的难度为131,072,并用一个特殊的公式来计算后面每个区块的难度。如果某个区块比前一个区块更快地被验证,那么以太坊协议会增加该区块的难度。

    该区块的难度会影响nonce,这是一个哈希,必须在挖矿时使用工作量证明算法来计算。

    区块的难度与nonce之间的关系在数学上表示为:

    这里Hd代表了难度。找到满足难度阈值的nonce的唯一方法是使用工作量证明算法来枚举所有的可能性。 寻找解决方案的预期时间与难度成正比,难度越大,找到nonce就越困难,因此验证区块的难度就越大,这反过来增加了验证新区块的时间。通过调整区块的难度,协议可以调整验证区块的时长。

    另一方面,如果验证时间变慢,那么协议就会减少难度。通过这种方式,验证时间可以自我调整从而保持一个常量ーー平均每15秒一个区块。

    交易的执行

    看到这,你已经来到了以太坊协议中最复杂的部分之一。假设将一个交易发送到以太坊网络进行处理,如果以太坊状态要将你的交易包括在内,会发生什么?

    首先,所有交易都必须满足初始的一组需求才能执行。 其中包括以下几个部分。

    • 交易必须是正确的RLP格式(RLP是「递归长度前缀」的缩写,是用于二进制数据编码嵌套数组的数据格式,RLP是以太坊使用的序列化对象的格式)。

    • 有效的交易签名。

    • 有效的交易nonce,回想一下,一个帐户的nonce是从该帐户发送的交易的统计,为了有效,交易nonce必须与发送方帐户的nonce相等。

    • 交易的Gas限额必须等于或大于交易所使用的内部Gas, 内部Gas包括:

    1)为执行交易预先确定的费用为21,000 Gas;

    2)与该交易一起发送的数据Gas费用(对于每一个等于零的数据或代码的每个字节收取4个Gas,每个非零字节的数据或代码为68个Gas);

    3)如果这笔交易是一笔合约创建交易,则额外收取32,000 Gas。

    • 发送方的账户余额必须有足够的以太币来支付前期的Gas费用。前期Gas成本的计算很简单:首先,交易的Gas Limit乘以交易的Gas Price,以确定最大的Gas成本。 然后,这个最大的成本被算在从发送方转移到接收方的总额中。

    如果交易符合上述有效性的所有要求,那么,就可以进入下一个步骤。

    首先,从发送方的余额中扣除执行的前期成本,并将发送方帐户的nonce加1。我们可以计算剩余的Gas,因为交易的Gas Limit要减去所使用的内在Gas。

    然后,交易开始执行。在交易的整个执行过程中,以太坊都跟踪「子状态」。子状态记录交易中产生的信息,这些信息也是交易完成后所马上需要用到的。具体来说,它包含:

    • 自毁集合:交易完成后将丢弃的一组帐户(如果有的话);

    • 日志序列:虚拟机代码执行的存档和可索引的检查点;

    • 退款余额:交易完成后退还给发送者账户的余额。

    一旦处理完交易中的所有步骤,并假定没有无效状态,则通过确定向发送方退还未使用的Gas数量,来最终判定最终状态。除了未使用的Gas外,发送方还从上文所述的「退款余额」中退还了一些余额。

    一旦发送者获得退款:

    • Gas(以太币)就会给到给矿工;

    • 该交易所使用的Gas被添加到区块的Gas计数器(该计数器记录该区块中所有交易使用的总Gas);

    • 删除自毁集合中的所有帐户(如果有的话);

    最后,只剩下了新的状态和已创建交易的一组log。至此,我们就讲完了交易执行的基本原理,下面再来看看合约创建的交易和消息调用之间的一些差异。

     

    合约创建

    前面说过,以太坊的账户分为两类:合约帐户和外部账户。当交易是「契约创建」(Contract Creating)时,意思是,交易的目的是创建一个新的合约账户

    为了创建一个新的合约帐户,我们首先使用一个特殊的公式来声明新账户的地址,然后通过以下方式初始化新帐户:

    • 将nonce设置为零;

    • 如果发送方在交易中发送了一定数量的以太币作为价值,则将帐户余额设置为该价值;

    • 从发送方的余额中扣除这个新账户余额的增加部分;

    • 将存储设置为空;

    • 将合约的codeHash设置为空字符串的哈希值;

    一旦帐户完成了初始化就可以创建帐户了,使用与交易一起发送的init代码。在执行这个init代码的过程中,可能发生很多情况。根据合约的构造函数,它可能更新帐户的存储,创建其他的合约账户,或其他的消息调用,等等。

    一旦初始化合约的代码被执行就将开始消耗Gas,交易使用的Gas不能超出账户的余额,一旦超出,将会出现「Gas耗光」的异常并且退出。如果交易由于Gas耗光的异常而退出。

    但是,如果发送方在交易中发送了一些以太币,这时合约创建失败也会退还以太币吗?

    答案是,不会。

    如果初始化代码执行成功,则支付最终的合约创建成本。这是一个存储成本,并且与创建合约代码的大小成正比。如果剩余的Gas不足以支付这笔最终成本,那么这笔交易将再次声明为一个「Gas耗光」异常。

    如果一切顺利,而且没有遇到任何异常,那么剩余的Gas都会退还给交易的原始发送方,并允许改变状态继续存在!

     

    消息调用

    消息调用的执行类似于合约创建,但有一些不同之处。

    消息调用的执行不包含任何init代码,因为没有创建新的帐户。但是,如果这些数据是由交易发送方提供的,它可以包含输入数据。一旦执行,消息调用也有一个额外的组件,其中包含输出数据,如果后续执行需要此数据,则使用这些数据。

    如同合约创建一样,如果由于Gas耗尽或交易无效(例如堆栈溢出、无效的跳转目的地或无效指令),则所使用的任何Gas都不会退还给原来的调用者,取而代之的是,所有剩余的Gas都会被消耗掉,并且状态被重置到余额转移之前的情况。

    执行模式

    现在,我们来看看在VM中,交易实际上是如何执行的。

    实际处理交易的部分是以太坊自己的虚拟机,被称为EVM。就像之前定义的那样,EVM是一个「图灵完备」的虚拟机。唯一的不同是EVM有内在Gas的约束。因此,可以完成的计算总量本质上受到所提供Gas数量的限制。

    此外,EVM 有一个基于栈机器的架构。栈机器是一种使用「后入先出」的堆栈来保存临时值的计算机。EVM中每个栈条目的大小为256位,最大为1024位。

    EVM具有内存,其中存储的条目是字地址字节数组(word-addressed byte arrays)。 内存是易失性的,这意味着它不是永久性的。

    EVM还有存储空间。与内存不同,内存的存储是非易失性的,并作为系统状态的一部分来维护。EVM在一个虚拟ROM中独立存储程序代码,只能通过特殊的指令访问虚拟ROM。这就是EVM与典型的冯·诺伊曼结构的不同,冯·诺伊曼结构中程序代码是在内存或存储中。

    EVM也有自己的语言——EVM字节码。当程序员在以太坊上写智能合约的时候,通常用高级语言写代码,比如Solidity。然后,可以编译成EVM字节码,以便EVM可以理解执行。

    接下来我们来看看EVM如何运行。在执行特定的计算之前,处理器要确保以下信息是可用且有效的:

    • 系统状态;

    • 用于计算的剩余Gas;

    • 拥有执行代码的帐户地址;

    • 产生此执行交易的发送方地址;

    • 引发代码执行的帐户地址(可能与原始发送方不同);

    • 产生此次执行交易的Gas Price;

    • 此执行的输入数据;

    • 作为当前执行的一部分,价值(以Wei为单位)传递到这个帐户;

    • 要执行的机器码;

    • 当前块的区块头;

    • 当前消息调用或合约创建的栈深度;

    • 在执行开始时,内存和栈是空的,程序计数器归零。

    然后,EVM递归执行交易,计算系统状态和每个循环的机器状态。简单地说,这个系统状态就是全局状态。机器状态包括:

    • 可用的Gas;

    • 程序计数器;

    • 内存的内容;

    • 内存中的字活跃数;

    • 栈内容。

    栈中条目是从该系列最左边的部分中添加或删除。表现为,在每个循环中,从剩余的Gas中减少适当的Gas,并且程序计数器递增。

    在每个循环的结束时,有三种可能性:

    1. 机器达到一个特殊状态(例如Gas不足、指令无效、栈条目不足、栈条目溢出超过1024、无效的JUMP/JUMPI等),因此必须停止,任何更改都将被丢弃;

    2. 这个序列继续进入下一个循环;

    3. 系统被迫停止。

    假设执行没有达到一个特殊状态,并达到一个「可控制的状态」或正常停止,那么机器就会生成结果状态、保留执行后剩余的Gas。

    说了这么多,终于结束了以太坊中最复杂的部分。即使没有完全理解这部分,也没关系,除非是从事底层的开发工作,否则并不需要真正理解这些细节。

     

    一个区块的最终完成

    最后,来看看多个交易块是如何最终完成的。

    这里所说的「最终」可能是指两种不同的东西,这取决于区块是新的还是已经存在的。如果是一个新区块,「最终」指的是挖掘这个区块所需要的过程。如果是一个现有的区块,那么「最终」指的是验证块的过程。在这两种情况下,对于要到「最终」状态的区块有以下四个要求。

    1. 验证(如果是挖矿,就是判定)ommer:每个区块头中的每个ommer区块都必须是一个有效的区块头,并且在当前区块的六代以内。

    2. 验证(如果是挖矿,就是判定)交易:区块上的gasUsed数字必须等于该区块中所列交易所使用Gas的累积。

    3. 申请奖励(只限于挖矿的情况):受益人地址被授予5以太币,用于开采该区块。 (根据以太坊EIP-649,这5个ETH的报酬将很快减少到3个)。此外,对于每一个 ommer,当前区块的受益者将额外获得当前区块奖励的1/32。最后,ommer区块的受益人也可以得到一定数额的赔偿。

    4. 验证(如果挖矿,计算一个有效的)状态和nonce:确保应用所有交易和由此产生的状态更改,在区块奖励应用于最终交易的结果状态之后,定义新区块的状态。通过检查这个最终状态来验证存储在区块头中的状态。

     

    7.挖矿的工作量证明

    将区块难度赋予意义的算法叫做「工作量证明」(PoW)。以太坊的工作量证明算法被称为「Ethash」(之前被称为Dagger-Hashimoto)。

    该算法的公式如下:

    这里m是mixHash、n是nonce、Hn是新区块的头(不包括nonce和mixHash组件)、Hn是块头的nonce、d是DAG(一个大数据集)。

    还记得上面谈到的在区块头中存在的mixHash和nonce两个字段吗?

    • mixHash是一个哈希,当与nonce结合时,可证明这个区块执行了足够的计算;

    • nonce是一个哈希,当与mixHash结合时,可证明这个区块已经执行了足够的计算;

    PoW的功能就是评估这两个字段。至于如何使用的PoW函数来精确计算mixHash和nonce说起来有点复杂,但从总体上看,它的工作原理是这样的。

    每个区块都算出一个「seed」,每个「epoch」对应的seed都不相同,一个epoch相当于3万个区块的长度。在第一个epoch,seed是一系列32字节零的哈希。对于后来的每一个epoch来说,它都是以前seed哈希的哈希。使用seed,一个节点可以计算一个伪随机的「缓存」。

    这个缓存非常有用,因为它使之前讨论过的「轻节点」成为可能。轻节点的目的是为了使某些节点能够有效地验证交易,而没有存储整个块环链数据集的负担。一个轻节点可以完全基于这个缓存来验证交易的有效性,因为缓存可以重新生成需要验证的特定区块。

    使用缓存,节点可以生成DAG数据集,数据集中的每个项都依赖于缓存中的少量伪随机选择(pseudo-randomly-selected)的项。为了成为一名矿工,必须生成这个完整的数据集;所有客户和矿工都存储这个数据集,并且数据集随时间线性增长。

    然后,矿工们可以随机抽取数据集的片段,然后通过数学函数将它们混合成一个mixHash。矿工将反复生成mixHash,直到输出低于预期目标的nonce。当输出满足这个要求时,这个nonce被认为是有效的,并且块可以添加到链上。

     

    挖矿作为一种安全机制

    总体而言,PoW的目的是以一种安全加密方式证明工作量,基于特定的计算量生成某些输出(即nonce)。这是因为除了穷举所有可能性之外,没有更好的办法来找到低于要求阈值的nonce。重复应用哈希函数的输出具有均匀分布,因此我们可以确信,找到这样一个nonce所需的平均时间取决于难度阈值。难度越大,解决问题的时间就越长。这样,PoW算法对难度概念赋予了真实的意义,这个概念被用来增强区块链的安全。

    那么,区块链安全又是指什么?很简单:就是要创建一个每个人都信任的区块链。正如先前在本文中讨论的那样,如果存在一个以上的链,用户将对其失去信任,因为他们无法合理地确定哪一个链是「有效的」链。为了让一组用户接受存储在块环链上的基本状态,需要一个大家都相信的且单一规范的区块链。

    而这正是PoW的作用:它确保一个特定的区块链可以保持规范,使攻击者难以创建新的区块,或者覆盖历史的某一部分(例如擦除交易或创建虚假的交易),或者对一个分叉进行维护。为了验证他们的区块,攻击者需要比网络中的其他任何人都更快地解决nonce问题,这样网络就会相信他们的链条是最重链(基于之前提到的GHOST协议的原则)。这是基本上不可能的,除非攻击者拥有超过一半的网络挖掘能力,因此这种情况被称为「51%攻击」。

    挖矿作为一种财富分配机制

    除了确保一个安全的区块链环境,对那些为了提供这种安全而消耗算力的人,Pow还是一种分配财富的方式。回想一下,矿工在开采一个区块时会得到奖励,其中包括:

    • 「获胜」区块获得的5以太币(不久将改为3以太币)的奖赏;

    • 该区块所包括的交易在区块内消耗的Gas成本;

    • 将ommer作为区块的一部分的额外奖励。

    从长远来看,为了确保PoW机制在安全和财富分配方面的使用是可持续的,以太坊努力培养它的两个特性:

    • 让尽可能多的人能够接触到它,换句话说,人们不应该需要专门的硬件来运行算法,这样做的目的是使财富分配模型尽可能开放,以便任何人都可以根据自身的情况提供计算能力,以换取以太币。

    • 减少单个节点(或小集)产生不成比例利润的可能性,任何节点,如果能够获得不成比例的利润,就意味着节点对规范区块链的确定有很大的影响,这会降低网络的安全性。

    在比特币区块链网络中,与上述两个属性有关的一个问题是,PoW算法是一个 SHA256哈希函数。这类函数的弱点在于,它可以通过使用专门的硬件更有效地解决问题,也就是所谓的ASIC。

    为了解决这一问题,以太坊选择了将PoW算法按顺序存储到内存硬件中。这意味着这个算法是经过设计的,所以计算nonce需要大量的内存和带宽。大量的内存需求使得计算机很难同时使用它的内存来同时发现多个nonce,而且高带宽的要求使得即使是超级计算机也很难同时发现多个nonce。这减少了集中化的风险,也为正在进行验证的节点创建了一个更公平的机制。

    需要注意的是,以太坊正在从PoW机制过渡到PoS机制,这又是另一个话题了,希望可以在今后的文章中探讨。

     

    展开全文
  • 21 以太坊权益证明

    2021-01-08 00:46:12
    比特币和以太坊目前都是使用的基于工作量的证明,这种共识机制受到了普遍的批评——浪费电 以下这张图表示比特币的能耗随时间的曲线 以及 具体的数字 以下是以太坊的能耗曲线 以太坊与比特币相比能耗要少很多,这...
  • 选择2,配置新的创世区块,之后的选项1是创建新的创世区块,2是导入一个已经存在的配置,这里选择1 这里的选项是选择该链所用的共识机制,第一个是以太坊的公链共识机制PoW,显然不适合私链或者联盟链,所以这里选择...
  • 以太坊与智能合约.pdf

    2020-02-18 11:10:29
    尽量通俗易懂,由浅入深的介绍了被称为区块链2.0的以太坊的基本架构和算法,包括MPT树,以太坊数据结构,区块验证机制,智能合约的执行机制等,并且结合了两个简单的智能合约进行了讲解。然后介绍了一些以太坊中出现...
  • 以太坊白皮书.pdf

    2020-04-16 12:21:12
    景,提出典型的区块链技术架构,并分析了共识机制、数据存储、网络 协议、加密算法、隐私保护和智能合约等6类核心关键技术,以及区块链 治理和安全。最后,结合国内外发展趋势,提出了我国区块链技术发展 路线图建议...
  • 以太坊的共识机制

    万次阅读 2018-08-13 14:50:49
    在开始之前,我们补充一点基础知识。   第一个概念是哈希。简单理解,哈希是一个函数。...几乎任何加密货币都会用到哈希算法,以太坊采用的哈希算法是ethash算法。   第二个补充知识是,以太坊的区块结构。...
  • POW是指工作者通过一定的工作量,提供一个能被大多数验证者快速验证的答案,从而得到奖励的机制。 原理 讲原理之前,先给大家普及两个概念:难度值和nonce 难度值        难度值...
  • 这一机制是为了使以太坊向权益证明机制算法的巨大转变而设计的。 在目前的工作量证明共识机制的条件下,矿工每次创建新区块并将其添加到区块链中时都会赢得奖励。但当以太坊难度炸弹设置为“引爆”时,矿工通过挖矿...
  • 以太坊交易收发机制

    2018-07-19 14:27:53
    目录 1、交易的主要数据结构 2、交易收发相关协程 3、关键流程描述 ​ 3.1 交易数据验证流程 ​ 3.2 交易入池流程   1、交易的主要数据结构 2、交易收发相关协程 3、关键流程描述 ...
  • 信标链是以太坊 2.0 系统的核心,然而针对该系统的大部分描述都过于技术化、针对性过强或者...阅读本文之前,我们假设读者对以太坊和比特币有不错的基础知识,并对权益证明 (Proof of Stake) 这一共识机制有一定了解。
  • 相对于比特币来说,以太坊账户是以太坊的一个十分具有划时代意义的发明,因为账户的出现,以太坊不仅可以支持比特币中直接的货币转账,还可以支持更加复杂的智能合约。
  • 以太坊(Ethereum ETH)的奖励机制

    千次阅读 2018-03-14 10:08:16
    然而,除了购买矿机、连接矿池、卖币套现之外,是否有人关注过以太坊的奖励机制呢? 临时分叉 区块链由于是一种去中心化的技术,全世界所有的矿工同时工作,各自独立的挖掘满足要求的区块。由于是各自独立的工作,...
  • 以太坊概述 比特币和以太坊是两种最主要的加密货币 比特币被称为区块链1.0,以太坊被称为区块链2.0 以太坊的设计上针对比特币的运行过程中出现的一些问题进行了一些改进
  • 以太坊利用了很多跟比特币类似的机制(比如区块链技术和 P2P 网络),来维护一个共享的计算平台,这个平台可以灵活且安全地运行用户想要的任何程序(当然也包括类似比特币的区块链程序)。 geth+docker运行以太坊...
  • 以太坊基础概念

    千次阅读 2022-03-20 21:28:12
    1、以太坊的组成部分:P2P网络、交易、以太坊虚拟机(EVM)、以太坊账本、客户端 2、以太坊中的重要概念:账户,分为普通账户(EOA)和合约账户(Contract)、地址、交易、gas 3、以太发行规则:挖矿前、挖矿产出、...
  • 以太坊技术浅探

    千次阅读 2022-03-13 20:09:32
    目录 一、技术背景 二、 关键技术 2.1 智能合约 2.2 共识算法 ...以太坊技术探究 摘要:区块链技术是近十年来的新兴技术,具有去中心化、不可篡改、数据公开透明等优点,是分布式数据...
  • 文章目录什么是以太坊 2.0?以太坊 1.0 和 2.0 的区别2.0 升级完成后有什么变化?以太坊 2.0 发展路线图持币人手中的 ETH 会受影响吗?如何通过质押成为验证人?普通用户不建议成为验证人 什么是以太坊 2.0? 以太坊...
  • 以太坊之Gas

    千次阅读 2022-02-03 23:34:45
    Gas:以太坊中资源消耗的基础单位 GasLimit:允许消耗的最大Gas值 GasUsed:执行后消耗的最大Gas值 GasPrice:用户为消耗的每个Gas单位支付的以太币 在交易的执行过程中,每笔交易都带有基础 Gas 消耗值。 用户在...
  • 以太坊交易

    千次阅读 2022-03-05 22:14:36
    以太坊交易
  • 一、以太坊简介 以太坊(Ethereum)项目的最初目标是打造一个运行智能合约的平台(Platform for Smart Contract),支持图灵完备的应用,按照智能合约的约定逻辑自动执行,理想情况下将不存在故障停机、审查、欺诈以及...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,614
精华内容 8,645
关键字:

以太坊机制