区块链入门 -- 01 区块链介绍

一、比特币的现有概念介绍



1、历史


        去中心化的货币概念,像产权登记等已经存在了几十年了。上世纪80年代和90年代的匿名电子现金协议主要使用了一种被称为“乔姆盲签(Chaumian Blinding)”的加密技术,这种技术为这些新货币提供了很高的隐私保护,但是由于他们的基础协议在很大程序上需要依赖一个中央中介,因为未能获得支持。1988年,戴伟(Dai Wei)的b-money首次引入了通过解决计算难题和去中心化的共识来创造货币的思想,但是该建议并未给出实现去中心化的共识的具体方法。2005年,芬妮(Hal Finney)引入了“可重复的工作证明”(reusable proofs of works)概念,它同时使用b-money的思想和Adam Back提出的计算困难的哈希现金(Hashcash)难题来创造密码学货币。但是,这种概念再次迷失于理想化,因为它需要可信任的计算作为后盾。在2009年,一种去中心化的货币由中本聪在实践中首次得到实现,通过使用公共密钥密码来管理所有权,并通过一种一致性算法来跟踪货币的持有者,这种算法被称为“工作证明”。这“工作证明”的算法是一种突破,因为它同时解决了两个问题。首先,它提供了一种简单的、有节制的有效的共识算法,允许网络中的节点一起同意比特币总账状态的一组更新。其次,它提供了一种机制,允许任何节点自由进入共识的处理过程,从而解决了谁来影响共识的政治难题,同时阻止了女巫攻击。这参与共识投票的节点的投票权比重是直接和节点它们自己的算力挂钩的。从那时候起,一个新的方案被提出,称之为“权益证明”,计算一个节点的权重,与它拥有的货币占比成比例,而不是计算资源。这两种方法都可以作为加密货币的支柱。


2、比特币一个状态转移系统




         从技术角度来说,这加密货币的账本,如比特币可以被看作为一个状体转移的系统,在这个系统里,有一个包含了所有现在已存在的比特币的持有者的状态,并且有一个“状态转移函数”可以使用一个状态和一个交易来产生一个新的状态。在一个标准的银行体系里,这状态就是一个资产负债表,当一个交易要求把 x$ 的钱,从A转移到B时,那么它的状态转移函数就会从A的账户中减去数量为 x$ 的金额,然后在B的账户中增加数量为 x$ 的金额。如果A的账户没有 x$ 的钱,那么状态转移函数就会返回一个错误。所以,我们可以做如下定义:


//使用一个状态和一个交易才产生一个新的状态,或者返回错误

APPLY(S,TX)  -->  S'  OR  ERROR

//在银行系统中,它可以定义成这样

APPLY({ Alice : $50, Bob : $50}, "send $20 from Alice to Bob") = {Alice : $30, Bob : $70}
或者
APPLY({ Alice : $50, Bob : $50}, "send $70 from Alice to Bob") = ERROR

        这“状态”,在比特币中是指所有的已经被挖出的但是还没有被消费的硬币的集合(技术上被称为:“没有被花费的交易产出(unspent  transaction  out  puts)”或者“UTXO”),每个UTXO都有一个面值和一个持有者(持有者是由20个字节组成的地址,其本质是一个加密的公钥)。一个交易包含了一个或者多个输入,每一个输入都包含了对一个已存在的UTXO的引用,和用持有者的地址所关联着的私钥来产生的一个加密签名,并且会产生一个或者多个输出,每一个输出包含一个用于添加到状态的新的UTXO。


这状态转移函数 APPLY(S, TX)  -->  S'  可以被大概的定义如下:


1.在TX中的每个输入:
	如果被应用的UTXO不再 S 里,返回一个错误
	如果提供的签名和UTXO的所有者匹配不上,返回一个错误

2.如果所有的输入的UTXO的面值和少于所有输出的UTXO的面值和,返回一个错误

3.返回一个所有输入的UTXO都被移除的,所有输出的UTXO都被加进的新的 S'


        第一个步骤的前半部分防止交易的发送方消费不存在的硬币,第一个步骤的后半部分阻止了交易的发送方使用别人的硬币,第二个步骤是强制的价值保护。为了使用这种支付方式,协议如下:


假设:
    Alice 想发送 11.7 BTC 给 Bob. 首先, Alice 要找到一组她自己拥有的有效的 UTXO ,且总数要至
