以太坊开发实战(第 2 章: Truffle, Ganache, Geth, 和 Mist)

原文作者:dev_zl

原文地址:https://hackernoon.com/ethereum-development-walkthrough-part-2-truffle-ganache-geth-and-mist-8d6320e12269

我们在本系列教程的第一章已经见识了智能合约以及它的工作方式。现在我们就尝试将它部署到两种测试网络里面。

我们将会用到的工具

部署合约最重要的工具如下:

  • Truffle:一个以太坊的开发环境,测试框架,和资产管道。换句话说,它可以帮助你进行智能合约的开发,发布,还有调试等工作。你可以阅读 Truffle suite 的文档以获取更多信息。
  • Ganache:它的前身是 TestRPC。如果你在几个月前已经读过有关的教程,那么你会发现它们很有可能用到 Truffle 的同时用到了 TestRPC。不过在 Truffle Suite 整合了 TestRPC 后,它就被改名叫作 Ganache 了。Ganache 所做的事情很简单,它会创建一个虚拟的以太坊区块链,并且会产生一些我们将在开发过程中用到的虚拟账户。
  • Mist:这是一个去中心化 web 应用的浏览器。它在试图成为一个 Chrome 或 Firefox 的替代品(能运行去中心化应用的那种)。可是它仍不是很安全,你不应该用它来运行尚未受信任的 DApps(去中心化应用)。
  • 以太坊钱包:这是 Mist 的一个版本,但它只会打开一个 DApps —— 以太坊钱包。Mist 和以太坊钱包都只能作为一个 UI 层存在。我们还需要一个核心应用将它们连接到以太坊区块链上,这样才能正常使用它们的功能(可以连接到真正的以太坊区块链,或只连到测试环境的区块链)。
  • Geth:它就是上文所说的在计算机上的一个核心应用,能让你连接到一条区块链上。它也可以启动一条新的区块链(在我们将要介绍的例子里面,我们会创建一个本地测试区块链)、在区块链上创建合约,还能在区块链挖矿得到以太币,等等。

我们将首先使用 Truffle 和 Ganache,然后使用 Truffle,geth 还有 Mist。

安装

本教程需要读者了解命令行工具及其使用方法,并且在一定程度上熟悉 NPM

Truffle

打开命令行工具,输入以下指令即可:

npm install -g truffle

如果在这过程中出现了问题,建议阅读 Truffle 文档来了解更多信息。

Ganache

然后安装 Ganache 的命令行版本:

npm install -g ganache-cli

如果不确定安装过程是否正常进行,不妨查阅一下 Ganache 的 Github 主页

注意:Ganache 有一个图形界面版本,不过毕竟我们都有一颗黑客的心,因此我们会先演示命令行版本的使用。

开始吧

首先,创建一个新文件夹,然后在文件夹目录里面输入这行指令:

truffle init

这会初始化一个空的 truffle 项目。

然后将上一章教程的 Wrestling.sol 文件复制到文件夹 “contracts” 中。

接下来,打开文件夹 “migrations” 并创建一个名为 “2_deploy_contracts.js” 的新文件。这个 "migrations" 文件夹只会存放一些仅帮助我们把合约部署到区块链上的脚本。

复制以下代码粘贴到 .js 文件里面并保存:

const Wrestling = artifacts.require("./Wrestling.sol")

module.exports = function(deployer) {
	deployer.deploy(Wrestling);
};

第一行代码会从 “contracts” 文件夹导入 “Wrestling.sol” 文件作为合约的一个实例,第四行则会将合约部署到区块链。

现在把目光放到根文件夹上,你会看到两个文件:“truffle.js” 和 “truffle-config.js”。如果你用的是 Windows 系统,那就得把 "truffle.js" 删掉;如果不是,那这两个文件挑一个删或者不删也无所谓。这其中的原因在于 Windows 系统有个命名问题,它会让我们在执行 Truffle 命令的时候只打开配置文件 "truffle.js",而不会读取里面的内容。

我是基于 Windows 系统来编写本教程的,所以我会删掉 “truffle.js” 文件。然后还得将以下这段代码放在 “truffle-config.js” 里面。

module.exports = {
  // 不妨查阅一下 http://truffleframework.com/docs/advanced/configuration
  // 来看看自定义 Truffle 配置的更多方法吧!
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*" // 匹配全部网络的 id
    }
  }
}; 

这段代码的基本功能就是当连接的是名为 "development" 的网络时,应该连接到 IP 为 “127.0.0.1”(也就是本地主机的 IP)的主机,使用的目标端口是 7545。

现在我们就完成了准备工作,可以在区块链上测试我们的代码了!

测试我们的代码

我们首先使用 Ganache。

打开一个新的命令行窗口,并输入以下命令:

ganache-cli -p 7545 

