以太坊基础

来源:互联网 发布:天文软件stellarium 编辑:程序博客网 时间:2024/09/21 09:05

本文时学习区块链技术中关于以太坊这一部分的相关学习总结整理。

以太坊简介

以太坊(Ethereum)目标是打造成一个运行智能合约的去中心化平台(Platform for Smart Contract),平台上的应用按程序设定运行,不存在停机、审查、欺诈、第三方人为干预的可能。为了打造这个平台,以太坊提供了一条公开的区块链,并制定了面向智能合约的一套编程语言Solidity。智能合约开发者可以在其上使用官方提供的工具来开发支持以太坊区块链协议的应用。

以太坊架构如下图所示:
这里写图片描述

以太坊区块链的特点主要包括:

  • 单独为智能合约指定编程语言 Solidity;
  • 使用了内存需求较高的哈希函数:避免出现算力矿机;
  • uncle 块激励机制:降低矿池的优势,减少区块产生间隔为 15 秒;
  • 难度调整算法:一定的自动反馈机制;
  • gas 限制调整算法:限制代码执行指令数,避免循环攻击;
  • 记录当前状态的哈希树的根哈希值到区块:某些情形下实现轻量级客户端;
  • 为执行智能合约而设计的简化的虚拟机 EVM。

更多参考以太坊白皮书、黄皮书:
以太坊白皮书:https://github.com/ethereum/wiki/wiki/%5B%E4%B8%AD%E6%96%87%5D-%E4%BB%A5%E5%A4%AA%E5%9D%8A%E7%99%BD%E7%9A%AE%E4%B9%A6
以太坊黄皮书:http://gavwood.com/paper.pdf

以太坊技术

以太坊核心概念

以太坊虚拟机

以太坊虚拟机(EVM)是智能合约的运行环境。它是一个完全独立的沙盒,合约代码在EVM内部运行,对外是完全隔离的,甚至不同合约之间也只有有限的访问权限。它是以太坊项目中的一个主要创新。

账户

以太坊中有两类账户,它们共用同一个地址空间。外部账户,该类账户被公钥-私钥对控制。合约账户,该类账户被存储在账户中的代码控制。外部账户的地址是由公钥决定的,合约账户的地址是在创建合约时由合约创建者的地址和该地址发出过的交易数量计算得到。两类账户的唯一区别是:外部账户没有代码,人们可以通过创建和签名一笔交易从一个外部账户发送消息。每当合约账户收到一条消息,合约内部的代码就会被激活,允许它对内部存储进行读取、写入、发送其他消息和创建合约。

以太坊的账户包含4个部分:①随机数,用于确定每笔交易只能被处理一次的计数器;②账户目前的以太币余额;③账户的合约代码(如果有的话);④账户的存储(默认为空)。

消息

以太坊的消息在某种程度上类似于比特币的交易,但是两者之间存在3点重要的不同。
1)以太坊的消息可以由外部实体或者合约创建,然而比特币的交易只能从外部创建。
2)以太坊消息可以选择包含数据。
3)如果以太坊消息的接收者是合约账户,可以选择进行回应,这意味着以太坊消息也包含函数概念。

交易

以太坊中“交易”是指存储从外部账户发出的消息的签名数据包。交易包含消息的接收者、用于确认发送者的签名、以太币账户余额、要发送的数据和被称为STARTGAS和GASPRICE的两个数值。为了防止代码出现指数型爆炸和无限循环,每笔交易需要对执行代码所引发的计算步骤做出限制。STARTGAS就是通过需要支付的燃料来对计算步骤进行限制,GASPRICE是每一计算步骤需要支付矿工的燃料的价格。

Gas

以太坊上的每笔交易都会被收取一定数量的燃料Gas,设置Gas的目的是限制交易执行所需的工作量,同时为交易的执行支付费用。当EVM执行交易时,Gas将按照特定规则被逐渐消耗。Gas价格由交易创建者设置,发送账户需要预付的交易费用= GASPRICE * Gas amount。如果执行结束还有Gas剩余,这些Gas将被返还给发送账户。无论执行到什么位置,一旦Gas被耗尽就会触发一个out-of-gas异常。同时,当前调用帧所做的所有状态修改都将被回滚。

存储、主存和栈

每个账户都有一块永久的内存区域,被称为存储,其形式为key-value,key和value的长度均为256位。在合约里,不能遍历账户的存储。相对于主存和栈,存储的读操作开销较大,修改存储甚至更多。一个合约只能对它自己的存储进行读写。

第二个内存区被称为主存。合约执行每次消息调用时都有一块新的被清除过的主存。主存可以按字节寻址,但是读写的最小单位为32字节。操作主存的开销随着主存的增长而变大。

