手把手教你搭建智能合约测试环境、开发、编译、部署以及如何通过JS调用合约方法

完整视频教程

https://v.qq.com/x/page/h0552ba9k8h.html

学习目标

了解智能合约

简单环境搭建

能够利用solidity编写Hello World合约

合约部署

和合约互动

使用solidity语言撰写智能合约

Ethereum上的智能合约需要使用solidity语言来撰写。虽然还有其他能用来撰写智能合约的语言如Serpent(类Python)、lll(类Fortran),但目前看到所有公开的智能合约都是使用solidity撰写。

宣传上说,solidity是一种类似Javascript的语言,而且围绕着solidity的各种开发工具链,都是使用属于Javascript生态系的npm来提供的。但我觉得solidity还是比较像Java或C#。因为和Javascript不同,solidity与Java或C#同属于强类型(Strong Type,在定义变数时需要指定类型)语言、在定义函式(function)时同样需指定回传的类型(type)、同样也需要先编译才能执行。这些特性都是Javascript所不具备的。

开发前的准备

本文将使用当前最活跃的智能合约开发框架truffle为基础来开发。ENS(Ethereum Name Service)也是采用truffle框架。其他选择还有embark等。

就像一般网站或App开发一样,在提供公开服务之前,开发者会在自己用于写程序的电脑(又称作本机)或透过测试网络来测试程序执行的效果,测试完成后,才会部署到公开的网络上提供服务。开发区块链智能合约(程序)的过程也是如此。特别是公开链上所有写入或读取计算结果的操作都需要真金白银(虚拟代币),而且根据网络状况,每个公开链上的操作都需要要一小段反应时间(15秒~数分钟),这些等待颇浪费宝贵的开发时间⏳。因此在开发的过程中,我们将使用testrpc工具在电脑上模拟智能合约所需的以太坊内存块链测试环境。

testrpc中也包含了Javascript版本的Ethereum虚拟机(Ethereum Virtual Machine),因此可以完整地执行智能合约。

此外,开发前还需准备一个合手的编辑器。我目前是使用Atom搭配solidity插件来开发。solidity插件除了支持语法高亮之外,也会透过Solium检查并提示基本的语法错误,相当方便。其他编辑器应该也有类似的插件可选择。

安装所需工具

首先开发机上必须装好Node.js,再使用以下命令安装所需的工具:

liyuechun:~ yuechunli$ npm install -g ethereumjs-testrpc truffle

/usr/local/bin/testrpc -> /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js

/usr/local/bin/truffle -> /usr/local/lib/node_modules/truffle/build/cli.bundled.js

+ truffle@3.4.9

+ ethereumjs-testrpc@4.1.3

added 1 package and updated 7 packages in 76.132s

liyuechun:~ yuechunli$ 


启动Testrpc

安装好后随时可以使用testrpc命令来启动以太坊测试环境。

liyuechun:~ yuechunli$ testrpc

EthereumJS TestRPC v4.1.3(ganache-core: 1.1.3)

Available Accounts

==================

(0)0xbbd414b340f2255dab9d923428c97f0b65d9df81

(1)0xe9869e3cf29b6fca81762c314df229c7c4fea25e

(2)0xc79e72362a4511b9e499d186654332c4d6f569be

(3)0x9a6f0651907c149d4173c03927144dbbba1473d4

(4)0x5b13a5d6788752b26dd4e338aae2e01058ee145e

(5)0xfc7f56d942ad5260be23ecee92a344aba1b7e7d8

(6)0xc48dc22c6bacd6ade4421ab54f25bc45c1c51142

(7)0x3fe2b7d4141dd0a456661f77086d055cbaf3b78f

(8)0x567979fed26ca85e9d1b4ac919c840e3fc9857e2

(9)0xb2eafe245f098eef1c2c1f466d9a8dcd58764c62

Private Keys

==================

(0)947ab78e91133103612ca099d60e6c38cac5bb769f7f097c82d003cf058500bd

(1)8ffe0ba8dc53e16944a17dddd3378b5fba0379cd84df4e5237b8b46d05b8762f

(2)ffe2e04e43e4106b247407656f5233bcc3e0c49730972d0df9c1d1093375e2ef

(3)a20e453dc44c76aaca6a22efdbb605c2ed9eea64c11317e683461e11bd105ea7

(4)4748268ff1b828868dc56d07a1b121b427e1bdede5dbb3c14ef1254d9d26b1a5