这一命令的功能是让 ganache-cli 在 7545 端口启动。

Ganache 启动时会给用户生成测试账号,在默认情况下这些测试账号都有 100 个以太币,并且这些以太币都会处于解锁状态,能让我们自由发送它们的以太币。比如第一个账户就是下图箭头所指的这家伙:

接下来,我们回到在一开始打开的命令行窗口,执行以下两条命令:

truffle compile
truffle migrate --network development

compile 命令会将我们的 Solidity 代码编译为字节码(以太坊虚拟机(EVM)能够识别并执行的代码)。在本教程的情景里,Ganache 就模拟了一个 EVM。

migrate 命令会将代码部署到区块链上。在本教程的情景里,就如我们之前在 "truffle-config.js" 里面设定的那样,我们想要部署到的目标区块链就位于名为 "development" 的网络里。 此时此刻,如果一切顺利,你就应该能在命令行界面看到这些内容:

注意划线位置显示了实例化的 Wrestling 合约的地址。

在运行着 ganache-cli 的命令行窗口上,你会看到正在执行的这条交易:

注意划线位置显示了实例化的 Wrestling 合约的地址。

现在输入以下命令来启动 Truffle 的控制台。它会帮助我们和 Ganache 的区块链进行交互。

truffle console --network development

首先,我们会执行这个命令:

account0 = web3.eth.accounts[0]
account1 = web3.eth.accounts[1]

它会把第一个测试账号的地址赋给 account0 变量,然后把第二个赋给 account1 变量。Web3 是一套 JavaScript API,它封装了调用 RPC 的方法,后者让我们能以简单的方式和区块链进行交互。

然后我们再执行以下命令:

Wrestling.deployed().then(inst => { WrestlingInstance = inst })

这行命令会将 truffle 部署的合约的实例的一个引用赋给 WrestlingInstance 变量。

再执行这一行命令:

WrestlingInstance.wrestler1.call()

这行命令会返回wrestler1的地址,在本教程的情景中它就是第一个测试账号。Truffle 在部署合约期间会从 Ganache 选定一个默认的(也就是第一个)账号来作为合约的部署者。这是因为因为我们没有在迁移过程中指定另一个帐户地址,或者在Truffle的配置文件中有另一个地址。 然后我们把第二个测试账号注册为一个对手:

WrestlingInstance.registerAsAnOpponent({from: account1})

在这行命令的函数里面,from 指令(directive)的意义是触发交易的目标账户。

在这行命令正在执行的时候,命令行界面应该会显示一些如下图所示的内容:

注意交易使用了一些 Gas,并且触发了事件 WrestlingStartsEvent

第二个摔跤手的地址可以通过执行以下命令获得:

WrestlingInstance.wrestler2.call() 

现在,玩家们可以开始角力了:

WrestlingInstance.wrestle({from: account0, value: web3.toWei(2, "ether")})
WrestlingInstance.wrestle({from: account1, value: web3.toWei(3, "ether")})

// 比赛第一轮结束

WrestlingInstance.wrestle({from: account0, value: web3.toWei(5, "ether")})
WrestlingInstance.wrestle({from: account1, value: web3.toWei(20, "ether")})

// 比赛结束

这里 value 指令被用于通过交易发送以太币。比如 web3.toWei(5, ‘ether’) 就发送了 5 个以太币,而且这些以太币会被换成 "Wei"。"Wei" 是以太币的基本单位(最低面值),可以点这个链接了解一下。

在执行最后一行命令时,account1将会胜出,因为我们让account1总共投了 23 个以太币进去,比我们让account0投进去的多了两倍多。

接下来不妨做个小练习:实现从合约中提取以太币的功能。

现在你需要研究 Truffle 还有 Ganache 的高级功能的用法。这可以从阅读文档开始。另外,如果你对此感到一头雾水或者想增强对上文提到的知识的理解,可以看看这篇对 Truffle 的不错的介绍

怎么把 geth 用到我们的情景里来

此时,如果我们在开发阶段用过了 Ganache,为了能更深入地熟悉真实环境,我们就会想去引入一些更接近真实环境的东西。

安装

首先下载 geth。如果用的是 Windows 系统,那可能要将 geth 的安装根目录加到环境变量 PATH 里面。

接着下载 Mist 或者以太币钱包。就本教程的使用场景来说,这两个东西都是一样的,所以选择下哪个并不重要。

创建本地私有测试网络

在同一个根目录下,创建一个名为 “genesis.json” 的新文件。然后将以下内容加进去:

{
  "difficulty" : "0x20000",
  "extraData"  : "",
  "gasLimit"   : "0x8000000",
  "alloc": {},
  "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    }
} 

文件 “genesis.json” 就是创建新区块链所需要的配置文件。现在了解这个文件的内容并不重要。