少不低于 11.7 BTC. 实际上, Alice 不会恰巧刚好拥有 11.7 BTC; 她得到的最小值是 6+4+2=12,
她然后使用这 3 个输入和 2 个输出创建了一个交易。 这第一个输出是 11.7 BTC ,是输出 Bob,第
二个输出是剩下的 0.3 BTC “找零”。如果 Alice 没有要求把这个找零发送到她自己的账户上,
那么这矿工可以要求拥有这个零钱(即通常被成为的小费)。


3、挖矿




        如果我们有一个可信任的中央服务器, 那么实现这个系统是一件很简单的事情。就按照需求所描述的去编写代码即可,把状态记录在中央服务器的硬盘上。 然而,与比特币一样,我们试图去建立一个去中心化的货币系统,所以,我们需要把状态转移系统和一致性系统结合起来,以确保每个人都同意这交易的顺序。比特币的去中心化的一致性处理进程要求网络中的节点连续不断的去尝试对交易进行打包,这些被打成的包就称为“区块”。 这个网络会故意的每隔 10 分钟左右就创建一个区块, 每一个区块里都包含一个时间戳,一个随机数,一个对上一个区块的引用 ,和从上一个区块开始的所有交易的列表。随着时间的推移,这会创建一个持久的,不断增长的区块链,这个区块链不断的被更新,使其始终代表着最新的比特币总账的状态。


在这个范例中,用来验证一个区块是否有效的算法如下:


1. 检查其引用的上一个区块是否存在并且有效.

2. 检查这个区块的时间戳是否大于上一个区块的时间戳 并且小于 2 小时之内

3. 检查这区块上的工作证明是否有效.

4. 让 S[0] 成为上一个区块的最末端的状态.

5. 假设 TX 是这个区块的交易列表,且有 n 个交易。 做 for 循环,把 i 从 0 加到到 n-1, 
   设置 S[i+1] = APPLY(S[i],TX[i]) 如果任何一个应用(APPLY)返回错误,则退出并且返回。

6. 返回 true,并且把 S[n] 设置成这个区块最末端的状态。


        从本质上说,区块中的每一个交易都必须提供一个有效的状态,从交易执行前的标准状态到执行后的一个新的状态。 注意,状态并没有以任何方式编码进区块中;它纯粹是一个被验证节点所记住的抽象,并且它只能用来被从创世区块起的每一个区块进行安全的计算,然后按照顺序的应用在每一个区块中的每一次交易中。此外,请注意矿工把交易打包进区块的顺序是很重要的,如果一个区块中有 2 个交易 A 和 B,B 花了一个由 A 创建的 UTXO, 那么如果 A 比 B 更早的进入区块,那么这个区块将是有效的,不然就是无效的。


        在上述列出的验证条件中,“工作证明” 这一明确的条件就是每一个区块的 2 次 SHA256 哈希值,它作为一个 256 位的数字,必须小于一个动态调整的目标值,截止到本文写作的时间,该动态调整的值的大小大约是 2 的 187 次方。 这样做的目的是为了让创建区块的算法变难,从而阻止幽灵攻击者从对它们有利的角度来对区块链进行整个的改造。因为 SHA256 被设计成一个完全不可预测的伪随机函数,这创建一个有效区块的唯一的方法只有是不断的尝试和出错, 不断对随机数进行递增,然后查看新的哈希值是否匹配。


        按照当前的目标值 2 的 187 次方,这个网络在找到一个有效的区块前,必须进行 2 的 69 次方次的尝试。一般来说,每隔 2016 个区块,这个目标值就会被网络调整一次 ,因此网络中平均每隔 10 分钟就会有一些节点产生出一个新的区块。为了补偿这些矿工的计算工作,每一个区块的矿工有权要求包含一笔发给他们自己的 12.5BTC(不知道从哪来的)的交易。另外,如果任何交易,它的总的输入的面值比总的输出要高,这一差额会作为“交易费用”转给矿工。顺便提一下,对矿工的奖励是比特币发行的唯一途径,创世状态中并没有比特币。


        为了更好的理解挖矿的目的,让我们来检测一下,当恶意攻击发生时会发生什么。 由于比特币的底层的加密技术众所周知是安全的,所以这攻击者的目标将是比特币系统中的某个部份,那就是没有被密码直接保护的:交易的次序。攻击者的策略其实很简单:


