00:00
好,接下来我们就准备真正的给大家来介绍一下solidity,然后我们就会真正的知道怎么样用这样的一种语言来构建我们自己的智能合约,呃,之前我们其实已经做了一个简单的水龙头合约,但是那个合约呢,其实不是很典型,然后它的功能也会比较有点奇怪,所以呃,对于我们掌握,可能对于我们实现一个功能来讲是没有什么问题的,我们已经完成了我们第一个智能合约,但是从对我们了解soli的整个这门语言和怎么样去更深刻的理解智能合约,怎么样去构建出更复杂的智能合约,呃,那可能我们之前那个水龙头还不够对吧,所以接下来的时间我们就会给大家来讲一讲,从一个呃,我们还是。
01:00
就从比较理论性的东西还是先先出发啊,就是我们至少要先知道这个solidity是什么,Solidity定义来了,它是一门面向合约的,为实现智能合约而创建的,它是它的特点是说面向合约,所以这个提法也是很奇怪,我们之前一直都是说面向过程,面向对象,他这里来了一个面向合约,那既然他这么提,那肯定就是针对合约这样的特殊的新式的一个东西,它肯定有各种各样更特殊的处理,所以说后面我们就会看到它的很多东西,其实就跟它这个目的是相关的,呃,那solidity呢,它是一个静态类型的语言,它的发展,它的发明其实是受到了就是CC加加Python javascript这些语言,各种语言的影响,所以大家其实如果熟悉其他。
02:00
他的编程语言的话,在这个so雷体里边其实是可以看到很多自己很熟悉的东西的,他的语法也不难,咱们之前已经接触到一点点了,对吧?它本身设计的目的只是为了让我们熟悉的那些语言能够在以太网、虚拟及EPM上运行,所以说它又做了很多其他的一些调整和其他一些特殊属性的引入,那solidliity它的发明者呢?或者说创建者呢?是,呃,应该叫开文伍德,就盖文wood这个人是是一个大神。他是谁呢?这个人是以太坊黄皮书的写作者,写作者同时呃,应该也是,就是微生团队里边,他应该一开始就是以太坊项目的CTO,他后来除了写了以太坊的黄皮书之外,还跟人合写了很著名的一本书,就叫精通以太坊,所以这也就是为什么推荐大家可以去好好看一看这个呃,精通以太坊啊,该文物的大神写的。那扫这个语言呢,它是静态语言类型,这就这一点上跟c Java是一样的,那跟JS那就不一样了,既然是静态类型语言,所以大家就要注意它里边的数据类型是要求比较严格的,等一下我们会详细的讲它里边有哪些数据类型。呃,当然了,它同。
03:41
时也吸收了很多语言里边面对对象的特点,所以它其实尽管没有类的概念,但是我们都说了可以把合约就当成类,那么本身它的合约也是支持继承,也也支持库的调用,同时还支持复杂的用户定义的一些数据类,数据类型比如说就是像结构体啊,像媒体类型啊,就这些都是支持的,呃,大家就是只要有一门熟悉的语言,肯定就觉得这些东西都都不陌生了。下面就是它比较特殊的地方,它内涵的数据类型呢,除了常见语言里面所有的这些类型之外,还有一个它独有的类型。
04:24
这个类型叫做叫做地址类型,这是以太坊独有的。呃,那因为它是面向合约的嘛,而且又是要部署在区块链上的,呃,专门为区块链而生的一门语言,所以说呃,有这个地址的概念当然也是很正常的一件事情,那扫地地址源码文件呢,通常就会以第2SO作为扩展名,我们已经知道了。最后要说的就是它的编译器,目前来说尝试solid编程最好的方式就还是remix,咱已经使使用过几天,使用过一段时间,应该可以发现它确实非常的方便,我们可以随时的看到编译是否通过,可以看到编译错误,而且可以非常方便的就把它部署到我们的测试网络或者真正的网络当中去,而且还可以很很方便的点一个按钮,就就调用它的函数,对吧,调用它里面的方法,这个整个的这一个,呃,这个工具都做的非常的亲密,非常的简洁,非常的。
05:30
方便,所以呃,到目前为止大家肯定就是会发现,我们接下来如果做智能合约开发的话,可能很长一段时间还会,呃,就是依赖remix,我们至少就是即使是之后我们去做项目的时候,可能很多文件是比方说用Vs code去写原文件的,写完了之后,因为它那边没有编译的功能,所以我们可能还要把它贴到X里面去检查一下编译错误,呃,所以大家还是要把这个当成一个常态啊。呃,下面这个大家都已经知道了啊,Remix是一个基于web浏览器的IDE,它可以让你写solid的原文件,这就是我们可能可以编译,可以部署,而且运行这样的一个智能合约。好,接下来我们再着重的跟大家说几个它的语言特性啊,所以它的语法跟GS非常小,这也是为什么guess它的。
06:30
这个客户端本来它的底层是用构写的,呃,但大家知道现在很多区块链的开发语言,底层链的开发语言都是狗,呃,他在这个并发性和这种预算速度上确实还是很有优势,呃,所以我记得好像第一天还是第二天就有这个同学问我说那个就是购在我们这个以太坊学习里边有用没用?呃,之后我们的开发可能跟购物相关的比较少,因为我们定位这一部分学习还是放在应用层面,直接在我们这部分学习里面直接用go开发的比较少,但是以太坊的源码是构写的,所以大家如果对底层链感兴趣,如果还要想去研究以太坊的深层机制,包括之后我们有时间做源码分析的时候,肯定都是会接触到勾的代码的,而如果我们做应用的话,它的上层大家可以看到最强大的就是GS。
07:28
它本身官方的这个WEB3的内库也是JS来写的,我们可以看到盖客户端的控制台cons也是内置的,WEB3的对象也是用JS写的,而它本身的语法也是比较接近JS,所以这就是大家如果要是对JS比较熟,如果掌握的比较好,这部分应该会上手很快,觉得比较容易扫,是面对对象的语言,他不光面对合约,也面面对对象,但是呢,那这是跟就是我们传统的语言相同的地方,那作为一种它是真正意义上运行在区块链网络当中的去中心化的合约语言,那它又跟我们传统的语言有很多不一样的地方,什么不一样呢?一个就是前面我们提到的专门提到的,它增加了一个address数据类型。
08:22
很简单,就是因为它的底层是基于账户的,而不是UTXO,所以它有address这一个数据类型,用于定位外部用户和合约账户都是用address来定位的。另外就是它的语言内部的这个框架,内嵌的框架呢是支持支付的,因为说白了,以太坊它的基础的应用还是有一个加密数字货币在里面嘛,还是有以太币在里面,所以它提供了一个叫做配O的关键词。这个我们也已经接触到了,对吧?啊,这是很特别的一个,所以它是在语言层面直接就支持这种直接支付的,第三条这个就不说了,那它既然是一个区块链系统嘛,就是solidliity是为了以太坊这样的一个块链系统来服务的,所以solidity的语言语法里边也是可以直接用区块链进行数据存储的,所以我们在用的时候呢,是需要去指明它的存储位置的。
09:25
你到底是要用永久存储还是放在内存里面,这是两种不同的存储的位置,之后我们讲到的时候再说啊,还有就是运行环境呢,是在去中去中心化的网络上,所以它会强调合约和函数执行的调用方式不一样,这个说的是什么呢?就是它会有内部调用和外部调用之说,这是我们大家先有一个概念,讲到的时候再说,最后就是他的异常机制。或者说错误处理的机制跟别的语言可能会不一样,那别的语言就是异常处理的话,那我们就是在哪里报错,你就一层一层的把异常抛出来,然后去处理就好了,之前做过的操作肯定还是有效的,但是以太坊上不一样,扫里面不一样,一旦出现异常,所有的执行就都将被回正啊,这主要就是为了保证我们合约执行的原子性,因为我们知道所有上面代码执行都是由于交易而引起的,都是用交易来触发代码执行的,而交易它必须是要有原子性的,我不能说给别人转账转到一半,然后发现我的款扣了,别人没收到,这是绝对不能允许的事情,对吧?所以作为一个交易,以太网上所有的交易都有原子性,那一旦中间出现状态,呃,出现这个错误的状态异常,异常的状态的话,那一定。
10:58
是会回撤到上一个状态的,不能出现中间状态不一致,这些相对来讲还是理论性有点强啊,还是相对来讲有一点枯燥,但是接下来这一部分大家是一定要知道的,前面那一部分大家可能就作为这种知识的扩展了解就可以,接下来这一部分是必须要知道,就是。
11:18
以太坊的源码,呃,就是solid的源码,是怎么样变成智能合约的?我们在remix里面去发布水龙头合约的时候,其实已经感受过一点这整个的步骤了,第一步我们首先要编译扫编写的智能合约是点sol文件,这是这是我们的源代码,首先我们要把它编译成EVM识别的东西。也就是说我们点那个编译按钮,或者呃,没有编译按钮,有一个那个start compel按钮,或者说我们让它自动编译的时候,这个过程当中,尽管我们不可见,但是我们应该能够想到这是有一步过程的,只不过是remix直接帮我们做了而已,那这个过程当中编译成字节码呢,它会产生一般情况啊,会产生两份。
12:11
文件或者说两个东西,一个东西就是解码,另外同时还会产生一个东西叫做二进制接口规范,就是有时候大家可能会听说就是叫abi,就是application binary interface二进制的接口,呃,这个应该叫应用二进制规范,执执译应该叫二进,应用二进制接口应该叫。那大家理解的话,就可以理解成是它那个二进制的一个接口,接口规范,我们从外部如果要去想要调用链上的合约的话,比如说我们想要用JS跟它去交互,那怎么办呢?一定要用到这样的一个abi这样的一个接口,是链上合约跟外部交互的一个一个通道。
13:03
好,这是abi,然后它的部署过程编译完了之后,第二步就是部署,我们也已经知道了,部署的时候是要发送一个交易的,通过交易的方式将解码部署到以太坊网络,每次成功部署的时候,当然我们都知道这个交易是发送到零兆就是零地址了,每次交易成功的时候,部署成功的候就会产生一个新的智能账户合约,这个合约账户就会永久的存储在以太坊网络当中去。那最后呢,就是刚才我们已经说到的用JS编写的DF,通常的做法是什么呢?就是用WEB3JS,我们提到的那个JS库,然后它调用,当然它要结合我们前面编译出来的那个API。编译过程当中产生的API,然后了解到我们定义的这个合约的接口规范,然后就可以去调用智能合约里面的函数了,这就是我们整个源码是怎么样变成智能合约,然后怎么样去调用的一个过程,相当于是我们智能合约的一个工作流。
14:12
呃,在后续这里只是一个简单介绍,在后续的话,可能我们会给大家强化这一部分的内容,就是我们可能有两天会跟大家一起去试着自己去写脚本,去把这个扫的源码自动的让它去编译出来,然后部署出来,呃,就是我们会对这个过程非常非常了解,我觉得这个是有有必要的啊。那编译的过程当中我们用到什么东西呢?就是用到扫的编译器,主流的编译器其实其实就这两个,一个就是remix,大家已经很熟悉了,它的编译过程是全全部封装好的,我们甚至都不需要了解,所以这个都已经不用我再去多说什么了。另外想要跟大家说的一个呢,是sock sock JS,我一般是把它叫sock啊,SOJS,它是。
15:09
就是扫丽源码库的构建目标之一就是它的so,丽在创创建出的时候,官方定义的它的编码编译工具就是sock,所以它是solid命令行编一起,就像我们去,呃,如果大家去装了Java,装了Python之后,直接就就可以用那个比方说Java,直接用Java c命令就可以去做做编译,对吧?呃,就是就像这样的一个命令行编译起,所以这个东西也是我们一定会掌握的一个东西。既然说到这里,我觉得要不我们现在就稍微的停一下,大家就就做一点事情,我们先把这个装上吧,对吧,这个应该也不费什么事,它比较简单装的,装这个so怎么装呢?我推荐大家就是直接用NPM,大家note都已经装了是吧?对,用NPM非常方便,装这个SGS非常方便,就下面这一句,N PM in store,呃,杠G的话就是全局。
16:09
安装,大家如果要是不愿意杠G,自己想要去装在特定的目录下面,自己本地的目录下面,大家可以不打杠G,就是n PM in store-GSO就可以装上SOGS,呃,大家现在给大家两三分钟时间,大家要先把这个装一下,在咱们的那个开发环境里面,Linux环境里边,先用N命令把它装一下,没有吗?配Windows配呃,那那也可以,如果要是在Windows下面的话,大家也可以在Windows下面去装啊,但是我不确定会不会有有有问题,就因为这个环境可能多多少少会有一些状,对对,Windows确实还是,呃,做开发的话,确实会有各种各样的问题,呃,这这个倒没关系啊,我就是希望就是既然讲到这里了,我们捎带的就。
17:09
我把这个做了,因为这个也比较简单,主要是装完了之后会需要跟大家啊,我这里就给大家演示一下吧,尽管我这里已经装了啊呃,大家可以看我这边呃,N PM list。嗯,大家可以看到我这边装的版本是0.4.25,大家只要是直接这样去用NPM装,应该装的就是版本不会太久,应该都没有什么问题,就是只要去打一个n PM in store到GSO,只要打这么简单一个定义就可以大嗯,在装了吗?
18:11
在装是吧,主要是装完了之后我要跟大家说一下,我自己在安装的时候发现它的安装就是打了杠G命令的话,默认会安装在node,就是我们自己node的那个安装目录下面,所以如果node的安装目录大家没有把它加到自己的环境变量,就是没有加到pass里边的话,可能大家就没有办法直接调用就是so的命令,所以大家可能还要加一下环境变量,然后还有一个问题是,我可以给大家看一下我这边装好的这个位置啊,我这边装好的位置在这里,这是我的note的安装目录,大家可以看就是。
19:11
我这里装好的这个SOJS,它会指向我这里no modules下面的sock so JS,所以装好之后大家可能会发现要调用这个命令的时候,它是需要打sock JS这样一句的,这样去调用,所以如果大家不习惯这样,就觉得如果是直接打一个sock,这样会比较舒服一点的话,可以像我这样啊,就是我是做了一件什么事情呢?我也没有把这个note这个目录加到自己的环境变量里面,我是在我的,就是大部分软件装在了就是user local下面,User local bam下面,所以我就在user local bin这个是加在我的环境变量里面的,这里是可以直接访问的,所以我在这里建了一个软链接。
20:11
就是用我建了一个叫so的文件,把它软链接到我们note安装目录文件下的那个SOJS上,所以我就可以直接打so命令了,是这样啊,呃,等大家这个如果想要跟我这边之后敲命令敲的都完全一样的话,可以用我这种方式,但如果要是就觉得没关系的话,因为这个不重要,只不过就是我这边打so,大家可能就得打SOGS这样啊。0.4.25编译器版本。应该还没有装好吗?我觉得应该可以装好了啊,是是慢是吧,好,如果慢的话,那大家就先先放着吧,先先等一下吧,我们就不在这里耽误时间,因为我觉得这个这个应该还好,不会像源码编译那个问题那么多啊呃,主要就是说有可能大家装完了之后找不到它,所以我说一下就是大家看一下装完了之后装到哪个目录了,好没关系,那大家就是装好的话就就装好,有没有装好的同学装好了是吧?好呃,大家如果要是没装好的话,就下来自己再看一看,或者问一问已经装好的同学,这个环境以后不要占咱们太多的这个时间,我们尽量还是下来之后大家把这个搞定就好了,因为因为我。
21:59
之前听其他老师说,就就包括左老师也跟我说,就是咱们整个这个班本身的起点,或者说大家平均的这个水平比其他班还是要高很多的,所以我也是想就就给大家节省比较,就是多节省一点时间,大家能自己搞定的肯定就就下来之后大家自己搞定就好了。好接下来我们还是看一下我们这个整个源码编译成,就是刚才我们提到这么多概念啊,源码,然后编译器自检码abi,他们到底是一个怎么样的过程呢?这个工作流到底是一个什么样的状况呢?我们看看这个图能不能让大家觉得更清晰一点,呃,当然这个图也是我我扒下来的一张图啊,我是觉得这个图确实做的还不错,大家可以看到最上面就是智能合约的源代码,我们的点so文件,它首先经过编译,呃,但是这一步我觉得这个。
22:59
箭头写的不太对啊,就是应该是经过了扫ity编译起之后,这一步就叫编译对吧?编译完了之后呢,就会生成两样东西,一样叫字节码by code,另外一样叫二进制接口,呃,二进制应用接口abi就是这说的接口声明这两样东西分别怎么用呢?自解码直接就可以作为我们交易的一部分,发出去之后就部署到区块链上了,所以大家可以看到部署可以分别部署到不同的网络当中去,比如说测试网络,Riy主网或者我们的本地私私有链,对吧?本地网络都是可以的,然后就会创建出不同的智能合约实例,就有了地址,这是我们自解码的应用。那接口API主要是用来干什么呢?它主要是给外部使用,那外部我们就可以用WEB3GS这样的接口。
23:59
工具,然后结合合约它自己的接口声明,那WEB3GS就相当于是一个通用的接口,然后他才知道具体这个合约你里边的函数到底是怎么定义的,怎么声明的,这两个一结合,我们就可以在外部知道这个合约具体的形式,具体的函数调用该怎么去用,那我们如果要开发出DF之后,跟JS,就是跟WEB3去做交互,就可以直接调用我们链上的合约实力了,所以是这样的一个过程啊,大家会感觉稍微有一点明白吗?应该是稍微了解一些了,对吧?比刚才光是一张图,可能确实有时候就是一张图,比说那么多可能都会管用一点。好这是我们所说的整个智能合约的工作流,它从编译部署到我们调用的一个过程,前面说的都是泛泛而谈,比较大的东西。
24:59
接下来我们就来看一个简单的智能合约吧,这个这样吧,这个我们不要在这里看了,我们直接到remix里面去敲代码吧,好,我们来新建一个,大家如果要是想跟着我一起做的话,可以就是跟着我一起敲啊,当然也可以先看我做一遍,然后大家再再自己去做尝试,呃,比方说我们这个就就跟我们那边定义的一样吧,比方说我们现在想做一个简单存储的一个一个智能合约,我们不是说整个区块链是可以存储数据的吗?存储状态的吗?合约里边不是有自己的存储空间嘛,我们现在就来做一个简单的存储,我们这个合约的目的非常简单,就是我就想在里边定义一个变量,然后它就当成我自己私有的一个存储空间,我可以去改这个值我。
25:59
可以给它set一个值,Set进去,然后可以get把它拿出来啊,这就实现了我们一个基本的一个呃存储简单存储的一个功能,对吧,好,我们一样啊,还是problemmama啊,这个容易写错solidity,比如呃,我们这个还是先大于0.4.22吧,呃,之所以为之所以为什么要大于0.4.2,等一会儿再跟大家说啊啊什么啊,这个向上和向右,这个跟大家说一下,这个向右就是本身这就是一个大于号,这个好理解对吧,就是比这个版本大就可以向上的这个这个符号呢,稍微有一点不一样,他的意思是说要高于这个,当后面指定的这个版本,但是不贵,不会高。
26:59
过一个一个大版本,对,不会高过大版本,所以就是说这个意思就相当于是大于0.4.22,小于0.5.0,对也可以可以这么写啊,当然这个大家可以随便定义,然后发现如果这个跟我们用的编译器有冲突的时候,大家再去调整一下,再重新下个编译器,然后看看哪些语法通用,哪些语法不适用了,这个大家都可以去自己去做一做啊好,那么我们同样有contract simple storage字搞大一点,但是看不清楚是吧?哎呦,这个有点过了,现在看得清楚吗?
27:59
说重置是吧,是是要上面这里调是吧,好大家对这个还是做了挺多研究的,这个我平常都没这么用过,好我们来定义一个简单的一个合约,那这个合约我们已经说了,它里边我们是希望有一个自己的一个存储空间,然后去做好大家看这个自动回收下来,它会补足一个大括号啊,所以小心一点,我们要定义一个自己的存储空间,然后去设置它的值,获取它的值,那这个存储空间很简单,我们想一个最简单的,大家都已经熟悉的,比方说U,原来敲出来之后,它下面就就在提示有这么多UN的选项可以选,那后面那个跟子当然就是它的位数了,对吧,我们一般就默认就给一个UN就可以,U其实就是U。
28:59
256,所以我们直接给一个,比如说U,我这个叫做my data吧,我随便给名字啊,可能跟我们课件里面不一样,然后我们要做的是什么呢?我们要能设置它的值,那我们当然就是要定一个function了,Function set data,对吧?然后既然要set data,我们肯定得传一个值进去,对不对,那一样也是一个U的,比方说这个叫一个new data,好后面后面注意就是如果我们要想能够在外面调用的话,它一定要是public类型,这个大家前面我们做水龙头的时候也知道啊,它必须要是public,好,那里边写法也很简单,直接就是my data,大家看它还有这个补全提示的my data等于new data,就这样,所以大家看这个。
29:59
它的这个写法也是很很简单啊,很简洁,咱们如果要JS里边有可能还得比方说this点麦塔对吧,这个this指针什么的,这里边就是直接my data访问就可以了,然后等于new data直接复制写进去,那大家可以想到那function式,如果要是我们还要get的话,那就来一个get data get data就不不需要参数了,对吧,同样我们来一个public,诶大家注意那get get data的话,我们肯定是需要有返回值的,对不对,所以我们这里要加一个他注意啊,返回值类型需要在前面定义,它的返回值有一个returns关键词,指明返回什么样类型的数据,那返回的也是一个,然后下面那就是直接return my data。
30:59
就这么简单,但是大家可以看到这里它有一个warning啊,这里有一个warning,大家可以看一下,它说的是function state mutable mutability can be restricted to view是什么意思呢?这个就涉及到一个它叫函数状态的可变性,他说可以把它限制成view,其实简单理解就是意思说remix已经自动的检测出来,我们的这一个函数里边是没有做对状态数据做改变的。
31:38
就没有改写,我们的数据存储没有写入,它只是读取,所以它提示说你可以再把它限制一下,你可以直接限制它叫并一个关键词,这样的话就表明我这个函数是只读不写的,那这个就方便EVM理解我们这个要做什么事情,它就可以节省很多资源,所以是这样的,大家可以看到我把这个VI加上去之后,这边就没有再曝光了,对吧?好,这就是我们这样一个简单的一个一个智能合约,那这里边所需要给大家解释的有几个点呢?主要也就是刚才说到的几个点,首先上面我们这个P,这这应该是叫一个,这个叫什么我给忘记了,叫叫什么杂住吧,好像叫我看一下课件啊。
32:38
课件里面好像也没有写好,那我们就先不管它,反正大家就知道这是一个一个标记,然后就相当于我们要通用去声明一下我们的版本信息,所以这是固定的一个写法,Program ma solidity,然后后面的版本号呢,就是大家看到可以用大于小于这样的方式,当然你也可以指定唯一的版本号,比方说我就要指定这个就是0.4.22,那肯定就会报错了,我现在用的是0.4.25嘛,对吧,所以这就肯定就报错了,大家如果要是愿意,就是自己习惯是非要用一个指定版本的编译器的话,也可以那样去指定,因为之后我们我们的so去编译的时候,那确实就是固定版本的编译器,呃,所以这是这样的一个状况,另外就是下面我们这一个UNMY,这其实就是已经声明了我们自己合约里边的一个状态变量,所以大家可以看到。
33:39
那就是我们的合约里面是有状态变量的数据存储就存储在这里,然后下边呢,就是我们定义的函数,函数的定义方式function,然后后面加名词,然后加它的函数的参数,入参,后面加它的这种调用方式,或者叫它的可见性,这是一个,呃,这就大家统一理解,这是叫函数类型吧,这所有的这些都算函数类型吧,简单理解就是这样,最后就是一个它的返回类型。
34:09
返回类型,如果有就写上,没有的话不加也可以,那在里边的话,如果我们要给这个状态变量去赋值,我们直接把它写进去,等于就可以了,如果我们要返回一个数,那直接把它返回就可以了。呃,这个东西就这么简单,好我们已经做完了,那我们来编译通过没有问题,我们来让一下吧,嗯,多多吧,嗯,你是说这个就是可以返回,同时返回多个值是吗?可以的,就是比方说我这里如果要是返回多个值的话,这里的定义就后面你也要加东西,就是这样,对对跟go差不多是吧。哦,我这边好像会有一点问题啊,我这里应该是没有网络了。
35:02
那我觉得这个很简单,这个我觉得就交给大家吧,大家自己来试一试好不好,好那现在给大家一点时间,好都已经48了啊,那大家就自己来实现一下这个,然后自己部署,然后自己去点一点,看看有什么样的这个按钮可以去点,自己是不是可以真正改它里边的数值。
我来说两句