文件名称:
Solidity官方文档中文版.pdf
开发工具:
文件大小: 1mb
下载次数: 0
上传时间: 2019-09-03
详细说明:Solidity 是一种语法类似 JavaScript 的高级语言。它被设计成以编译的方式生成以太坊虚拟机代码。在后续内容中你将会发现,使用它很容易创建用于投票、众筹、封闭拍卖、多重签名钱包等等的合约。汇智网 Hu biz. com
Solidity官方文档中文版
Browser-Based Compiler Changelog
Story Backlog.
Source code
Gitter Chat
Solidity文档
在下一章中,我们先看一个用 Solidity写的简单的智能合约,然后介绍一区块链和以太
坊虚拟机的基础知识。
后续章节会通过一些实用的合约例子,来探索 Solidity的一系列特性。记住,你可以在浏
览器中尝试这些合约。
最后以及更多扩展章节的内容,会深入到 Solidity的各个方面。
如有任何关于 Solidly,或者本文档的问题及改进建议,请在 gitter频道提岀来。
智能合约介绍
个简单的智能合约
先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的
细节。
Storage
contract SimpleStorage t
uint storedData:
function set(uint x)t
storedData =x;
function get() constant returns (uint retval)[
return storedData
在 Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位
于以太坊区块链上的一个特殊地址。* uint stored Data*;这行代码声明了一个状态变量,
变量名为 storedData,类型为uint(256bits无符号整数)。你可以认为它就像数据库
里面的个存储单元,跟管埋数据库·样,可以通过调用函数查询和修改它。在以太坊中,
3/137
汇智网 Hu biz. com
Solidity官方文档中文版
通常只有合约的拥有者才能这样做。在这个例了中,函数set和get分别用于修改和查询
变量的值。
跟很多其他话言一样,访问状态变量时,不需要在前面增加this.这样的前缀
这个合约还无法做很多事情(受限于以太坊的基础设施),仅仅是允许任何人储存个数字
而且世界上任何一个人都可以来存取这个数字,缺少一个(可靠的)方式来保护你发布的数
字。任何人都可以调用set方法设置一个不同的数字覆盖你发布的数字。但是你的数字将会
留存在区块链的历史上。稍后我们会学习如何增加一个存取限制,使得只有你才能修改这个
数字。
代币的例子
接下来的合约将实现一个形式最简单的加密货币。空中取币不再是一个魔术,当然只有创建
合约的人才能做这件事情(想用其他货币发行模式也很简单,只是实现细节上的差异)。而
且任何人都可以发送货币给其他人,不需要注册用户名和密码,只要有一对以太坊的公私钥
即可。
Note
对于在线 solidity环境来说,这不是个好的例了。如果你使用在线 solidity环境来尝试
这个例子。调用函数时,将无法改变from的地址。所以你只能扮演铸币者的角色,可以铸
造货币并发送给其他人,而无法扮演其他人的角色。这点在线 solidity环境将来会做改进
contract Coin i
//关键字“pub1ic”使变量能从合约外部访问
address public minter
mapping(address => uint public balances;
//事件让轻客户端能高效的对变化做出反应。
event Sent(address from, address to, uint amount);
//这个构造函数的代码仅仅只在合约创建的时候被运行。
function Coin(i
minter msg sender;
function mint(address receiver, uint amount)t
if (msg sender ! minter) return;
balances[receiver] + amount;
function send (address receiver, uint amount)[
if (balances [ msg sender< amount) return;
balances[msg sender]-= amount;
汇智网 Hu biz. com
Solidity官方文档中文版
balances receiver+= amount;
Sent(msg sender, receiver, amount
这个合约引入了一些新的概念,让我们个个来看下
address public minter;这行代码声明了一个可公开访间的状态变量,类型为 address.
address类型的值大小为16 D bits,不支持仼何算术操作。适用」存储合约的地址或其他
人的公私钥。 public关键字会自动为其修饰的状态变量生成访问函数。没有 public关键字
的变量将无法被其他合约访问。另外只有本合约内的代码才能写入。自动生成的函数如下
function minter( returns (address)i return minter; y
当然我们自凵增加一个这样的访问函数是行不通的。编译器会报错,指出这个函数与一个状
态变量重名。
下一行代码 mapping( address=>uint)pub1 ic balances;创建了一个pubc的状态变量
但是其类型更加的复杂。该类型将一些 address映射到无符号整数。 mapping可以被认为
是一个哈希表,每一个可能的key对应的vaue被虚拟的初始化为全0这个类比不是很严
谨,对于一个 mapping,无法获取一个包含其所有key或者vaue的链表。所以我们得
自凵记着添加了哪些东西到 mapping中。更好的方式是维护一个这样的链表,或者使用其
他更髙级的数据类型。或者只在不受这个缺陷影响的场景中使用 mapping,就像这个例子
在这个例子中由pubc关键字牛成的访问函数将会更加复杂,其代码人致如下
function balances(address account) returns (uint balance)t
return balances[ account];
我们可以很方便的通过这个函数查询某个特定账号的余额。
event sent( address from, address to, uint value);这行代码声明了一个N事件"。由send
函数的最后一行代码触发。客户端(服务端应用也适用)可以以很低的开销来监听这些由区
块链触发的事件。事件触发时,监听者会同时接收到from,to,Vaue这些参数值,可以
方便的用于跟踪交易。为了监听这个事件,你可以使用如下代码
Coin Sent).watch(0,', function(error, result)t
if (error)i
console. log("Coin transfer: result args. amount
coins were sent from+ result. args. from
to"+ result. args to +. "
console. log( Balances now: \n"+
Sender:+ Coin balances, call(result. args, from)+
Receiver:+ Coin balances. call(result. args to));
汇智网 Hu biz. com
Solidity官方文档中文版
注意在客户端中是如何调用自动生成的 balances函数的
这里有个比较特殊的函数Coin。它是一个构造函数,会在合约创建的时候运行,之后就无
法被调用。它会永久得存储合约创建者的地址。msg(以及tx和bock)是一个神奇的全
局变量,它包含了些可以被合约代码访问的属于区块链的属性。 msg sender总是存放
着当前函数的外部调用者的地址
最后,真止被用户或者其他合约调用,用来完成木合约功能的函数是mnt和send。如果
合约创建者之外的其他人调用mint,什么都不会发生。而send可以被任何人(拥有一定
数量的代币)调用,发送一些币给其他人。注意,当你通过该合约发送一些代币到某个地址,
在区块链浏览器中査询该地址将什么也看不到。因为发送代币导致的余额变化只存储在该代
币合约的数据存储中。通过事件我们可以很容易创建个可以追踪你的新币交易和余额的
区块链浏览器。
区×块链基础
对」程序员来说,区块链这个概念其实不难珄解。因为最难慬的一些东西(挖矿,哈希,椭
圆曲线加密,点对点网络等等)只是为了提供·系列的特性和保障。你只需要接受这些既有
的特性,不需要关心其底层的技术。就像你如果仅仅是为了使用亚马逊的AWS,并不需要
了解其内部工作原理。
交易/事务
区块链是一个全局共享的,事务性的数据库。这意味着参与这个网络的每一个人都可以读取
其中的记录。如果你想修改这个数据库中的东西,就必须创建个事务,并得到其他所有人
的确认。事务这个词意味着你要做的修改(假如你想同时修改两个值)只能被完完全全的实
施或者一点都没有进行。
此外,当你的事务被应用到这个数据库的时候,其他事务不能修改该数据库
举个例子,想象一张表,里面列出了某个电子货币所有账号的余额。当从一个账户到另外
个账户的转账请求发生时,这个数据斥的事务特性确保从个账广中减掉的金额会被加到另
个账户上。如果因为某种原因,往目标账户上增加金额无法进行,那么源账户的金额也不
会发生任何变化。
6/137
汇智网 Hu biz. com
Solidity官方文档中文版
此外,个事务会被发送者(创建者)进行密码学签名。这项措施非常直观的为数据斥的特
定修改增加了访问保护。在电子货币的例子中,一个简单的检查就可以确保只有持有账户密
钥的人,才能从该账户向外转账
区×块
区块链要解决的一个主要难题,在比特币中被称为双花攻击"。当网络上出现了两笔交易,
都要花光一个账户中的钱时,会发生什么?一个冲突?
简单的回答是你不需要关心这个问题。这些交易公被排序并打包成区块",然后被所有参与
的节点执行和分发。如果两笔交易相互冲突,排序靠后的交易会被拒绝并剔除出区块。
这些区块按时间排成一个线性序列。这也正是区块链”这个词的由来。区块以一个相当规律
的时间间隔加入到链上。对于以太坊,这个间隔大致是17秒。
作为顺序选择杋制″(通常称为"挖矿")的一部分,一段区坎链可能会时不时被冋滚。但这
种情况只会发生在整条链的末端。回滚涉及的区块越多,其发生的概率越小。所以你的交易
可能会被回滚,甚至会被从区块链中删除ε但是你等待的越久,这种情况发生的概率就越小
以太坊虚拟机
总览
以太坊虚拟杋(E∨M)是以太坊中智能合约的运行环境。它不仅被沙箱封装起来,事实上
它被完全隔离,也就是说运行在EVM内部的代码不能接触到网络、文件系统或者其它进程
甚至智能合约与其它智能合约只有有限的接触。
账户
以太坊中有两类账户,它们共用同一个地址空间。外部账户,该类账户被公钥-私钥对控制
(人类)。合约账户,该类账户被存储在账户中的代码控制。
外部账户的地址是由公钥决定的,合约账户的地址是在创建该合约时确定的(这个地址由合
约创建者的地址和该地址发出过的交易数量计算得到,地址发出过的交易数量也被称作
Nonce"
合约账户存储了代码,外部账户则没有,除了这点以外,这两类账户对于EVM来说是一样
的
7/137
汇智网 Hu biz. com
Solidity官方文档中文版
每个账户有个key- value形式的持久化存储。其中key和vaue的长度都是256比特
名字叫做 storage
另外,每个账户都有一个以太币余额(单位是"we"),该账户余额可以通过向它发送带有
以太币的交易来改变
交易
一笔交易是一条消息,从一个账户发送到另一个账户(可能是相同的账户或者零账户,见下
文)。交易可以包含二进制数据( payload)和以太币。
如果目标账户包含代码,该代码会执行, payload就是输入数据
如果目标账户是零账户(账户地址是0),交易将创建一个新合约。正如上文所讲,这个合
约地址不是零地址,而是由合约创建者的地址和该地址发出过的交易数量(被称为 nonce)
计算得到。创建合约交易的 payload被当作EVM字节码执行。执行的输出做为合约代码
被永久存储。这意味着,为了创建一个合约,你不需要向合约发送真正的合约代码,而是发
送能够返回真正代码的代码
Gas
以太坊上的每笔交易都会被收取·定数量的gas,gas的目的是限制执行交易所需的⊥作量,
同时为执行支付费用。当EMM执行交易时,gas将按照特定规则被逐渐消耗
gas price(以太币计)是由交易创建者设置的,发送账户需要预付的交易费用= gas price
* gas amount。如果执行结束还有gas剩余,这些gas将被返还给发送账户。
无论执行到什么位置,一旦gas被耗尽(比如降为负值),将会触发一个out-of-gas异常
当前调用帧所做的所有状态修改都将被回滚。
存储,主存和栈
每个账户有一块持久化内存区域被称为存储。其形式为 key-value,key和vaue的长度
均为256比特。在合约里,不能遍历账户的存储。相对于另外两和种,存储的读操作相对来
说开销较大,修改存储更甚。一个合约以能对它自己的存储进行读写
第二个内存区被称为主存。合约执行每次消息调用时,都有一块新的,被清除过的主存。
存可以以字节粒度寻址,但是读写粒度为32字节(256比特)。操作主存的开销随着其增
长而变大(平方级别)。
8/137
汇智网 Hu biz. com
Solidity官方文档中文版
EVM不是基于寄存器,而是基于栈的虚拟机。因此所有的计算都在个被称为栈的区域执
行。栈最大有1024个元素,每个元素256比特。对栈的访问只限于其顶端,方式为:允
许拷贝最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面16个元素中的
个。所有其他操作都只能取最顶的两个(或一个,或更多,取决于具体的操作)元素,并把
结果压在栈顶。当然可以把栈上的元素放到存储或者主存中。但是无法只访问栈上指定深度
的那个元素,在那之前必须要把指定深度之上的所有元素都从栈中移除才行。
指令集
EVM的指令集被刻意保持在最小规模,以尽可能避免可能导致共识问题的错误实现。所有
的指令都是针对256比特这个基本的数据类型的操作。具备常用的算术,位,逻辑和比较
操作。也可以做到条件和无条件跳转。此外,合约可以访问当前区块的相关属性,比如它的
编号和时间戳
消息调用
合约可以通过消息调用的方式来调用其它合约或者发送以太币到非合约账户。消息调用和交
易非常类似,它们都有一个源,一个目标,数据负载,以人币,gaS和返回数据。事实上每
个交易都可以被认为是一个顶层消息调用,这个消息调用会依次产生更多的消息请用
个合约可以决定剩余gas的分配。比如内部消息调用时使用多少gas,或者期望保留多
少gas。如果在内部消息调用时发生了out-of-gas异常(或者其他异常),合约将会得到
通知,一个错误码被压在栈上。这种情况只是内部消息调用的gas耗尽。在 solidity中,
这种情况下发起调用的合约默认会触发一个人工异常。这个异常会打印出调用栈。就像之前
说过的,被调用的合约(发起调用的合约也一样)会拥有崭新的主存并能够访问调用的负载。
调用负载被存储在一个单独的被称为 calldata的区域。调用执行结束后,返回数据将被存
放在调用方预先分配好的块内存中
调用层数被限制为1024,因此对于更加复杂的操作,我们应该使用循环而不是递归。
代码调用和库
存在一种特殊类型的消息调用,被称为 malcode。它跟消息词用几乎完全一样,只是加载
自目标地址的代码将在发起调用的合约上下文中运行。
这意味着一个合约可以在运行时从另外一个地址动态加载代码。存储,当前地址和余额都指
向发起调用的合约,只有代码是从被调用地址获取的
9/137
汇智网 Hu biz. com
Solidity官方文档中文版
这使得 Solidity可以实现"。可复用的库代码可以应用在个合约的存储上,可以用来
实现复杂的数据结构。
日志
在区块层面,可以用一种特殊的可索引的数据结构来存储数据。这个特性被称为日忐
Solidity用它来实现事件。合约创建之后就无法访问日志数据,但是这些数据可以从区块链
外高效的访问。因为部分日志数据被存储在布隆过滤器( Bloom filter)中,我们可以高效
并且安全的搜索日志,所以那些没有下载整个区块链的网络节点(轻客户端)也可以找到这
些日志
创建
合约甚至可以通过一个特殊的指令来创建其他合约(不是简单的向零地址发起调用)。创建
合约的调用跟普通的消息调用的区别在于,负载数据执行的结果被当作代码,调用者/创建
者在栈上得到新合约的地址。
自毁
只有在某个地址上的合约执行自毁操作时,合约代码才会从区块链上移除。合约地址上剩余
的以太币会发送给指定的目标,然后其存储和代码被移除
注意,即使个合约的代码不包含自毁指令,依然可以通过代码调用( callcode)来执行这个
操作。
安装 Solidity
基于浏览器的 Solidity
如果你只是想尝试一个使用 Solidity的小合约,你不需要安装任何东西,只要访问基于浏
览器的 Solidity
如果你想离线使用,你可以保存页面到本地,或者
从http://github.com/chriseth/browser-solidity克隆一个。
NPM/node. js
这可能安装 Solidity到本地最轻便最省事的方法。
10/137
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.