1. 发送 100 BTC 到一个商人,以兑换一些商品 (最好是快速交易的数字商品)

2. 等待商品的发货

3. 创建另一个交易,发送同样的 100 BTC 给自己

4. 尝试让网络相信他发给他自己的那个交易是最新出现的。


        一旦步骤 1发生,几分钟后,一些矿工就会把这个交易打包进一个区块,假设声明该区块编号是270000。大约一个小时后, 在那个区块之后又会有新增的五个区块添加到区块链中,这五个区块都间接的指向了那个交易,从而“确认”了那交易是真的。在这一刻,商家接收到了货款,并且发出了商品。因为我们假设是一个数字商品,所以攻击者能立刻就收到货。现在攻击者创建另一个交易,向他自己的另一个账户发送这 100 BTC 。如果这个攻击者只是简单的释放了这个交易,那么这个交易将不会被执行。矿工将会尝试运行 APPLY(S,TX) ,注意那个 TX 消耗一个在以太坊状态中已经不存在的 UTXO。因此,这个攻击者创建了一个比特币区块链的“分支” , 开始挖取区块 270000的另一个版本,这个版本指向同样的区块 269999 作为一个父亲,但是用这新的交易替换了旧的。因为这区块的数据是不同的 , 这就需要为相关的区块重新做工作证明。 此外,这个攻击者的新的版本的区块 270000 有一个不同的哈希,所以这已存在的区块 270001 到 270005 不会指向它。因此,这原来的链和这攻击者的新链是完全独立的。区块链的规则是:在分支中最长的区块链链将会变成真正的链。所以合法的矿工将会继续在 270005 这条链上工作,同时攻击者自己一个人单独的工作在新版本的 270000 这条链上。为了让攻击者他自己的区块成为最长,他需要的计算能力比其他网络的总和还要多(“51%攻击”)。比特币的区块依赖之前所有区块的哈希。一个拥有巨大计算能力的攻击者可以重新设计工作的证明(PoW),并最终获得大量的比特币。


4、默克尔树(Merkle Trees)




在默克尔树中只要提供少数的几个节点就可以给出一个分支有效性的证明




试图改变默克尔树的任一部分都将会导致链条上在某处发生不一致的情况


        比特币的一个重要特性,这区块是存在一个多级数据结构中的 。一个区块的“哈希值”实际上只是这个区块的头信息的哈希值,一个大约 200 个字节的数据,其中包含了时间戳随机数上一个区块的哈希一个存储了这个区块中所有交易的称之为默克尔树的数据结构的根哈希。 默克尔树是一种二叉树,包含了一组节点,它们的含有基础信息的树根有大量的叶子节点,一组中间节点,每一个节点都是它的 2 个子节点的哈希,然后,最终的一个根节点,也是由它的 2 个子节点的哈希形成,代表着这树的“顶端”。 这个默克尔树的目的是允许在一个区块中的数据能够被零散的传递:一个节点只能从一个源来下载一个区块的头信息,树的一小部分关联着另一个源 ,并且仍然可以保证所有的数据都是正确的。之所以这样做行得通,是因为哈希值都是向上传导的:如果一个恶意的用户试图在默克尔树的底部替换一个假的交易,这个更改将导致上面的节点发生变化,然后上面的节点的变化又会导致上上面的节点发生变化,最终改变这个数根节点,因此也改变了这区块的哈希,导致这个协议把它注册成一个完全不同的区块 (几乎可以肯定是一个无效的工作证明)。


        这默克尔树协议对比特币的长期可持续发展是必不可少的。比特币网络中的一个“完整节点” , 截止到 2014 年,占用了大约 15G 的磁盘空间,并且每月正在以 10 亿字节的速度递增。目前,这对于电脑来说是没有问题的,但是在手机上却是不现实的。在以后的将来,只有商业的和业余爱好者才能参与玩比特币。一个称之为 “简化支付验证(simplified payment verification)” (SPV)的协议 允许另一种类型的节点存在,这种节点称之为 “轻节点(light nodes)”, 其下载区块的头信息,在这区块头信息上验证工作证明,然后只下载与之交易相关的“分支” 。 这使得轻节点只要下载整个区块链的一小部分,就可以安全地确定任何一笔比特币交易的状态和账户的当前余额。


