以太坊教程:搭建环境、编写编译一个智能合约
dancing520
发表于 2022-11-6 21:10:54
633
0
0
N& e& p0 K. W. O4 [
以太坊是什么1 ^( n7 Y! }4 {
5 \! K/ M1 L. k! W$ ^+ K/ s
以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。3 k, K8 B+ Y9 {& L2 C& f- e
' M3 q5 V9 A: G' W7 G/ Y, j& z
以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。
9 g* F, z( [) {# E3 w1 o- O
以太坊区块链是什么?$ m0 c0 f4 {4 ~- ?
c7 L+ I5 @% Y# o( A
以太坊区块链有2个主要组件:
数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。6 z* N4 _8 H! A4 Z: M0 D/ R" y
9 O s4 n: S2 j, b' L/ s
代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。* {3 }7 d, o) n* l* t9 U& f
可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。
要准备的基础知识" m9 `, b4 p7 x2 ]
为了进行以太坊开发,你应该对以下语言/技术有基本了解:
熟悉某种面向对象语言(如Python,Java,go)
HTML/CSS/Javascript
基本的命令行交互如Linuxshell命令$ ?' x! q Y+ @2 m
理解数据库的基本概念2 E6 E. [0 p2 _
为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。5 t. d0 K% |3 w' D6 p- l' @
示例:一个以太坊投票应用: w6 U4 @" _& w. A7 [; M
以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。$ a. N5 C" v. ]" Q0 d3 v) E
9 i3 k6 \+ n+ T& a
本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。
现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。# j# m; Z7 F+ Q/ {4 n. { } W: K
以太坊开发环境搭建9 l8 `8 ?, ^# }6 M- x# m
8 f/ b4 b) E! |
Linux: e% m2 a+ v4 F' [
# U; P; ^6 O( E3 f/ P, ^
示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。
" p) L* W) L3 k# i) ^: s% u
我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。: k: T v- P+ p1 d$ e' l
4 I, P$ ?: `; T _" o# C4 |5 O
下面是安装过程:5 T4 v7 x3 W7 ~0 g% u& U% c N
/ e9 \ @3 w' C3 u+ x# H6 o
$sudoapt-getupdate8 o) o" D1 g( r f5 B& d& ^# v, W' j
% A4 N Q- z& {* U7 Q
$curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh6 G1 W5 Y& c) c5 z: w8 {
$sudobashnodesource_setup.sh
% f0 E G! m/ _& @
$sudoapt-getinstallnodejs2 A5 j) P, b1 }& Z
: k0 Q8 y2 v x9 e: ~2 i
$node--version
. d+ X" @5 P" @6 R
v7.4.0
$npm--version4 \! I) Y% \# Q
4.0.5- j* G# i3 l+ _# u- o
, \/ F0 ]- i! _( a+ w7 ]* ]
$mkdir-pethereum_voting_dapp/chapter1* |1 E Z2 J0 `2 ^
$cdethereum_voting_dapp/chapter14 V3 p- X [ X( E9 N* t1 s1 ]7 R
$npminstallganache-cliweb3@0.20.1solc" u' q: S# C3 _8 H9 n$ _" |
# k+ u3 u y3 E8 n" ^5 ?* }
$node_modules/.bin/ganache-cli
. p2 U$ F3 D! T& F' G3 X# U: T
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。
GanacheCLIv6.0.3(ganache-core:2.0.2)3 `& z' e( B( n Y, x
AvailableAccounts
* y; k f) @, o. A* U: f% t; ^
==================
9 s5 N. c) M) i" E6 j0 J
(0)0x5c252a0c0475f9711b56ab160a1999729eccce979 E; |3 R$ E) @* M
(1)0x353d310bed379b2d1df3b727645e200997016ba3
# M: B9 Y/ _; p& Z
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
! y0 m' L: n9 R
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798: ~" N6 d- Q' x: w- Q
, `5 E" I0 ]1 Q0 m
(5)0xda695959ff85f0581ca924e549567390a00340588 S2 n! B2 q2 \1 f$ u& M+ y5 j1 j
) }/ d! @0 k2 m* ]* x, n5 V" V
(6)0xd4ee63452555a87048dcfe2a039208d113323790; y- c' [# Z# B- p/ a% W
0 z8 A r o& y- ^ r
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14. a0 s5 I/ Q- r6 o4 Z5 V
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36' N& d: ~$ s/ F! B# ]# d
( i! [* l( r$ c1 `3 h' e
PrivateKeys9 T; f6 m* [3 ?7 v2 T
- B% p/ R5 K( p& ~
==================+ x/ X% k- n% |. }- R/ t3 n5 g
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603! k0 \7 W+ T% i) y" I) _
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99( @$ N8 R5 B7 Q$ P4 ]+ _& V2 Z
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430# V* ]' x0 y, j/ M5 @
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
$ ], d, y4 |3 m4 f- a
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
! Y' E' i A b4 K. Y; u
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
4 k% f2 w( C( F( T j1 A6 Y
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
6 c- Y4 ?# H3 Q8 _! I
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0/ w5 Q! F& Z8 b4 y1 y
HDWallet; y2 ~( _3 l D* `+ s/ O6 W9 b
==================) K" `# ~% m' N* \* y
. s6 N' A# u g3 }- R
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella; q" `& t+ V8 E& X" _' ]
% x0 p; n; l% Q% u- s- a% S+ |
BaseHDPath:m/44'/60'/0'/0/{account_index}
Listeningonlocalhost:85458 h" K: Z+ R: z6 Z% B
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
MacOS6 s7 B% v( q& p" z! Q
3 z* S, p; d& E: N8 @2 _8 b
如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。
; o5 f1 {$ ^: U5 l
$brewupdate
$brewinstallnodejs, T/ o$ M3 l2 ^8 i8 N
$node--version
! f3 d% T* b0 `5 Y) i) |& D5 g
v7.10.0
6 H; \! o: H& L) ] I& T1 u
$npm--version
, y G8 r5 f; y/ x, D
4.2.0) t7 U3 x% V* T* r1 Z$ ]
$mkdir-pethereum_voting_dapp/chapter1& s6 _9 \% S. J4 K
( c$ I0 U" v6 U# R
$cdethereum_voting_dapp/chapter1
) [9 P h7 L. c/ i" P
$npminstallganache-cliweb3@0.20.1solc
1 m2 a% r! G- V p8 @/ I0 D
$node_modules/.bin/ganache-cli C. H' R* s. K" `* ^; C5 { x1 [
( ~, ]% j5 f8 H& o
我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。1 ~* U; t9 ?. X; K& X% @- d+ r/ @
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。4 w8 Q% X) g! g0 y1 n7 _( k" V3 `
GanacheCLIv6.0.3(ganache-core:2.0.2)2 t# D7 C; u; z5 g9 l
AvailableAccounts) d0 R0 e' N% ^8 {& v/ y f
==================
) L: t) W- O( V8 Z) X* K5 T
(0)0x5c252a0c0475f9711b56ab160a1999729eccce978 Q$ ?/ l) U. Z; K: U9 D
(1)0x353d310bed379b2d1df3b727645e200997016ba3
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23+ X/ i6 n! A* |, R$ z
K! G1 x0 I3 C3 t( z! e3 A7 p: C
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec59 C4 x) t' _) ^# [+ @4 M5 v4 P" J1 U
2 |+ B! D! ]3 H/ I; E3 R; |
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd27980 }) x' H% }8 Q) w2 \
- S `2 }: K( w( B
(5)0xda695959ff85f0581ca924e549567390a0034058
(6)0xd4ee63452555a87048dcfe2a039208d113323790
9 D: ]* G( z9 I
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d141 x4 r# ` P6 M' G2 u3 G
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42$ i7 } C/ ^5 I6 j, k, I# @: l
$ R! w7 z: q. |7 e% I# F4 d, [: g
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36
: n' T' a( C, M1 O
PrivateKeys
==================6 @7 W; \4 z5 p3 m+ f
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b# |- W4 i4 O) _* n3 G$ ^! W9 M
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603, R$ _4 \! n" Y( _+ U
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
, z$ b+ G6 `% u8 g! m# L
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a83 q- h# j0 O7 |/ t. ^; T h
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
# X- q9 l3 p5 z, b3 B& B
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9# W* G6 N; n, N: k) Q
" p5 y0 l/ r( o5 O1 B4 K, R9 J) @
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
. H2 s4 c8 E) b1 |- m( ?7 T& H
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
2 _4 b; C. G! ]* ~7 U: W7 `
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0) t: ~- { W/ N. s% u- w% g- M
HDWallet R+ i* L& l( g5 {$ S! j. P
+ J2 c9 F2 q9 w. D/ H% _
==================1 P; K! D' P# V6 t8 J$ a" D
& z# f0 V0 J6 b. K
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
BaseHDPath:m/44'/60'/0'/0/{account_index}
m+ J% |3 {/ _
Listeningonlocalhost:85456 @" S! d5 j# L& q, y* ?
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
2 X- T) S6 l: ~) r# M
Windows, R: D0 ^/ W2 [8 Q' I
安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)
+ m s: C0 a) k0 p n* N, N. ~2 }7 F3 \
安装WindowsSDKforWindows
1 ?% ?- h. g+ e
安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH
2 \2 R5 j1 t! z
安装git如果你还没有安装并加入到PATH
2 e1 x6 U5 W* e5 i# y( U$ b
安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径
: Q9 J+ e+ r4 R# y# S, j7 o
下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS2017
执行命令npminstallganache-cliweb3@0.20.1solc
SolidityContracts
1 x+ k; n, E$ J$ z( \4 D% O
现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。! M7 {8 P5 n% ?0 d3 W* {, [
我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:9 x- F R1 i- B7 o4 Z0 f
, |" w6 S2 I9 e7 Z) J% K9 @- S+ S
一个构造函数,用来初始化一些候选者。
一个用来投票的方法(对投票数加1)( K8 c" g- }4 X% }) C1 y7 L% a
# [# {- ]) v# j! X
一个返回候选者所获得的总票数的方法! x% N+ @3 |, y( I9 _
当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。
pragmasolidity^0.4.18;+ V; \& m; U4 J6 _( K3 O* W. w
3 {- z. H: H7 [: w
contractVoting{
7 \/ _( s, q2 ]* g; \/ Q
mapping(bytes32=>uint8)publicvotesReceived;
bytes32[]publiccandidateList;
functionVoting(bytes32[]candidateNames)public{; ?8 x3 s4 ^, n
candidateList=candidateNames;
. q4 F. J+ U P- T( O ~+ g
}- k& z3 A+ F7 M# U8 [
functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){
require(validCandidate(candidate));
returnvotesReceived[candidate];- k5 t: ~0 c G
4 a ^2 L/ I/ f6 B S! w
} ]* }) C( Y& c; S- `8 f9 u& O
7 z7 M& ], W8 e6 A" T& p8 r6 s
functionvoteForCandidate(bytes32candidate)public{
* N- }/ K% I! R! g
require(validCandidate(candidate));
+ O- R5 z& V4 o8 m
votesReceived[candidate]+=1;( T' F$ x+ D$ m( O7 e6 [8 c
+ g7 f: y# `2 v! F5 v
}2 N' l% V9 ?6 O# n
2 O9 j. V7 D. ^. T
functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){
for(uinti=0;i
将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。
2 ^" t$ q) w- D* X$ K' K& ~0 w
代码和解释
1 X, g. d* e- \/ v0 |. H8 }; ^
Line1.我们必须指定代码将会哪个版本的编译器进行编译2 X: d9 G- {5 e5 s" w
Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。0 }( v/ o9 S* H! e1 p7 y2 s
. ?' ^+ e& m: ~! \4 N8 c% F
Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。, @- m( x8 J2 F; M- Q2 O
# x) D( C& O+ ]
Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。
你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。8 H, s+ U$ W7 V+ r5 B4 y7 M4 n
你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。
编译智能合约2 T2 q+ D( L" c% N% w- [ m
我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。 P9 m5 s* n! ^9 \% \( H5 d
首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
确保与此同时ganache已经在另一个窗口中运行7 A% u; F1 g1 R! o* I
为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。
$node
Inthenodeconsole6 i) H2 Z: `. m! B& s
6 h8 V1 V6 D8 r& ^, W. ^7 B
>Web3=require('web3')
>web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));
>web3.eth.accounts I: z8 ^' R: q' d/ p" H
* X! O8 |0 ^/ F& [6 m! u
['0x5c252a0c0475f9711b56ab160a1999729eccce97'
: L/ | L8 O! W) f4 t" K" v$ B
'0x353d310bed379b2d1df3b727645e200997016ba3'
5 c7 t" X. q$ \* \4 [
'0xa3ddc09b5e49d654a43e161cae3f865261cabd23'
'0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5' y* H d! x0 {% |) F$ j
1 n% @6 V# G# R
'0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'
0 W' @, ]& q @5 f/ n! z' F
'0xda695959ff85f0581ca924e549567390a0034058'
'0xd4ee63452555a87048dcfe2a039208d113323790'# g4 k! ^- ]8 m' }. `2 m
. ^5 R) ?3 w& A( z
'0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'
9 ]2 @& o5 R9 V) {
'0xba7ec95286334e8634e89760fab8d2ec1226bf42'- G A. l1 l3 l+ F0 F# t* H
'0x208e02303fe29be3698732e92ca32b88d80a2d36']
>code=fs.readFileSync('Voting.sol').toString(), v" a8 k: d R% C" s+ q7 d0 O+ j
>solc=require('solc')
>compiledCode=solc.compile(code). l7 C/ f7 E7 q3 j
当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:
1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。
2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。$ t$ B S- Q+ D9 e( \- C
0 }" ^ ?) V! U1 | H {% A- G
教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人