(5)f9957e68c6d20d38b81604a0509e6c4591478bc754f87d5682564073705fbb46

(6)34e648b23c0ace6b2b0893651d87f70be8496f97ecf6b7b4607b2acc4e05c9bd

(7)d2477cedec217e3fb19a5981dafbc125ef66ccc9dc7df29301d08a24da843cf5

(8)d319f85ccd80e55b2e707e05f09662632564c297248f8b96f82ea5eeaeef0851

(9)88c33ac9f1062b82f9e82f86a0ce307e3bd8fcf683b9751232c2f193f5bdc668

HD Wallet

==================

Mnemonic:      hire custom clinic expect fury fantasy try dress source spy viable flag

Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

可以看到testrpc启动后自动建立了10个帐号(Accounts),与每个帐号对应的私钥(Private Key)。每个帐号中都有100个测试用的以太币(Ether)。要注意testrpc仅运行在內存中,因此每次重开时都会回到全新的状态。

一切准备就绪,我们可以开始建立第一份智能合约项目了。

建立项目

开启另一个终端窗口,输入以下命令以建立项目:

liyuechun:Desktop yuechunli$ mkdir SmartContractDemo

liyuechun:Desktop yuechunli$ cd SmartContractDemo/

liyuechun:SmartContractDemo yuechunli$ mkdir HelloWorld

liyuechun:SmartContractDemo yuechunli$ cd HelloWorld/

liyuechun:HelloWorld yuechunli$ truffle init

Downloading project...

Project initialized.

  Documentation: http://truffleframework.com/docs

Commands:

  Compile: truffle compile

  Migrate: truffle migrate

  Test:    truffle test

liyuechun:HelloWorld yuechunli$ ls

contracts    migrations    test        truffle.js

目录结构:

/contracts:存放智能合约原始代码的地方,可以看到里面已经有三个sol文件,我们开发的HelloWorld.sol文件就存放在这里。

/migrations:这是 Truffle用来部署智能合约的功能,待会儿我们会修改2_deploy_contracts.js来部署 HelloWorld.sol。

/test: 测试智能合约的代码放在这里,支持js 与 sol 测试。

truffle.js: Truffle 的设置文档。

新建HelloWorld合约

在contracts文件夹下新建HelloWorld.sol文件,当然也可以直接在HelloWorld路径下面直接执行truffle create contract HelloWorld命令来创建HelloWorld.sol。

HelloWorld.sol文件內容如下:

讲解

pragma solidity ^0.4.4;

第一行指名目前使用的solidity版本,不同版本的solidity可能会编译出不同的bytecode。^代表兼容solidity`0.4.4 ~ 0.4.9`的版本。

contract HelloWorld {

    ...

}

contract关键字类似于其他语言中较常见的class。因为solidity是专为智能合约(Contact)设计的语言,声明contract后即内置了开发智能合约所需的功能。也可以把这句理解为class HelloWorld extends Contract。

function sayHello()returns(string){

    return("Hello World");

}

函数的结构与其他程序类似,但如果有传入的参数或回传值,需要指定参数或回传值的类型(type)。

编译

现在执行truffle compile命令,我们可以将HelloWorld.sol原始码编译成Ethereum bytecode。

编译成功后,会在HelloWorld文件夹下面的build/contracts文件夹下面看见HelloWorld.json文件。

liyuechun:HelloWorld yuechunli$ ls

contracts    migrations    test        truffle.js

liyuechun:HelloWorld yuechunli$ truffle compile

Compiling ./contracts/ConvertLib.sol...

Compiling ./contracts/HelloWorld.sol...

Compiling ./contracts/MetaCoin.sol...

Compiling ./contracts/Migrations.sol...

Writing artifacts to ./build/contracts

liyuechun:HelloWorld yuechunli$ ls

build        contracts    migrations    test        truffle.js

liyuechun:HelloWorld yuechunli$ cd build/

liyuechun:build yuechunli$ ls

contracts

liyuechun:build yuechunli$ cd contracts/

liyuechun:contracts yuechunli$ ls

ConvertLib.json    HelloWorld.json    MetaCoin.json    Migrations.json

liyuechun:contracts yuechunli$ cat HelloWorld.json 