5、山寨区块链应用


        将底层的区块链理念应用到其他概念上的想法也有很长的历史了。在 2005 年, 尼克萨博提出了这个概念 “用所有权保护产权(secure property titles with owner authority)”, 文档描述了“复制数据库的新技术”将如何使用一个基于区块链的系统来存储谁拥有土地的注册登记信息, 建立一个精心设计的框架,包括“宅地”,“逆权侵占”和 “地税”等概念。然而,不幸的是,那个时候没有一个有效的复制数据库信息,因此,协议从未付诸实践。然而,在 2009 年之后,比特币的去中心化的共识一被开发出来,许多山寨应用就迅速涌现出来。


        Namecoin – 创建于 2010 年,名字币是一个去中心化的名字注册数据库 。 在去中心化的协议中,像 Tor, Bitcoin 和 BitMessage, 这些需要有一些识别账号的方法,这样用户就可以和其他人进行交互了,但是现存在的所有的解决方案中,这个标识符都是一个伪随机的哈希字符串像 1LW79wp5ZBqaHW1jL5TCiBCrhQYtHagUWy。在理想情况下,人们一般都希望拥有一个像 “george” 这样的名字。然而,问题是如果一个用户可以创建一个名为 “george” 的账号的话, 那么其他人也可以使用相同的过程来为自己注册一个名为 “george” 的账号,并且冒充他们。唯一的解决方案只能是先申请原则,第一个人可以注册成功,其他人都注册失败 – 这是一个完全适用于比特币的共识协议的解决方案。域名币是利用区块链实现名称注册系统的最早的、最成功的系统。


        Colored coins – 彩色币的目的是为人们在比特币区块链上创建自己的数字货币,或者,其他一般意义上的货币 – 数字令牌提供服务。依照彩色币协议,人们可以通过为某一特别的比特币 UTXO 指定颜色,发行新的货币。该协议递归地将其它 UTXO 定义为与交易输入 UTXO 相同的颜色。这就允许用户保持只包含某一特定颜色的 UTXO,发送这些 UTXO 就像发送普通的比特币一样,但是需要通过回溯全部的区块链判断收到的 UTXO 颜色。


        Metacoins – 元币的理念是在比特币区块链上创建新的协议,利用比特币的交易保存元币的交易,但是采用了不同的状态转换函数 APPLY’。因为元币协议不能阻止比特币区块链上的无效的元币交易,所以增加一个规则如果 APPLY’(S,TX)返回错误,这一协议将默认APPLY’(S,TX) = S。这为创建任意的、先进的不能在比特币系统中实现的密码学货币协议提供了一个简单的解决方法,而且开发成本非常低,因为挖矿和网络的问题已经由比特币协议处理好了。


        因此,总得来说,有 2种构建共识的方法:一是构建一个独立的网络,二是在比特币之上建立一个协议。 前一种方法,在名字币这样的应用中相当的成功,但很难实现;每一个独立的实现都需要启动一个独立的区块链,以及构建和测试所有必要的状态转移函数和网络代码。此外,我们预测去中心化技术的应用会以指数级别的速度增长,绝大多数的应用会因为太小,而不能保护好它们自己的区块链,另外,我们还注意到存在大量去中心化的应用程序,特别是去中心化的自治组织,它们需要相互作用。


        基于比特币的方法,有一个缺陷,它没有继承比特币的简化支付验证(SPV)的功能。SPV 可以让比特币使用区块链的深度来做验证;在某种程度上,一旦一个交易已经离的足够远了,就可以放心地说,这个交易就是合法的状态的一部分。基于区块链的元协议,从另一方面说,不能强制区块链不包含用它们自己的协议验证无效的交易。因此,一个完全安全的 SPV 元协议的实现需要从比特币区块链的末端一直扫描到顶端,这样才能确定某些交易的合法性。


        目前,基于比特币的元协议的所有“轻”应用的实现都依赖于一个受信任的服务器来提供数据,这可以说是一个非常不理想的,尤其是当一个加密货币的需要消除信任的时候。


