以太坊开发演练 :Truffle,Ganache,Geth 和 Mist
李悔之2015
发表于 2022-12-2 09:56:46
275
0
0
Truffle:是以太坊的开发环境、测试框架和资产通道。换句话说,它可以帮助你开发、发布和测试智能合约等等。你可以阅读有关Truffle套件的文档,了解更多信息。
. \6 g, s* U- n
Ganache:以前叫作TestRPC,如果你读过几个月前的教程的话,有可能他们在使用TestRPC的情境下配合使用了Truffle,它在TestRPC和Truffle的集成后被重新命名为Ganache。Ganache的工作很简单:创建一个虚拟的以太坊区块链,并生成一些我们将在开发过程中用到的虚拟账号。
5 I* ]( Z0 Q% Q( E4 s
Mist:Mist是一个分布式网络apps的浏览器,相当于是只针对Dapps的Chrome或Firefox。目前来说,它仍然是不安全的,所以你还不能在不受信任的dapp中使用它。
以太坊钱包:它是Mist的一个版本,但只启动一个dapp——以太坊钱包。Mist和以太坊钱包只是UI(用户界面)前端,我们还需要一个将我们连接到以太坊区块链的核心程序(它可以是一个真正的以太坊区块链,也可以是一个测试版的)。
Geth:Geth是把你连接到区块链的核心应用程序,它也可以启动一个新的区块链(在我们这个示例中,我们将创建一个本地测试网区块链),创建合约,挖掘以太币等。5 x& k& H# t8 z9 r" i- Q: i
) Y8 e7 r( C, }& m. m2 b/ L* h4 M; R
我们会先使用Truffle配套Ganache,然后使用Truffle配套Geth和Mist。; j! F5 ^. D8 U( H7 v' X
" d% e6 M! q, t
安装" N' z) Q0 h1 }9 u9 a; f' E/ @
本教程的要求是你要知道它是什么以及如何使用命令行工具,并且你要稍微熟悉NPM。
Truffle
打开命令行,并输入:
npminstall-gtruffle, O/ }- d. W* d$ D0 z
如果出现错误,建议你多阅读有关Truffle的文档。
Ganache( ?1 g- C) q/ S! | k7 _
. U+ T% U# @4 R) R3 H- D. z& Y& x
然后,安装Ganache的命令行界面:
npminstall-gganache-cli5 v. Q/ n# }: G! k& G6 S
! d& o0 y. \ L# f9 M0 Z% g; Y
如果你对此不是很确定,点击此处访问Ganache的Github页面。3 n7 q% y& Z- P
注意:这是Ganache的GUI(图形用户界面),不过既然我们都是程序猿,还是要用CLI(命令行界面)。0 r h$ F8 J$ [* T
开始吧" W. b# V1 i. Z2 Q
) p6 y7 c+ S, G4 L# z' L; o) d
首先,创建一个新的文件夹,并输入。
) Z# t' g/ N! D- L
truffleinit0 Q$ {# n! O V! U9 ]
" d8 x8 w- A& U" }% U8 G7 `" E
它会初始化一个空的truffle项目。
然后从上一个教程中复制Wrestling.sol文件,粘贴到到contracts文件夹中。接下来,打开“migrations”文件夹并创建一个名为“2_deploy_contracts.js”的新文件。Migrations只是帮助我们将合约部署到区块链的脚本。7 p5 @4 D* _& {. K7 \4 E
将下面的代码粘贴到里面,然后保存。
constWrestling=artifacts.require("./Wrestling.sol")
0 D Z# ~' u( o [* X* X4 N
module.exports=function(deployer){0 W, X9 f! g" d' Y7 j
4 Z4 F. r/ W* H8 n2 [8 J3 U6 \% a g
deployer.deploy(Wrestling);
- d' b f# E4 y! Q9 b
};! d9 c4 k( f9 X8 q3 b, @: X
第1行是用来导入“Wrestling.sol”文件的(从“contracts”文件夹导出),第4行则将它部署到区块链中。) q5 q# v9 j# `
现在,回到根目录,你会看到两个文件,“truffle.js”和“truffle-config.js”。如果你在Windows上操作,那就删除“truffle.js”;如果你在另一个系统上操作,删除其中一个或者同时保留它们,都不要紧。这样做的原因是,在Windows上有一个命名问题,当我们想要执行Truffle命令时,它会打开“truffle.js”配置文件而不是读取里面的数据。 j! K0 G4 L) F. h7 U
8 M( u7 i; r: f& Q9 w0 r
我是在Windows上写的这篇教程,所以我把“truffle.js”文件删掉了。然后我会把这段代码放入truffconfig.js中:
# e: ^. ~6 e+ _ Q! R2 R
module.exports={
//See% p4 f' j F ?9 m6 t, c; J
7 }" G" r/ a1 X& H
//formoreaboutcustomizingyourTruffleconfiguration!1 @4 F" n! y" H0 W
( O5 d+ O2 m- M+ n
networks:{; N; Z& B+ x( e7 o2 e( F% @
development:{
; T; P) f9 P) W' u- [* J
host:"127.0.0.1",( Z: d! S1 V5 c/ B
port:7545,/ z8 ], F8 J5 o" {; |, O- j
network_id:"*"//Matchanynetworkid. y, d) i. Q# A, A7 |* g! c3 w3 M8 v! Q
}
}1 o ]% X0 `- r' K7 x9 N/ Q4 x9 o
};
$ T( T' _) o* s
基本上是说,当使用开发网络时,使用端口7545,连接到127.0.0.1(localhost)的主机。
现在我们准备在区块链上测试代码啦!+ V$ h6 U0 g I
8 R3 i2 K9 c1 W% W7 I/ |
测试我们的代码6 s6 A7 ^* H& J0 ?* n
2 s& Q$ T3 y3 K8 K9 d) a( V
在第一部分,我们会使用Ganache。% C" u" a0 h- B! q/ f- t$ m
启动一个新的命令行,并输入以下命令:( l! ]5 X1 [2 b+ f
4 C' F$ N: b; j5 p( R" q
ganache-cli-p7545
" i. d: k) E) P, o4 A9 Y- w. W8 k
它所做的,就是告诉ganache-cli从端口7545启动。9 [0 E" t: h0 H3 Z% L: Z) a
$ k/ H) e6 h0 O% ^
Ganache会为我们生成测试账户,默认情况下,每个账户都有未锁定的100个以太币并,所以我们可以自由地从那里发送以太币。第一个示例账户就是这个家伙:/ V' [$ w! S5 p0 H7 g
现在,回到我们的第一个命令行界面,执行两个命令: O6 r" } I* f2 @% {. j; d% v
trufflecompile
3 l2 A" B1 s z( g
trufflemigrate--networkdevelopment; P" W, P9 V( Y& N) g5 v( {
' a' f$ U. m, o
Compile将把我们的Solidity代码编译成字节码(以太坊虚拟机(EVM)能理解的代码),在我们的例子中,Ganache模拟了EVM。% R [5 f3 h, n$ P
+ E: G) v# @- f5 f9 G/ q+ a' j
Migrate(迁移)会把代码部署到区块链,我们之前在“truffle-config.js”文件中设置了“development”网络,我们可以在那里找到区块链。3 ^+ R) G6 S- p4 i% I9 `
现在,如果一切都按照预期进行,你应该会在终端上看到: _# v9 w% H, |5 Z
0 U0 t" m x3 A, j4 \# N+ O* ?9 a' D
注意,这里显示了实例化的Wrestling合约的地址。
; B% {' q% a3 u/ o
在ganache-cli运行的命令行界面上,你可以看到正在执行的交易:
注意,它显示了实例化的Wrestling合约的地址。$ D8 t, k3 b' X
现在输入以下命令启动Truffle控制台,这会帮助我们与ganache的区块链进行交互。4 K1 p7 m: V5 \" G
truffleconsole--networkdevelopment: ^- O7 k+ M7 Z2 w9 s
) R7 |) L# E; P$ \& J- n# S8 f
首先,我们会执行这个命令:9 L5 J' {5 H: D% F1 ?/ T6 X
account0=web3.eth.accounts[0]
. C* u6 n- h8 N# t. e5 ^2 M
account1=web3.eth.accounts[1]
$ n& c& N2 a7 S3 v8 y1 ?; K
它会把第一个帐户的地址分配给变量account0,第二个帐户分配给变量account1。Web3是一个JavaScriptAPI,它将RPC调用包装起来以方便我们与区块链进行交互。0 [, I1 u! F& C0 y
然后我们输入:" M% G3 ]+ E" } `
% c3 N" d- @+ `3 j' R! v) F
Wrestling.deployed().then(inst=>{WrestlingInstance=inst})4 e! B3 I: X- m5 s" R* W9 D6 O
它为truffle部署到变量“WrestlingInstance”的合约实例分配了一个引用。' N0 h6 {1 A3 U7 y* X6 J& m
3 Z* |* T$ s% k# t# C4 f) X& t
执行下一行:
WrestlingInstance.wrestler1.call()7 ]5 _5 {8 _' b7 @& M) P# j( E- Y
它将返回参与者1的地址,在我们的例子中,这是第一个帐户。在migration(迁移)过程中,Truffle会从Ganache选择默认账户,因为我们没有在迁移过程中指定另一个帐户地址或是Truffle配置文件中的另一个地址,所以这是第一个账户。
然后我们把第二个账户注册为一个对手:
: Q1 N& s1 J5 a6 `/ H
WrestlingInstance.registerAsAnOpponent({from:account1})0 X! d. ?; d( P& [7 [' S* P( n5 ~
在这里,“from”指令会告诉函数应该从哪一个账户触发交易。7 u9 h2 n( O* L. A' B5 m: d
在执行这一行之后,它应该会返回类似的内容:; r* I$ _4 r# b# i
5 C3 h$ p0 _3 A' A8 D
注意,该项交易使用了Gas,并且触发了“WrestlingStartsEvent”事件。5 i$ G5 {- x+ K
4 _' a! W; p$ C' u3 J7 X" a% u
你可以通过执行下列代码来检索第二位参与者的地址: ?5 ^2 `9 f1 ]# d& _6 p
WrestlingInstance.wrestler2.call()
$ X4 ]2 |4 }1 r. ~' S5 f' t/ L. Z
现在,玩家们可以开始角力了:
WrestlingInstance.wrestle({from:account0,value:web3.toWei(2,"ether")})& Y% f# @$ Q) a# z( h! ~
, m2 D! j4 D* }0 h5 ]6 D
WrestlingInstance.wrestle({from:account1,value:web3.toWei(3,"ether")})3 w* ]+ R9 x; S0 d9 F, p9 G8 R
//Endofthefirstround8 J1 e' e/ q2 w4 H
WrestlingInstance.wrestle({from:account0,value:web3.toWei(5,"ether")})& Z2 J9 N5 j+ `
WrestlingInstance.wrestle({from:account1,value:web3.toWei(20,"ether")})
//Endofthewrestling5 `; N+ \! ]7 J) H
“value”指令用来在交易时发送以太币。“web3.toWei(5,“ether”)”意味着发送5个以太币,这个值会被转换成Wei。Wei是以太币的基本单位(最低面额)。点击此链接,可以找到更多的信息。1 O" t! ~2 {" B" Z; p
在执行最后一行时,account1会是大赢家,因为我们总共投入了23个以太币,比我们在account0投入的两倍还要多。7 T0 b' G4 G o- W
给你留个小练习:从合约中提取以太币。
# G# N" D" W& w
现在,靠你自己研究如何使用Truffle和Ganache的高级功能啦。你可以从阅读文档开始,或者,如果你感到读不懂或者想要加强你对刚才所学知识的了解,这里有一篇很好的Truffle介绍。
Q( S* I, M0 J$ w& m5 a X$ I
geth如何在这个过程中发挥作用
好了,我们已经使用了Ganache来进行开发,现在我们想要试一试更接近真实运行环境的东西,就算只是让自己更熟悉运行环境就好了。& Y6 N A d) z6 B8 d7 I+ y4 I
3 X& r' e0 v% C) O2 P
安装
首先,下载geth。在Windows上,你可能需要将geth的安装文件夹添加到你的PATH变量中。
下载Mist或以太坊钱包。其实使用起来都是一样的,所以选择哪一个都可以。
创建本地私有测试网络
在同一个根目录中,创建一个新文件,并将其命名为“genesis.json”。然后把下面的内容复制进去。
* g. k% V. F% O3 x: ^
{
# ~7 y+ {, b6 O8 ~- H# ~. b
"difficulty":"0x20000",
; j, m* q% P- F3 @" k
"extraData":"",
"gasLimit":"0x8000000",
: P6 U. B) ?5 j
"alloc":{},7 X- \4 f3 Q, Y
"config":{
"chainId":15,
"homesteadBlock":0,8 \: ] d! V* n1 i- ], r( o) y+ B
"eip155Block":0,; N: `% ~5 O! U/ ]. p) f
"eip158Block":0
}3 H, |/ [: H7 a3 @9 K9 E* P4 O- j
" R5 C. D4 D4 y. J$ Q
}7 {6 Y+ I& j9 y$ ]
“genesis.json”是一个配置文件,geth需要用它来创建一个新的区块链。现在了解这个文件的内容并不重要。" ?. B; p3 C0 |: _& _# Z
' G/ p. K ~3 d; A! a2 b
如果你在没有指定任何参数的情况下运行Geth,它会尝试连接到Mainnet。Mainnet是以太坊的主网络,是真正的以太坊区块链。 q, y0 s; W+ D
, l% x7 m- S0 b$ @# T& s
如果你在没有指定任何参数的情况下运行Mist,那么如果geth实例也正在运行,它就会报错。但如果你让Mist连接到正在运行的geth实例(我们将在稍后操作),它就会正常工作。如果你在没有geth实例运行的时候运行Mist,它将会启动一个新的geth实例,并最后向你询问它应该从哪一个区块链中下载区块。8 _$ V0 U$ i0 \6 j$ g. O3 w$ u
8 m& N; S1 j! Y9 m5 J: y6 x3 t, W( j6 Z
虽然有公共的以太坊测试网络,但我们会使用之前创建的“genesis.json”文件在本地创建一个私有测试网络。
$ g" m0 d7 q: o6 f& w# v
启动另一个命令行界面并输入以下命令(确保在项目根文件夹中运行它):
8 G, S' U3 H" E. \3 ~+ y# W" F
geth--datadir=./chaindata/init./genesis.json
~" u1 p1 V2 r8 d
启动geth并指定区块链的存储位置,这里是在chaindata文件夹中(它会自动生成),然后我们用“genesis.json”配置文件对它进行初始化。" e+ w8 q; V- s! G# c
接下来,我们使用以下命令启动geth:
geth--datadir=./chaindata/--rpc
; ~) J- n3 e, M2 d; g7 k
用“–rpc”参数让geth接受RPC连接,这是很有必要的,这样truffle才可以连接到geth。. W# [* ]6 q ]% R
& o+ R r/ z" L% z/ c4 c( E
打开另一个命令行界面,启动Mist或以太坊钱包,使用相同的参数:) f4 @# H3 M2 v9 E
6 _9 J$ Y$ Y; L* W
mist–rpchttp://127.0.0.1:8545
( q6 ?/ @0 `1 w! _1 c1 I$ V
“-rpc”参数让Mist(或以太坊钱包)连接到我们刚刚启动的geth实例。
" g* s' M. o. L( b* ?
在“钱包”选项卡中,按下AddAccount(添加帐户),创建一个新的钱包:; u, o) J p- j8 N4 n+ {1 Z
' B F, C9 c5 d+ o
请注意,我们正在使用私有网络。注意,你不应该为了开发,而在主网上上使用以太币。, D( _( ?! T9 \4 s5 q# b3 R
我会用密码“123456789”创建一个帐户。在真实环境中,要使用更强的密码哦。
4 M$ G5 n; L& j4 G1 N$ [* P4 ~# s7 O
打开一个新的命令行界面并运行以下命令:: b: k4 Q0 Y& W) r7 [" ?
x" h& N( `. B" ?
gethattach
h7 C+ k% G) B0 r7 x8 B; q
它会运行geth的控制台,现在我们可以与它进行交互。
无须通过在MistUI上创建的主帐户,我们将在“gethattach”控制台中运行这个命令:
miner.start()
2 t( \; B% p2 o, _1 n
它会启动一名矿工,这个过程将会确认交易,而且在几秒钟或几分钟之后(这取决于你的电脑),你应该能开始看到你的余额中新增了以太币(以及你的主帐户也会有)。2 s4 P$ f4 M: V8 I; B7 W# f
请注意,如果你没有足够的可使用的RAM,它可能根本不会开始采矿。你可以使用“miner.stop()”指令停止挖矿。$ E: v) l) d# v
现在,再次打开“truffle-config.js”文件,像这样修改它:8 X8 m" g1 F4 V3 l# V
! y- C! `; V" o9 v( [2 o' W- k
module.exports={
//See, k i* Z! B0 X9 i- j7 @7 E
//formoreaboutcustomizingyourTruffleconfiguration!5 W3 Z9 \! q, V( |: C
# }5 M8 J- ]5 `8 h( s [1 ?6 V
networks:{% e! g" [# \# j% F0 v
development:{
host:"127.0.0.1",+ V! G) r2 a. N
# E* i4 X ]! ^5 K1 n
port:7545, ~; o% G4 I" I& P! \) C
network_id:"*"
7 W# [5 j! s, u1 [6 l, ~
},- o% V( J: R: V! ?9 ~" k
: T M" T0 B, j7 {) F, q
ourTestNet:{2 `% ~9 [7 p4 y4 ]5 ^+ j
host:"127.0.0.1",
. K L5 h9 s' }: j, H9 D3 j( R
port:8545,
3 u D# v: u4 _. Q, V0 e6 q/ ]0 q
network_id:"*"* K* j4 p# A! | ~+ V/ M
}
% i, L+ e; ]$ \+ v0 y5 U
}
};$ H! O8 D* `% V. I
4 R% Q. F% f9 F) f: j4 G% v; }
“ourTestNet”是连接到geth实例所必需的配置。Geth在端口8545上默认启动。$ k6 {6 G) R& v6 C$ A% T1 ?6 @
3 j3 ?; b$ J. g1 \
在我们启动“gethattach”的命令行界面中,我们会解锁账户。所以有了它,我们就可以从Truffle迁移智能合约。使用以下指令:' w, T k8 [; b
personal.unlockAccount('0x6AC4660c960Aaf5d9E86403DDAcB4791767e5869','123456789')
在这里,我使用了刚刚创建的账户的地址,在你创建的时候,它会是一个不同的地址,以及我将用于这些测试的密码“123456789”,对你来说也会是不同的。请注意,密码是以纯文本形式显示的,在真实账户中你应该使用一个不同的方法。
现在,回到我们之前发布的Geth的命令行界面,运行以下命令:
trufflemigrate--networkourTestNet1 @1 G2 [5 f1 |: p$ U* T
它会开始把合约转移到geth正在运行的区块链。如果你之前停止了挖矿,那现在启动它,否则,迁移将不会被执行。如果迁移成功,会看到这样的输出:
! P" r% ~# h1 H, R
现在,运行以下命令启动Truffle控制台:: u( h! L1 R `3 C2 x. V
truffleconsole--networkourTestNet$ x1 z9 j t& \* `& O7 o
然后运行这两个命令:
1 F! l9 i/ m4 J' e: m# k
Wrestling.address$ B! k. w9 P! I6 L5 q
JSON.stringify(Wrestling.abi)4 v* e. w' Y- ]
9 Y3 Y- T( H: ?, s; L
你会看到这样的输出:
第一行返回已部署的Wresting合约实例的地址。- Q# n- m$ |( u
第二行返回Wresting合约ABI。ABI基本上就是对合约的描述。它包含了一个函数、变量和其他因素的列表。
在复制地址和ABI的时候,删除屏幕截图中红色箭头所高亮显示的省略符号。* I3 p, u5 o' E+ M
现在,回到Mist,我们打开合约中的选项卡,点击“watchcontract.”。
然后,复制之前部署的Wrestling合约的地址和ABI:
点击“OK”,然后它将显示在你要查看的合约列表中。点击它,它将打开合约页面。如果你向下滚动,你会看到这样的东西:. H, d+ M8 H& f
3 v. r7 b* w; @8 d
使用“selectafunction”部分与合约进行交互。这和我们前面使用Truffle控制台是一样的。1 l9 ^0 n8 C" |
就是这样,我们了解了Ganache和geth是如何发挥作用的。当你想要把合约部署到真正的区块链时,你应该使用第二种方法,并将geth与mainnet连接起来。+ F9 V/ r1 b! b% _! v
注意:你可以直接在Mist上部署一个合约而不使用Truffle迁移系统,这里有一个这个过程的示例视频。虽然在实际开发过程中,使用Truffle其实更有意思,因为如果你要用模块化的方法来开发你的智能合约,你可以导入多个其他智能合约和脚本。
还有:你可以在一个基础的nodepad应用程序上编写你的合约代码,并使用一些可信的第三方门户把它部署到mainnet上,但是我不建议你这样做。3 Z9 f8 b5 s6 M/ {! `
+ c# I# L6 ?2 R" T6 G/ | E$ O/ F* V
本教程的资源库可以在这里找到:
devzl/ethereum-walkthrough-2' T3 D: W. q! n8 P2 h) x4 m
) @, U' Z$ x# D/ Y, J. ]
总结
( }6 o2 ]1 G) k5 }0 }1 ^+ z
我们已经学习了4种开发和部署智能合约的方法:6 W; z& S# L$ v+ N0 W9 ?
第1种是使用Truffle和Ganache。由于我们从上一篇教程中复制了代码,所以我想告诉你,有些插件可用于目前最流行的文本编辑器和IDEs。有些只提供语法高亮显示,而另一些则提供其他方面的帮助。+ n2 Y' h: B. H: v! s3 q5 A
第2种是将Truffle的代码部署到geth(以及Mist的图形界面中)。
% A; E. W' }; j3 x! s7 X
第3种方法则是当你刚学习Solidity时,使用Remix来编写小的简单的合约,并像之前链接的视频中演示的那样,在Mist中部署代码。3 g: F: N) z2 V3 d6 [4 P, t' K' p
第4种,你也可以像真正的牛仔一样,用一个简单的文本编辑器进行编写,然后使用一个匿名第三方的拖放部署特性来部署未经测试的合约。" r& v2 l* ^* p/ [
/ K; A# i% @, A4 U% v; G+ P8 i
因为我们的“Wrestling”脚本还远远没有准备好在一个真实的环境中启动,所以在下一讲中,我们将会讨论安全性。
成为第一个吐槽的人