如果 geth 在没有指定任何参数的情况下运行了,那么它就会尝试连接到主网络里。这一主网络就是以太坊的主网络,即真正的以太坊区块链。 如果 Mist 在没有指定任何参数的情况下运行了,并且有个 geth 的实例正在运行,那么它就会抛出一个错误。如果 Mist 连接到了一个确实正在运行的 geth 实例(过会我们就演示这个情景),那它就能正常运行。如果 Mist 在没有正在运行的 geth 实例的情况下运行了,那么它会启动一个 geth 的新实例,并且在最后向用户询问应该从哪个区块链网络里下载区块数据。

我们可以使用公有的以太网测试网络,不过我们还是会基于我们之前新建的 "genesis.json" 文件在本地创建我们自己的私有测试网络。

再打开一个命令行窗口,输入以下命令(确保这条命令运行在项目根目录里):

geth --datadir=./chaindata/ init ./genesis.json

这行命令运行了一遍 geth,指定了区块链数据的存储路径(这里就被指定成了 "chaindata" 文件夹。这一文件夹会被自动创建),而且还使用了 "genesis.json" 配置文件进行了初始化流程。

然后我们使用以下命令来启动 geth:

geth --datadir=./chaindata/ --rpc

--rpc参数会让 g​​eth 接受 RPC 连接,这是让 trufle 连接到 geth 的必要条件。

再打开一个命令行窗口,并使用相同的参数启动 Mist(或者以太币钱包):

mist –rpc http://127.0.0.1:8545

-rpc参数会让 Mist(或以太币钱包)连接到我们之前启动的 geth 实例。

然后在打开 Mist 窗口之后在 Wallets 标签页里点击 Add Account 来创建一个新的钱包。

注意我们在使用一个私有的网络。一定要意识到这点,相信谁都不会出于开发目的就想在以太坊主网络里花掉自己货真价实的以太币。

在这里我创建了一个账号,其密码为 “123456789”。在真实的使用场景下,密码的设置应该更复杂一些。

再打开一个新的命令行窗口,运行以下命令:

geth attach

这会开启 geth 的控制台,这样我们就能与之交互了。

如果在 Mist 的界面上创建了主账号,我们就能在 geth attach 命令打开的控制台中运行这条命令:

 miner.start()

它会启动一个矿工,后者是一个确认交易的过程。在数秒或数分钟后(取决于你的计算机有多快),以太币的余额(还有主账户里面的余额)应该就会开始增加。

请注意,如果没有足够的内存,那么挖矿过程可能根本不会执行。你可以使用命令miner.stop()来停止挖矿。

现在再打开 “truffle-config.js” 文件,然后把它修改成这个样子:

module.exports = {
  // 不妨查阅一下 http://truffleframework.com/docs/advanced/configuration
  // 来看看自定义 Truffle 配置的更多方法吧!
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*"
    },
    ourTestNet: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*" 
    }
  }
};

ourTestNet 是连接到 geth 实例所必需的配置信息。在默认情况下,geth 会在 8545 端口上启动。

接着在运行 "geth attach" 的命令行窗口里运行以下命令来解锁账号,这样才能在 Truffle 把这个账号用来部署智能合约。

personal.unlockAccount('0x6AC4660c960Aaf5d9E86403DDAcB4791767e5869', '123456789')

这里我使用了刚刚创建的账号的地址与其密码 “123456789”,在你进行这项操作的时候这个地址和密码应该是不一样的。注意这里的密码是按明文给出的,而当你要解锁一个真实的账户时应该采用一种不同的方法

现在,再把目光放回我们之前运行 Truffle 的那个命令行窗口,在里面运行这行命令:

truffle migrate --network ourTestNet

这行命令会将合约部署到 geth 正在运转的区块链。如果你在这之前把挖矿停掉了,那就把它开回来,不然部署过程就不会执行。

如果部署顺利完成,你就会看到输出信息:

现在运行以下命令启动Truffle的控制台:

truffle console --network ourTestNet

然后运行这两条命令:

Wrestling.address
JSON.stringify(Wrestling.abi)

然后应该就能见到如下图所示的输出信息:

输出信息的第一行显示的是已部署的摔跤比赛合约的实例的地址。 第二行显示的是摔跤比赛合约的 ABIABI 基本上就是对合约的一个描述,它包含了一个将合约的函数、变量还有其他东西放在一起的列表。

如果要复制在这里显示的合约的地址和 ABI,那就得把单引号(在上图用红色箭头标出的两个单引号)删掉。

现在再把目光放回 Mist,我们要打开 contacts 标签页,然后点击 watch contract。

然后我们便在弹出的窗口中填入已部署的摔跤比赛合约的地址还有 ABI。