6、脚本


        即便是没有任何扩展,这比特币的协议实际上确实促进了一个弱化版的“智能合约”的概念。UTXO在比特币中不是只被一个公钥持有, 而是还被在一个基于堆栈的程序语言组成的复杂的脚本所持有着。 在这个范例中,一个交易消耗的 UTXO 必须提供满足脚本的数据。实际上,这最基本的公钥所有权机制也是通过一个脚本来实现的:这个脚本使用一个椭圆曲线签名作为一个输入,验证拥有这个 UTXO 的交易和地址,如果验证成功,则返回 1,不然则返回 0。其他,更加复杂的脚本存在于各种复杂的用例中。 例如,你可以构造一个脚本,它要求从给定的三个私钥中,至少要选其中的 2 个来做签名验证(“多重签名”),这个对公司账本,储蓄账户等来说非常有用。脚本也能用来对解决计算问题的用户支付报酬。人们甚至可以创建这样的脚本“如果你能够提供你已经发送一定数额的的狗币给我的简化确认支付证明,这一比特币就是你的了”,本质上,比特币系统允许不同的密码学货币进行去中心化的兑换。


然而,在比特币中的脚本语言有几个重要的限制:


    缺乏图灵- - 完备– 那就是说,虽然比特币脚本语言支持的计算方式很多,但是它不是所有的都支持。在主要类别中缺失循环。 
它这样做的目的是为了防止对交易的验证出现死循环;理论上,它的脚本是可以克服这个障碍的,因为任何的循环都可以通过 if 语句
重复多次底层代码来模拟,但是这样的脚本运行效率非常低下。

    值的盲区 – 一个 UTXO 脚本没有办法提供资金的颗粒度可控的出金操作。比如, 一个预言合约(oracle contract )的其中一个强大
的用例就是一个套期保值的合约,A 和 B 都把价值1000$的 BTC 放到合约中,30 天后,这个合约把价值 1000$的 BTC 发给了 A,剩下的发给了
B。 这就需要合约要确定 1BTC 以美元计值多少钱。然而,因为 UTXO 是不可分割的,为实现此合约,唯一的方法是非常低效地采用许多有不同面值
的 UTXO(例如有 2^k 的 UTXO,其中 K 可以最大到 30)并使预言合约挑出正确的 UTXO 发送给 A 和 B。

    状态缺失 – UTXO 要么被使用了,要么没有被使用;这会使得多阶段的合约和脚本没有机会保持任何其他的内部状态。这使得制作多阶段
的期权合约、去中心化的交换协议或两阶段加密承诺协议变得困难(对于安全计算奖金来说是必要的)。这也意味着,UTXO 只能用于构建简
单的、一次性的合约,而不是更复杂的“有状态”的合约,比如去中心化的组织,并且使得元协议难以实现。

    区块链盲区 -UTXO 对某些区块链数据视而不见,比如随机数和之前的区块的哈希。这严重限制了博彩和其他一些类别的应用,因为它剥夺
了一种潜在的有价值的脚本语言:随机数!也就是在比特币的脚本中是没有随机数的。


       因此,我们看到了在加密货币之上构建高级应用程序的三种方法:一,构建一个新的区块链,二,在比特币之上使用脚本,三,在比特币之上构建一个元协议。 构建一个新的区块链可以无限制扩展功能集,但是这样做非常消耗时间。使用脚本很容易实现和标准化,但在其功能上非常有限,而元协议虽然容易,但在可伸缩性方面却存在缺陷。在以太坊中,我们打算建立一个替代性的框架,它提供了更大的开发和更强大的轻客户属性,同时允许应用程序共享一个经济环境和区块链安全。



二、以太坊



1、以太坊


        以太坊的目的是创建一种去中心化应用的协议,提供一套对大量的去中心化应用程序非常有用的新方案,特别强调快速开发,对小的和少数人使用的应用也非常安全(小而使用人少的应用容易被51%攻破),以及不同的应用程序之间能够有效的互动。以太坊通过建立在本质上是抽象的基础层来完成这一工作:一个区块链其内置了图灵完备的编程语言,允许任何人编写智能合约和去中心化的应用程序,在这些应用程序中,他们可以创建任意的属于他们自己的规则、交易格式和状态转换函数。名字币的一个简单版本在以太坊可以用两行代码来编写完成,而其他协议如货币和信用系统则可以用不到 20 行的代码来构建。智能合约-包含价值而且只有满足某些条件才能打开的加密箱子-也能在我们的平台上构建,并且因为图灵完备性、价值知晓(value-awareness)、区块链知晓(blockchain-awareness)和多状态所增加的力量,远比特币脚本所能提供的功能强大得多。