{

  "contract_name": "HelloWorld",

  "abi":[

    {

      "inputs":[],

      "payable": false,

      "type": "constructor"

    }

  ],

  "unlinked_binary": "0x60606040523415600e57600080fd5b5b5b5b603680601e6000396000f30060606040525b600080fd00a165627a7a723058203ee98a767948e9bc08094df4a46ab0361f068b2a559032cf968df5bbf63e91430029",

  "networks": {},

  "schema_version": "0.0.5",

  "updated_at": 1505805826302

}

liyuechun:contracts yuechunli$ 

部署

truffle框架中提供了方便部署合约的脚本。打开migrations/2_deploy_contracts.js文件(脚本使用Javascript编写),将内容修改如下:

var HelloWorld = artifacts.require("HelloWorld");

module.exports = function(deployer){

  deployer.deploy(HelloWorld);

};

使用artifacts.require语句来取得准备部署的合约。使用deployer.deploy语句将合约部署到区块链上。这边HelloWorld是contract的名称而不是文件名。因此可以用此语法读入任一.sol文件中的任一合约。

现在执行truffle migrate命令:

liyuechun:HelloWorld yuechunli$ ls

build        contracts    migrations    test        truffle.js

liyuechun:HelloWorld yuechunli$ truffle migrate

Compiling ./contracts/HelloWorld.sol...

Writing artifacts to ./build/contracts

Using network 'development'.

Running migration: 1_initial_migration.js

  Deploying Migrations...

  ... 0x218431f16a5cadc6347449808d981887c90b3872898af7cc9dc9b3280c07c184

  Migrations: 0x64e9673cf962d21642a08635e6654fb7f2ea9bcd

Saving successful migration to network...

  ... 0xd9ec788c106df36b8491c95a0ab02ff1e5ef22c1965c910a2576e8259a00535c

Saving artifacts...

Running migration: 2_deploy_contracts.js

  Deploying HelloWorld...

  ... 0x17774b4914d7bc7ab2505a53c59bda6a1fce30c9839d19d735290ca9140450ea

  HelloWorld: 0x471a22ffe2bddd02e82853059871067e4c07a7f4

Saving successful migration to network...

  ... 0xe5e2e11cf5a63ca4517221c68dadb3cae2ca42cbfed93c09c575b6d5f275fc8b

Saving artifacts...

liyuechun:HelloWorld yuechunli$ 

如此一来合约已经部署到testrpc中。切换到testrpc窗口,可以看到testrpc有反应了。

与合约互动

truffle提供命令行工具,执行truffle console命令后,可用Javascript来和刚刚部署的合约互动。

讲解

truffle console中预载了truffle-contract函数库,以方便操作部署到区块链上的合约。

这边使用HelloWorld.deployed().then语句来取得HelloWorld合约的Instance(实例),并存到contract变量中,以方便后续的调用。

上面用的是Javascript ES6+的语法,这句也可以写成:

还可以用ES5的写法:

这里直接呼叫contract.sayHello()也会得到一样的结果。truffle-contract提供使用call()来读取只读(read only)的数据,这样就不需提供gas。因此如果遇到的操作需要向区块链写入数据,我们就不能用call语句了。

如此一来,我们已写好并部署完成了第一个智能合约,也验证了合约确实可以运作。

加入新方法

我们在HelloWorld.sol中再加入一个echo方法,echo方法接受输入一个参数,并回传传送的参数。

新的echo方法中传入了一个name参数。我们也为echo方法加入一个constant声明,表示调用这个方法并不会改变区块链的状态。如此一来,透过truffle-contract来调用此方法时,会自动选用call来呼叫,也不需要额外提供gas。

由于更新了合约内容,我们需要先重新新编译一次,将编译结果部署到testrpc上,再透过truffle console执行看看结果。

echo方法确实将我们输入的内容回传了。同时因为声明了constant,我们不需要直接调用call()方法,truffle会自动选用call来呼叫。

另一点需要注意的,是这次如果还是用truffle migrate命令,我们会得到如下信息:

Truffle会告诉你现在网络上的合约都已是最新的,但事实上刚刚程序中新增的方法并没有更新到内存块链上。要更新内存块链上已部署的程序,需要改写migrations中的脚本,但现在还不到介绍migration的时候。还好我们开发用的内存块链是怎么修改都没关系的testrpc,可以使用truffle migrate --reset命令直接重新在testrpc上部署一次。

总结

这篇文章非常简单,通过这篇文章,你将掌握如何配置开发环境、如何创建新项目、如何编译、如何部署合约以及了解整个智能合约开发的流程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容