EVM不是基于寄存器的,而是基于栈的虚拟机。因此所有的计算都在一个称为栈的区域内执行。栈最大有1024个元素,每个元素有256位。对栈的访问只限于其顶端,允许复制最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面16个元素中的一个。所有其他操作都只能取最顶的一个或几个元素,并把结果压在栈顶。当然可以把栈里的元素放到存储或者主存中。但是无法只访问栈里指定深度的那个元素,在那之前必须把指定深度之上的所有元素都从栈中移除才行。

指令集

EVM的指令集被刻意保持在最小规模,以尽可能避免可能导致共识问题的错误。所有的指令都是针对256位这个基本的数据单位进行的操作,具备常用的算术、位、逻辑和比较操作,也可以进行条件和无条件跳转。此外,合约可以访问当前区块的相关属性,比如它的编号和时间戳。

消息调用

合约可以通过消息调用的方式来调用其他合约,或者发送以太币到非合约账户。消息调用和交易非常类似,它们都有一个源,一个目标,数据负载,以太币,Gas和返回数据。事实上每个交易都可以被认为是一个顶层消息调用,这个消息调用会依次产生更多的消息调用。

一个合约可以决定剩余Gas的分配。比如内部消息调用时使用多少Gas,或者期望保留多少Gas。如果在内部消息调用时发生了out-of-gas异常或者其他异常,合约将会得到通知,一个错误码被压入栈中。这种情况只是内部消息调用的Gas耗尽。在solidity中,这种情况下发起调用的合约默认会触发一个人工异常,这个异常会打印出调用栈。

就像之前说过的,被调用的合约(发起调用的合约也一样)会拥有崭新的主存,并能够访问调用的负载。调用负载被存储在一个单独的被称为calldata的区域。调用执行结束后,返回数据将被存放在调用方预先分配好的一块内存中。调用层数被限制为1024。因此对于更加复杂的操作,我们应该使用循环而不是递归。

代码调用和库

以太坊中存在一种特殊类型的消息调用,被称为callcode。它跟消息调用几乎完全一样,只是加载来自目标地址的代码将在发起调用的合约上下文中运行。这意味着一个合约可以在运行时从另外一个地址动态加载代码。存储,当前地址和余额都指向发起调用的合约,只有代码是从被调用地址获取的。这使得Solidity可以实现“库”。可复用的库代码可以应用在一个合约的存储上,可以用来实现复杂的数据结构,从而使智能合约更加的强大。

以太坊的状态转换

以太坊的状态转换是指在一个交易发生时,以太坊从一个正确状态S转变到下一个正确状态S的转换过程。
这里写图片描述

状态转换函数APPLY(S,TX)>S的具体过程:
1. 检查交易的格式是否正确,签名是否有效,以及随机数是否与发送者账户的随机数匹配。如否,返回错误。
2. 计算交易费用fee=STARTGASGASPRICE,并从签名中确定发送者的地址。从发送者的账户中减去交易费用和增加发送者的随机数。如果账户余额不足,返回错误。
3. 设定初值Gas=STARTGAS,并根据交易中的字节数减去一定量的燃料值。
4. 从发送者的账户转移价值到接收者的账户。如接收账户不存在,创建此账户。如果接收账户是一个合约,运行合约的代码,直到代码运行结束或者燃料用完。
5. 如果因为发送者账户没有足够的费用或者代码执行耗尽燃料导致价值转移失败,恢复原来的状态,但是还需要支付交易费用,交易费用加至矿工账户。
6. 若代码执行成功,将所有剩余的燃料归还给发送者,消耗掉的燃料作为交易费用发送给矿工。

以太坊客户端

目前主要有5中语言编写的以太坊客户端,分别是:

  • Go语言实现的客户端Geth
  • C++实现的客户端Eth
  • Python实现的客户端Pyethapp
  • Java实现的客户端EthereumJ。
  • Rust实现的客户端Parity。

源码:https://github.com/ethereum

以太坊智能合约

智能合约

区块链可以为智能合约提供可信的执行环境,以太坊实现了区块链和智能合约的完整契合。以太坊是内置有图灵完备编程语言的区块链,通过建立抽象的基础层,使得任何人都能够创建合约和去中心化应用,并在其中设立他们自由定义的所有权规则、交易方式和状态转换函数。建立一个代币的主体框架只需要两行代码就可以实现,诸如货币和信誉系统等其他协议只需要不到20行代码就可以实现。智能合约就像能在以太坊的平台上创建的包含价值而且只有满足某些条件才能打开的加密箱子,并且因为图灵完备性、价值意识(value-awareness)、区块链意识(blockchain-awareness)和记录多状态所增加的功能而比比特币脚本所能提供的智能合约强大得多。