2、以太坊虚拟机


        以太坊是一个可编程的区块链,不仅仅是给用户一些预定义操作(如比特币只交易),以太坊允许用户创建属于他们自己的复杂的操作。以太坊作为一个平台为不同的区块链应用提供服务。


        狭义来说,以太坊是一系列协议,其核心就是一个以太坊虚拟机,能执行遵守协议的任何复杂的代码。以太坊虚拟机是图灵完备的,开发者可以在虚拟机上使用像 javascript,python 这样的友好的编程语言来创建应用。


        和任何的区块链一样,以太坊包含了一个点对点的网络协议。这以太坊区块链是被链接着这个网络的各个节点维护和更新的。网络中的各个节点的虚拟机都执行相同的指令来共同维护区块数据库,因为这个原因,以太坊有时候被人称为“世界计算机”。


        以太坊全网的大规模并行计算不是只为了提计算效率,而是为了保证全网的数据一致性。实际上,这使得在以太网上的 运算要比传统的电脑慢的多,成本也昂贵得多。全网中的每一台虚拟机的运行都是为确保全网数据库的一致性。去中心化的一致性给全网极端的容错能力;抗审查能力和永不宕机能力等!


3、以太坊账户


        以太坊的基本单元是账号。每一个账户都有一个 20 个字节长度的地址 。以太坊区块链跟踪每一个账号的状态,区块链上所有状态的转移都是账户之间的令牌(令牌即以太币)和信息的转移。以太坊有 2 种账户类型:


        外部账号,简称 EOA,是由私钥来控制的。


        合约帐户,由合约代码来控制,且只能由一个 EOA 账号来操作。


        对于大多数用户来说,最基本的区别在于,用户掌握着 EOA 账号,因为用户掌握着控制 EOA 账号的私钥。而合约账号由内部程序代码来控制的,当然掌控私钥的 EOA 账户可以通过编写特定的程序代码来掌控合约账户。流行的术语“智能合约”就是合约账号中的代码,当一个交易被发送到该账户时,合约中的代码就会被执行。用户可以通过把代码部署到区块链中来创建一个新合约,也即创建了一个新的合约账户。


        合约账户只有在 EOA 账户发出一个指令的时候才会去执行一个操作。所以一个合约账户是不可能自己去执行一个操作的,如生产一个随机数或执行一个 API 调用等,它只有在 EOA 账户作出确认的情况下才会去做这些事情。这是因为以太坊要求节点能够对计算的结果无论对错都达成一致,这就对操作有了一个必定会执行的要求。


        在以太坊中,全网的状态是由被“账户”的对象组成的,账户之间可以直接的进行价值和信息的转移,一个以太坊的账户包含下面 4 个字段:


•  随机数, 一个计数器,用以确保每个交易都只会被处理一次

•  账户当前的 以太币额度

•  账户的 合约代码, 如果有的话

•  这个账户的  存储 (默认空)

        “以太币” 是以太坊主要的内部加密燃料,并且被用来支付交易的费用。一般情况下,有 2 种类型的账户:  外部拥有的账户,被私钥控制的,和 合约账户, 被合约代码控制的。外部拥有的账户没有代码,用户可以通过一个外部账户来创建和签名一个交易来送一个消息;合约账户中,每次当这个合约收到一个消息的时候,它的代码就会被激活,允许它读取这个消息,并且写入到内部存储中,然后按照一定顺序发送其他的消息或创建合约等。


4、消息和交易


名词“交易”在以太坊中是指签名的数据包,这个数据包中存储了从外部账户发送的消息,交易包含以下内容:


•  消息的接收者

•  一个可以识别发送者的签名

•  发送方给接收方的以太币的数量

•  一个可选的数据字段

•  一个 STARTGAS 值, 表示执行这个交易允许消耗的最大计算步骤

