以太坊简介
1、简介
以太坊是一个可编程的区块链,内置了一个完全成熟的图灵完备
的程序语言,可以用这个语言来创建“合约”,使得用户可以创建属于他们自己的任意复杂的操作(比特币只能交易),以太坊作为一个平台为不同的区块链应用提供服务。
狭义来说,以太坊是一系列协议,其核心就是一个以太坊虚拟机,能执行遵守协议的任何复杂的代码。以太坊虚拟机是图灵完备的,开发者可以在虚拟机上使用像 javascript,python 这样的友好的编程语言来创建应用。
以太坊的目的是创建一种去中心化应用的协议,提供一套对大量的去中心化应用程序非常有用的新方案,特别强调快速开发,对小的和少数人使用的应用也非常安全(小而使用人少的应用容易被51%攻破),以及不同的应用程序之间能够有效的互动。
以太坊通过建立在本质上是抽象的基础层来完成这一工作:
一个区块链其内置了图灵完备的编程语言,允许任何人编写智能合约和去中心化的应用程序,在这些应用程序中,他们可以创建任意的属于他们自己的规则、交易格式和状态转换函数。名字币的一个简单版本在以太坊可以用两行代码来编写完成,而其他协议如货币和信用系统则可以用不到 20 行的代码来构建。
和任何的区块链一样,以太坊包含了一个点对点的网络协议。以太坊区块链是被链接着这个网络的各个节点维护和更新的,网络中的各个节点的虚拟机都执行相同的指令来共同维护区块数据库,因为这个原因,以太坊有时候被人称为“世界计算机”。
我们可以把区块链理解为是全球共享的分布式事务性数据库,以太坊全网的大规模并行计算不是只为了提计算效率,而是为了保证全网的数据一致性。实际上,这使得在以太网上的 运算要比传统的电脑慢的多,成本也昂贵得多,全网中的每一台虚拟机的运行
都是为确保全网数据库的一致性。
2、以太坊账户
以太坊的基本单元是账号,每一个账户都有一个 20 个字节长度的地址 。以太坊区块链跟踪每一个账号的状态,区块链上所有状态的转移都是账户之间的令牌(令牌即以太币)和信息的转移
以太坊有 2 种账户类型:
- 外部账号:简称 EOA,是由私钥来控制的;
- 合约帐户:由合约代码来控制,且只能由一个 EOA 账号来操作;
对于大多数用户来说,最基本的区别在于:
-
用户掌握着 EOA 账号,因为用户掌握着控制 EOA 账号的私钥;
-
合约账号由内部程序代码来控制的,当然掌控私钥的 EOA 账户可以通过编写特定的程序代码来掌控合约账户。
合约账户只有在 EOA 账户发出一个指令的时候才会去执行一个操作。所以一个合约账户是不可能自己去执行一个操作的,如生产一个随机数或执行一个 API 调用等,它只有在 EOA 账户作出确认的情况下才会去做这些事情。这是因为以太坊要求节点能够对计算的结果无论对错都达成一致,这就对操作有了一个必定会执行的要求
一个以太坊的账户包含下面 4 个字段:
- 随机数, 一个计数器,用以确保每个交易都只会被处理一次
- 账户当前的以太币额度
- 账户的合约代码, 如果有的话
- 这个账户的 存储 (默认空)
“以太币” 是以太坊主要的内部加密燃料,并且被用来支付交易的费用。
3、交易
“交易”,在以太坊中是指签名的数据包,这个数据包中存储了从外部账户发送的消息;
交易包含以下内容:
- 消息的接收者
- 一个可以识别发送者的签名
- 发送方给接收方的以太币的数量
- 一个可选的数据字段
- 一个 STARTGAS 值, 表示执行这个交易允许消耗的最大计算步骤
- 一个 GASPRICE 值, 表示发送方的每个计算步骤的费用
前面三个是每一个加密货币都有的标准字段。
默认情况下第四个数据字段没有任何功能,但是合约可以访问这里的数据;
举个例子,如果一个合约是在一个区块链上提供域名注册服务的,那么它就会想把这数据字段中的数据解析成 2 个字段,第一个字段是域名,第二个字段是域名对应的 IP 地址。这个合约会从数据字段中读取这些值,然后适当把它们保存下来
STARTGAS 和 GASPRICE 字段 是以太坊的预防拒绝式攻击用的,非常重要。为了防止在代码中出现意外或敌对的无限循环或其他计算浪费,每个交易都需要设置一个限制,以限制它的计算总步
骤是一个明确的值。这计算的基本单位是“汽油(gas)”; 通常,一个计算成本是一个 1 滴汽油,但是一些操作需要消耗更多的汽油,因为它们的计算成本更高。在交易数据中每一个字节需要
消耗 5 滴汽油。这样做的目的是为了让攻击者为他们所消耗的每一种资源,包括计算,带宽和存储支付费用;所以消耗网络资源越多,则交易成本就越大。
4、消息
合约有能力向其他合约发生“消息”。消息是虚拟的对象,它从来不会被序列化,而且只存在于以太坊的执行环境中。
一个消息包含以下内容:
- 消息的发送者 (隐式)
- 消息的接收者
- 与消息一起传送的以太币的数量
- 一个可选的数据字段
- 一个 STARTGAS 值
从本质上说,一个消息就像一个交易, 只是它是由一个合约产生的而不是一个外部用户。
一个正在执行代码的合约,当执行到 CALL 代码时,会产生并执行一个消息。就像一个交易,一个消息会导致接收方的账户运行它的代码。因此,合约之间是可以互相发生作用的。
5、以太坊状态转移函数(交易过程)
image.png以太坊的状态转移函数 APPLY(S,TX) -> S' 可以被定义成下面的:
- 检查这个交易是不是合法的,签名是不是合法的,这随机数是不是匹配这个发送者的账户,
如果答案是否定的,那返回错误。
- 检查这个交易是不是合法的,签名是不是合法的,这随机数是不是匹配这个发送者的账户,
- 用 STARTGAS * GASPRICE 计算交易的费用,并且从签名中确定这个发送者的地址。 从发送者的余额中减去费用,并且增加发送者的随机值。如果余额不够,则返回错误。
- 初始化 GAS = STARTGAS, 并根据这交易中的字节数拿走一定量的汽油。
- 把交易的值从发送的账户转移到接收者的账户。如果接收者的账户还不存在,就创建一个。
如果这个接收者的账户是一个合约,那么就运行合约的代码直到完成,或者报汽油消耗光的异常。
- 把交易的值从发送的账户转移到接收者的账户。如果接收者的账户还不存在,就创建一个。
- 如果值转移失败了,因为发送者没有足够多的余额,或代码执行消耗光了汽油,恢复除了支付的费用外的所有的状态,并且把这个费用添加到矿工的账户上。
- 另外,把所有剩下的汽油退还给发送者,然后把用于支付费用的汽油发送给矿工。
举例,假设合约的代码是这样的:
if !self.storage[calldataload(0)]:
self.storage[calldataload(0)] = calldataload(32)
注意,真实的合约代码是用底层的 EVM 代码编写的;这个列子是用一个叫 Serpent 的高级语言写的。假设这个合约的存储开始是空的,并且发送了一个交易,其中包含 10 个以太币,2000 个汽
油,汽油价格是 0.001 比特币,和 64 字节的数据,其中 0-31 字节代表数字 2,32-63 字节代表字符串 CHARLIE。在这个案例中,这状态转移函数的处理如下:
-
检查者交易是否有效并且格式完好;
-
检查者交易的发送者是否至少有 2000 * 0.001 = 2 以太币。如果有,则从发送者的账户中减去 2 以太币;
-
初始化 汽油(gas)= 2000;
假设这个交易是 170 个字节长度并且每个字节的费用是 5,那么减去 850,汽油还剩 1150; -
从发送者的账户减去 10 个以太币,并且添加到合约的账户中;
-
运行合约的代码;
在这里例子中,检查合约的存储的第 2 个索引是否已经被使用,注意到它没有,然后就把这数据存储的第二个索引的值设置为 CHARLIE;假设这个操作消耗了 187 个汽油,那么剩下的汽油总量是 1150 – 187 = 963; -
把 963 * 0.001 = 0.963 以太币加到发送者的账户,然后反正结果状态。
如果交易的接收端没有合约,那么这总的交易费用就简单的等于汽油的价格乘以这个交易的字节长度,与交易一起发送的数据字段的数据将无关重要。
注意,在恢复这个方面,消息和交易的处理方式是相同的: 如果一个消息执行消耗光了汽油,那么这消息的执行和其他被触发的执行都会被恢复,但是父类的执行不会恢复。
6、代码执行
以太坊的合约代码是用底层的基于堆栈的字节码语言来编写的,被称为 “以太坊虚拟机代码” or “EVM 代码”。这代码有一系列的字节组成,其中每一个字节都标识一个操作。在一般情况下,代码的执行是一个无限循环,直到代码运行结束或遇到错误,或检测到 STOP 或 RETURN 指令。
这些操作有三种类型的空间可用于存储数据:
- 堆栈, 一种后进先出的容器
- 内存,一种无线扩展的字节数组
- 合约的持久化存储, 一种键值对的方式,
堆栈和内存计算结束后将会被重置,存储将长期保存。
代码还可以访问 值(以太币)、发送者、传入的消息的数据,以及区块的头信息,并且也可以返回一组字节数组当做输出
7、区块链和挖矿
image.png以太坊的区块链和比特币的区块链有很多相似的地方,也有很多不同的地方。
以太坊和比特币在区块链体系中最重要的不同点是 :
以太坊的区块同时包含了交易列表和最近区块的状态,
除此之外,2 个其他的值,区块的编号和难度值也存在在区块中。
以太坊中最基本的区块验证算法如下:
- 检查上一个区块是否存在和其有效性。
- 检测这区块的时间戳,是不是比上一个区块的大,并且小于 15 分钟
- 检查这区块编号,难度值,交易根(transaction root) , 叔根(uncle root)和汽油限制是否有效
- 检查这区块的工作证明是否有效
- 把 S[0] 设置成上一个区块的末端的状态
- 让 TX 成为这区块的交易列表,如果有 n 个交易,则做 for 循环 For i in 0...n-1, 设置S[i+1] = APPLY(S[i],TX[i]). 如果任何一个应用发生错误,或这区块中汽油的总的消耗达到了 GASLIMIT,则返回一个错误
- 让 S_FINAL 等于 S[n], 但是把支付给矿工的奖励添加到这区块里。
- 检查这个状态 S_FINAL 的默克尔树树根是不是和区块头信息中所提供的状态根是一样的。如果是,则区块有效,不然则无效
乍看上去,这种方法似乎效率很低,因为它需要将整个状态存储在每个块中,但在现实中,效率应该与比特币相当。原因在于,状态存储在树结构中,并且每个块后,只需要修改树的一小部分。此外,由于所有的状态信息都是最后一个区块的一部分,所以不需要存储整个区块链的历史——这一策略,如果它可以应用于比特币,那么它的磁盘空间将节省 5-20 倍
以太坊网络中交易会被验证这网络的节点收集起来。这些“矿工”在以太坊网络中收集、传播、验
证和执行交易,然后整理归档这些交易,打包成一个区块,与别的矿工竞争将区块添加到区块链
中,添加成功的矿工将收到奖励。通过这样的措施,鼓励人们为区块链全网提供更多的硬件和电力
支持。
8、应用
以太坊框架本身并没有什么特别的功能。就好像 程序语言一样,它做什么,都是由企业或开发者自己来决定的,如复杂的金融合约的自动化。
比特币可以让用户不通过第三方机构,如银行,政府等就可以直接兑换货币。但是以太坊的介入可能会产生更加深远的影响,因为任何复杂的金融操作都是可以自动被执行的,并且可以写成代码在以太坊上运行。当然除了金融外,任何情况下,只要对信用、安全、和持久有极高的要求,比如资产注册登记,投票,管理和物联网等都有可能受到以太坊平台的影响。
一般来说,在以太坊上有三种类型的应用。第一种是金融应用,这包括 子货币,金融衍生品,套期保值合约,和一些雇佣合同等;第二类是半金融应用,这里有钱的存在但也有很重的非金钱的方
面;
最后,还有在线投票和去中心化治理这样的完全的非金融应用