开发语言

以太坊有4种专用语言:Serpent(受python启发)、Solidity(受JavaScript启发)、Mutan(受Go启发)和LLL(受Lisp启发)。这里不详述。

代码执行

以太坊合约的代码是使用低级的基于堆栈的字节码的语言写成的,被称为“以太坊虚拟机代码”(“EVM代码”)。这里不详述。

DApp

DApp是由智能合约和客户端代码构成。智能合约只有当特定条件被满足时它才被打开,它封装了一些逻辑、规则、处理步骤或者双方间的协议。

区块链架构简述

对于区块链架构,有人将区块链分成了1.0、2.0、3.0,这里对这个进行简单概述。

区块链1.0架构

区块链1.0的典型就是比特币。比特币架构图如下所示:
这里写图片描述

简单说明:
钱包——钱包保存用户的私钥数据库,管理用户余额,提供比特币交易功能。
区块链管理——涉及初始区块链下载、连接区块、断开区块、校验区块、保存区块以及发现最长链条的顶区块。
内存池管理——比特币内存池管理也就是交易池管理。节点将通过验证的交易放在一个交易池中,准备放在一个挖到的区块中。当矿工挖到一个合格的区块后,他将按一定的优先级次序从交易池中选出交易放到区块中。当区块填满后,剩下的交易会留在内存池,等待下一个区块的到来。
邻节点管理——下面有一小节单独说明邻节点管理。
密码模块——主要是处理比特币地址,采用RIMEMD和SHA-256算法以及Base-58编码来生成比特币地址。
这里写图片描述

节点管理

当一个新比特币节点做初始启动(bootstrap)的时候,它需要发现网络中的其他节点,并与至少一个节点连接。一般是与一个已知的节点在8333端口建立TCP连接。连接的“握手”流程发送一个版本信息,包括:P2P协议版本,本节点支持的服务,当前时间,对方节点IP地址,本节点IP地址,比特币软件版本,以及本节点当前区块链长度。对方节点收到握手信息后会回复一个收到确认的消息。

新节点如何发现邻节点?
第一个方法是用一些“DNS种子”查询DNS。“DNS种子”是提供比特币节点地址的DNS服务器。比特币核心带有5个不同的”DNS种子“。DNS种子可提供稳定的比特币节点地址。
第二个方法是直接把一个已知的邻节点作为种子节点,然后通过它发现更多的邻节点。当发现新的邻节点后,新节点一般将断开和种子节点的连接。新节点将其地址信息发给邻节点,邻节点会继续将新节点的地址转发给它们的邻节点,这样新的节点会在网络上被其他节点知道,并保持其在网络上连接的畅通。新节点启动结束后,会记住最近连上的邻节点的地址。当它重新启动的时候,就能很快地完成完成和已知邻节点的连接。如果一个节点和邻节点的连接在90分钟里没有联系,该邻节点会被认为下线,节点会寻找一个新的邻节点来进行连接。因此,无需中心控制,网络节点可以自由加入或离开网络,比特币网络能动态地调节节点的连接,以保证比特币网络的正常运行。

P2P网络管理

P2P网络管理的代码主要是在P2P网络上实现和其他邻节点的通信功能。包括:发现邻节点;连接并管理与邻节点的Socket连接;与邻节点交换不同的P2P消息。比特币节点的缺省配置是主动连接8个邻节点,同时允许最多125个其他节点发起连接请求。

ZMQ队列管理

比特币采用Zero MQ作为消息队列管理和消息分发工具。ZMQ是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。与其他消息中间件相比,ZMQ并不像是一个传统意义上的消息队列服务器,事实上,它也根本不是一个服务器,它更像是一个底层的网络通讯库,在Socket API之上做了一层封装,将网络通讯、进程通讯和线程通讯抽象为统一的API接口。

区块链2.0架构

区块链2.0典型就是以太坊。以太坊架构图如下所示:

这里写图片描述

简单描述:

EVM高级语言

以太坊提供高级语言让用户编写智能合约。以太坊的高级语言最后会编译成在EVM中执行的EVM字节码,部署在以太坊区块链上。

Whisper协议

Whisper协议是DApp间通信的通信协议。Whisper是为需要大规模的多对多数据发现、信号谈判和最少的传输通信、完全的隐私保护的下一代DApp而设计的。

事件

以太坊中的事件是一个以太坊日志和事件监测的协议的抽象。

区块链3.0架构

目前业界还没有一个成熟的区块链3.0平台。下面是区块链3.0的一种可能的架构。

这里写图片描述

补充概念

DAO

Decentralized Autonomous Organization,DAO去中心化自治组织。

原创粉丝点击