•  一个 GASPRICE 值, 表示发送方的每个计算步骤的费用


        前面三个是每一个加密货币都有的标准字段。默认情况下第四个数据字段没有任何功能,但是合约可以访问这里的数据;举个例子,如果一个合约是在一个区块链上提供域名注册服务的,那么它就会想把这数据字段中的数据解析成 2 个字段,第一个字段是域名,第二个字段是域名对应的 IP 地址。这个合约会从数据字段中读取这些值,然后适当把它们保存下来。


        这个 STARTGAS 和 GASPRICE 字段 是以太坊的预防拒绝式攻击用的,非常重要。为了防止在代码中出现意外或敌对的无限循环或其他计算浪费,每个交易都需要设置一个限制,以限制它的计算总步骤是一个明确的值。这计算的基本单位是“汽油(gas)”; 通常,一个计算成本是一个 1 滴汽油,但是一些操作需要消耗更多的汽油,因为它们的计算成本更高。在交易数据中每一个字节需要消耗 5 滴汽油。这样做的目的是为了让攻击者为他们所消耗的每一种资源,包括计算,带宽和存储支付费用;所以消耗网络资源越多,则交易成本就越大。


5、消息


        合约有能力向其他合约发生“消息”。消息是虚拟的对象,它从来不会被序列化,而且只存在于以太坊的执行环境中。一个消息包含以下内容:


•  消息的发送者 (隐式)

•  消息的接收者

•  与消息一起传送的以太币的数量

•  一个可选的数据字段

•  一个 STARTGAS 值


        从本质上说,一个消息就像一个交易, 只是它是由一个合约产生的而不是一个外部用户。一个正在执行代码的合约,当执行到 CALL 代码时,会产生并执行一个消息。就像一个交易,一个消息会导致接收方的账户运行它的代码。因此,合约之间是可以互相发生作用的。



6、以太坊状态转移函数




以太坊的状态转移函数 APPLY(S,TX) -> S' 可以被定义成下面的:


1. 检查这个交易是不是合法的 ,签名是不是合法的, 这随机数是不是匹配这个发送者的账户,如果答案是否定的,那返回错误。

2. 用 STARTGAS * GASPRICE 计算交易的费用,并且从签名中确定这个发送者的地址。 从发送者的余额中减去费用,并且增加发送者的随机值。
   如果余额不够,则返回错误。

3. 初始化 GAS = STARTGAS, 并根据这交易中的字节数拿走一定量的汽油。

4. 把交易的值从发送的账户转移到接收者的账户。如果接收者的账户还不存在,就创建一个。如果这个接收者的账户是一个合约,
   那么就运行合约的代码直到完成,或者报汽油消耗光的异常。

5. 如果值转移失败了,因为发送者没有足够多的余额,或代码执行消耗光了汽油,恢复除了支付的费用外的所有的状态,并且把这个费用添加到矿工的账户上。

6. 另外,把所有剩下的汽油退还给发送者,然后把用于支付费用的汽油发送给矿工。


举例,假设合约的代码是这样的:


if !self.storage[calldataload(0)]:
self.storage[calldataload(0)] = calldataload(32)


        注意:真实的合约代码是用底层的 EVM 代码编写的;上述这个例子是用一个叫 Serpent 的高级语言写的。


        假设这个合约的存储开始是空的,并且发送了一个交易,其中包含 10 个以太币,2000 个汽油,汽油价格是 0.001 比特币,和 64 字节的数据,其中 0-31 字节代表数字 2,32-63 字节代表字符串 CHARLIE。在这个案例中,这状态转移函数的处理如下:


1. 检查者交易是否有效并且格式完好。

2. 检查者交易的发送者是否至少有 2000 * 0.001 = 2 以太币。如果有,则从发送者的账户中减去 2 以太币。

3. 初始化 汽油(gas)= 2000;假设这个交易是 170 个字节长度并且每个字节的费用是 5,那么减去 850,汽油还剩 1150。

4. 从发送者的账户减去 10 个以太币,并且添加到合约的账户中。

5. 运行合约的代码. 在这里例子中:检查合约的存储的第 2 个索引是否已经被使用,注意到它没有,然后就把这数据存储的第二个索引的值
   设置为 CHARLIE. 假设这个操作消耗了 187 个汽油,那么剩下的汽油总量是 1150 – 187 = 963

6. 把 963 * 0.001 = 0.963 以太币加到发送者的账户,然后反正结果状态。


        如果交易的接收端没有合约,那么这总的交易费用就简单的等于汽油的价格乘以这个交易的字节长度,与交易一起发送的数据字段的数据将无关重要。


        注意,在恢复这个方面,消息和交易的处理方式是相同的: 如果一个消息执行消耗光了汽油,那么这消息的执行和其他被触发的执行都会被恢复,但是父类的执行不会恢复。