点击 “OK”,然后这个合约就会在你的 watched contracts list 里面出现。点击它就会弹出合约界面。若在合约界面往下滚动,你就会看到如下图所示的内容:

接着使用 select function(图中黄圈标出部分)这一部分功能来和合约进行交互。这就跟之前使用 Truffle 控制台来和合约进行交互一样。 就这样,我们见识到了 Ganache 和 geth 的用法。如果你想将一个合约部署到真正的区块链,那就应该用第二种方法,并且将 geth 连接到主网络。

注意:Mist 自身也能不借用 Truffle 迁移系统而直接部署合约,可以看一下该流程的示例视频。不过在实际的开发过程中使用 Truffle 会更有趣一点,因为若能使用模块化方法开发智能合约,就可以包含并导入多个其他的智能合约或脚本了。

注意 2:你随时都能用合适的记事本应用编写合约的代码,然后使用某个可信的第三方门户将合约部署到以太坊主网络,但我建议最好先不要这么做。

本教程项目的源码可以点击以下链接查阅:

devzl/ethereum-walkthrough-2

总结

我们见识到了 4 种开发和部署智能合约的方式:

  • 第一个是使用 Truffle 和 Ganache。由于我们直接复制了上一章教程中的代码,因此我想提一点,最流行的文本编辑器或 IDE 都有给 Solidity 提供支持的能用的插件。有些插件仅提供了关键字高亮显示,另外一些插件还会提供一些其他方面的帮助。
  • 第二个是将代码从 Truffle 部署到用 geth 连接的区块链上(或者用图形界面应用 Mist 部署到 用 geth 连接的区块链)。
  • 第三种方法是使用 Remix 编写小而简单的合同,并将代码部署到 Mist 中,也就是初学 Solidity 时所用的那种方式,如前面链接的视频中所示。
  • 或者表演一下真正的技术,用个简单的文本编辑器编写一个合约,再用个不知名的第三方应用的拖曳部署功能来部署你那未经测试的合约。

下一章教程,我们将讨论到安全性,因为我们的 “摔跤比赛” 的脚本还远未准备好在真实环境中运行。

在更下一章,我们将见识到代币的创建还有首次币发行(ICO)。

如果你喜欢这第二章,不妨在推特 @dev_zl 上找我聊聊。

本文的版权归 Tnecesoc 所有,如需转载请联系作者。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏芋道源码1024

分布式事务 TCC-Transaction 源码分析 —— 项目实战

1. 概述 本文分享 TCC 项目实战。以官方 Maven项目 tcc-transaction-http-sample 为例子( tcc-transaction...

6407
来自专栏深入浅出区块链技术

智能合约开发环境搭建及Hello World合约

2368
来自专栏区块链大本营

千万别惹牛人!小哥被盗22元后,整出了这篇以太坊钱包安全攻略,黑客看完得哭了...

对于区块链动辄几十万行的代码量,安全漏洞时不时就冒出来。敏锐的黑客们,虎视眈眈地盯着漏洞的闸门,一旦看见开闸,便以迅雷不及掩耳的速度展开偷袭。

1222
来自专栏区块链大本营

教程 | 只用5步,教你从零用Truffle打造第一个以太坊Dapp!

7656
来自专栏极客编程

使用truffle部署以太坊智能合约到区块链

truffle是以太坊(ethereum)开发智能合约(smart contract)过程中最受欢迎的框架,本教程来安装构建一个基本的Truffle项目并部署一...

1313
来自专栏申龙斌的程序人生

同时给200多人发送比特币,程序员是这样做到的

在币圈中,使用自己的钱包给他人发币时,就跟平常的微信、支付宝扫码付款类似,输入BTC地址和金额,再输入支付密码,不管对方是否在地球的另一端,不需要任何银行的中介...

1632
来自专栏极客编程

如何用Python和Flask框架开发以太坊智能合约

将数据存储在数据库中是任何软件应用程序不可或缺的一部分。无论如何控制该数据库都有一个该数据的主控。区块链技术将数据存储到区块链网络内的区块中。因此,只要某个节点...

1543
来自专栏区块链入门

第二课 如何实现以太坊最简智能合约“Hello World”的运行

如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇。 就先学习任何编程语言一样,入门的第一个程序都是Hello World...

964
来自专栏区块链入门

第六课 技术小白如何开发一个DAPP区块链应用(以宠物商店为例)

通过逐步的指导和截图举证,一步步带领一个技术小白完成一个宠物商店DAPP应用的开发和部署。

2214
来自专栏丑胖侠

以太坊实战之《如何正确处理nonce》

问题概述 以太坊系列(ETH&ETC)在发送交易有三个对应的RPC接口,分别是eth_sendTransaction、eth_sendRawTransactio...

3906

扫码关注云+社区

领取腾讯云代金券