7、代码执行


        以太坊的合约代码是用底层的基于堆栈的字节码语言来编写的,被称为 “以太坊虚拟机代码” or“EVM 代码”。这代码有一系列的字节组成,其中每一个字节都标识一个操作。在一般情况下,代码的执行是一个无限循环,直到代码运行结束或遇到错误,或检测到 STOP 或 RETURN 指令。这些操作有三种类型的空间可用于存储数据:


•  堆栈, 一种后进先出的容器

•  内存, 一种无线扩展的字节数组

•  合约的持久化  存储, 一种键值对的方式. 不像堆栈和内存,计算结束后将会被重置, 存储将长期保存。

        代码还可以访问值(以太币),发送者,传入的消息的数据,以及区块的头信息,并且也可以返回一组字节数组当做输出。


8、区块链和挖矿




        这以太坊的区块链和比特币的区块链有很多相似的地方,也有很多不同的地方。这个以太坊和比特币在区块链体系中最重要的不同点是 :以太坊的区块同时包含了交易列表和最近区块的状态。除此之外,2 个其他的值,区块的编号和难度值也存在在区块中。以太坊中最基本的区块验证算法如下:


1. 检查上一个区块是否存在和其有效性。

2. 检测这区块的时间戳,是不是比上一个区块的大,并且小于 15 分钟

3. 检查这区块编号,难度值,交易根(transaction root) , 叔根(uncle root)和汽油限制是否有效

4. 检查这区块的工作证明是否有效

5. 把 S[0] 设置成上一个区块的末端的状态

6. 让 TX 成为这区块的交易列表,如果有 n 个交易。则做 for 循环 For i in 0...n-1, 设置S[i+1] = APPLY(S[i],TX[i])。
   如果任何一个应用发生错误,或这区块中汽油的总的消耗达到了 GASLIMIT, 则返回一个错误。

7. 让 S_FINAL 等于 S[n], 但是把支付给矿工的奖励添加到这区块里。

8. 检查这个状态 S_FINAL 的默克尔树树根是不是和区块头信息中所提供的状态根是一样的。如果是,则区块有效,不然则无效。

        乍看上去,这种方法似乎效率很低,因为它需要将整个状态存储在每个块中,但在现实中,效率应该与比特币相当。原因在于,状态存储在树结构中,并且每个块后,只需要修改树的一小部分。此外,由于所有的状态信息都是最后一个区块的一部分,所以不需要存储整个区块链的历史——这一策略,如果它可以应用于比特币,那么它的磁盘空间将节省 5-20 倍。


        以太坊网络中交易会被验证这网络的节点收集起来。这些“矿工”在以太坊网络中收集、传播、验证和执行交易,然后整理归档这些交易,打包成一个区块,与别的矿工竞争将区块添加到区块链中,添加成功的矿工将收到奖励。通过这样的措施,鼓励人们为区块链全网提供更多的硬件和电力支持。


三、应用


1、应用

        以太坊框架本身并没有什么特别的功能。就好像 程序语言一样,它做什么,都是由企业或开发者自己来决定的。如,复杂的金融合约的自动化。比特币可以让用户不通过第三方机构,如银行,政府等就可以直接兑换货币。但是以太坊的介入可能会产生更加深远的影响,因为任何复杂的金融操作都是可以自动被执行的,并且可以写成代码在以太坊上运行。当然除了金融外,任何情况下,只要对信用、安全、和持久有极高的要求,比如资产注册登记,投票,管理和物联网等都有可能受到以太坊平台的影响。


        一般来说,在以太坊上有三种类型的应用。第一种是金融应用,这包括 子货币,金融衍生品,套期保值合约,和一些雇佣合同等。第二类是半金融应用,这里有钱的存在但也有很重的非金钱的方面;最后,还有在线投票和去中心化治理这样的完全的非金融应用。


2、参考资料



以太坊官网网站:https://ethereum.org/


区块链信息查看:https://etherchain.org


去中心化的应用:https://dapps.ethercasts.com/


以太坊白皮书原文: https://github.com/ethereum/wiki/wiki/White-Paper

猜你喜欢

转载自blog.csdn.net/wingzhezhe/article/details/79529024