以太坊教程:搭建环境、编写编译一个智能合约
dancing520
发表于 2022-11-6 21:10:54
632
0
0
. V& L* X! p' m) x0 N) ^2 ~2 k1 W
以太坊是什么
* i1 u6 D* l7 l* x" g# r5 \
以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。) M0 [* h4 T0 P; [5 O
) `3 k. T7 A' ]3 l" M
以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。/ b; h- o4 x& J. j0 z& f
以太坊区块链是什么?! {2 l. q. [/ C4 i/ R/ S. S4 j7 C k
% z+ S* {& z9 V! M
以太坊区块链有2个主要组件:
; x9 B. S2 Y; c
数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。! q2 T* G6 ?. A; [
) _+ s, C" ^* o4 N0 c2 R
代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。* x* s! R7 l+ n+ q/ [0 R
可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。& b0 u8 d) v' _
要准备的基础知识
E- P1 V h" o% [: w4 }
为了进行以太坊开发,你应该对以下语言/技术有基本了解:* A) f8 z7 I+ c- _5 R
熟悉某种面向对象语言(如Python,Java,go); `4 Q. u. H* a* I
HTML/CSS/Javascript5 k+ `: F3 @1 x' Z; E
& ^' f% Q* O. o/ S
基本的命令行交互如Linuxshell命令
理解数据库的基本概念4 M6 C/ _1 U8 A5 j% p
. }* y* `2 h% ^( E, v
为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。& z9 |" l& ?9 U' z( X
示例:一个以太坊投票应用7 G5 e# L( O5 O+ {2 k# D
以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。
本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。& x8 ?7 K: m# Y8 Y- a
- L4 d k5 p) P. d1 k! C
现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。
以太坊开发环境搭建
3 {& ^6 H3 ]! J
Linux6 H- K W1 H2 ^# ^4 w( X
; B. ]. ?, Q% K* `+ k
示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。2 u1 O" ~9 e) S# u
6 m" L, J9 b# m0 K( ^9 h) C
我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。! s d' j8 X/ m3 j* S) ?+ Q, v& z
# X# N. l& p9 V8 ?! z
下面是安装过程:& I7 L4 n0 v1 O v) R2 d$ Z
4 ^- \- [+ b$ k5 c% |, w9 H
$sudoapt-getupdate6 B j4 {4 H1 E4 @4 m% J, O
$curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh
$sudobashnodesource_setup.sh2 y) p& @! @% q7 p! l+ j
$sudoapt-getinstallnodejs1 S+ F7 v. }# j
: J. [. P+ V. i
$node--version& @ [4 V! k! a9 C
4 x$ p0 W4 ]5 b0 F' E; z
v7.4.0
2 o3 h9 G" V* x @$ J' J
$npm--version
4.0.5! {3 I: A1 l n/ Z, V7 }: l
$mkdir-pethereum_voting_dapp/chapter1
# ]$ [9 Q2 _; L& D, F1 b- v
$cdethereum_voting_dapp/chapter1% ~4 H# l) I, Q
5 r" z$ x1 y2 \6 e
$npminstallganache-cliweb3@0.20.1solc4 i4 m8 U M# e7 E
$node_modules/.bin/ganache-cli4 O% m: y% t( c
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。
8 P& p. ?& a$ g9 B
GanacheCLIv6.0.3(ganache-core:2.0.2) o4 A+ i; R2 M' F0 v* U# b
8 t! N/ I; D6 I K
AvailableAccounts
==================
& J1 V# x: o! E4 v; L
(0)0x5c252a0c0475f9711b56ab160a1999729eccce971 S: w- _3 H3 V4 \
(1)0x353d310bed379b2d1df3b727645e200997016ba3
) ~- P7 w# n8 K1 ]8 _1 q9 d8 L8 M
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23 s5 X$ G. x% B5 {# R+ H
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
9 x# |# P4 p8 d6 y+ w' m
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798* ?( y9 g' L+ |2 [
(5)0xda695959ff85f0581ca924e549567390a00340588 s1 E/ a3 O Q. Q( r
(6)0xd4ee63452555a87048dcfe2a039208d113323790
8 z! J2 ^; t3 I4 r8 J7 i
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
|% k8 E3 p+ V$ d# }$ d& x
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36& v2 k6 h6 B. N' y
PrivateKeys
% Y. {6 G" D. P$ J0 x
==================
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b
8 n& ^9 {5 D) W5 p5 w1 ]0 @
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603 D) E- x0 a1 w% W* X
7 n" U+ V O" [9 P5 n/ M$ d
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99! v9 ?% e y% q" m
4 y9 ?; B% Y* X2 n Z! n4 A
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f354309 Z o; Y/ G S( s+ ?
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
; o& _' n7 J" E+ h1 q: Q
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a99 M; [+ t% ^1 A X$ U; H
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d0 l+ S! ^! P( I
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
" S/ }/ {' [# I9 |6 Q9 o
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0' F" Q" f- k5 Y- B2 @
HDWallet% I. X7 x% r+ ~/ E; F% o$ u1 b# Q
==================1 Y& }' F/ N$ d4 a( X
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella7 Y/ P; r0 K: H" m: `
% v3 s5 A! C) F* Y% B; f" f
BaseHDPath:m/44'/60'/0'/0/{account_index}% Q# d9 J7 E9 A) m
Listeningonlocalhost:85452 F$ g$ Q' r5 q a. Z, O. R. o
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
MacOS6 d$ P8 \8 }& ]) f( e3 f; l. T! J8 {
如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。5 ^' b" w% Y* R4 H" F x
$brewupdate8 F0 n/ T }3 [6 a. S
$brewinstallnodejs' f! d/ X" c, [6 ]
$node--version" w- v- l8 \, t8 \( _
5 R# c! h$ s" j g: }9 Y
v7.10.0) Q, z2 `5 i- z# n% \1 S
' g$ x( b$ f1 k+ z9 m8 M# H
$npm--version
4.2.0) G% j3 I5 v& t8 d
4 n2 m. R8 a0 ]1 ?- X, H
$mkdir-pethereum_voting_dapp/chapter1
" }7 Y' b* M& e; b0 L, a) I
$cdethereum_voting_dapp/chapter1
- P! c4 h2 h3 I( _5 x
$npminstallganache-cliweb3@0.20.1solc; y( g) e7 y; K6 }& _8 w
7 E2 k" }0 r0 Z/ f5 w
$node_modules/.bin/ganache-cli
我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。; x% U( K! U4 V
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。
GanacheCLIv6.0.3(ganache-core:2.0.2)* w8 _5 ^1 A; y3 l$ M) ]0 n
7 w+ P/ j6 Y+ N8 c! F* M
AvailableAccounts7 l K4 o" g2 {/ w' ]
( u- ?( u5 G/ v$ q; u/ l! [
==================
(0)0x5c252a0c0475f9711b56ab160a1999729eccce975 U( h4 t# d+ ^+ G, y; v
$ M1 c% s' h* R3 `
(1)0x353d310bed379b2d1df3b727645e200997016ba3
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
; p! h! p- D( S& V, I$ B: m
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798( ~) K9 L) G3 b! d; E1 h
9 h. n* L; Q. l
(5)0xda695959ff85f0581ca924e549567390a0034058! M) k# I$ X, p" ]4 G7 N
- b B; X! g0 `6 d; ?+ J8 U
(6)0xd4ee63452555a87048dcfe2a039208d113323790
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42/ T# c9 ^" l" A; L) B; d; R; Z5 H
% {* m+ y. A' H
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36+ d" ?; F, a, ?2 K- \( H: A
7 J2 B* {/ f! ~2 F) C
PrivateKeys
) B& G& E, R& ? s' o- Q
==================" G& b2 ]- k- r( P
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b% o# s7 `+ T7 U" S) r- ~
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
2 S1 N- `4 v: H3 P; p
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc5 j. K. X: y/ X) L( {) t, F
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a91 c: D- f: X2 b( ^" d6 k
# T! b- S' t1 ~. U4 v# ]
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a' v4 C% b8 n$ S/ C
# G: L6 C0 j! P% U& g, T
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
3 R, O" P4 `: Y U) s/ [, V1 r- x/ T* z
HDWallet+ _* K5 V; M" ~7 c3 |7 p
; X+ l. p Y1 T, V5 o- r- k
==================# r+ L" c+ @ h6 z1 U
1 |2 t6 Q3 q/ E! a% R' w
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
: _0 {3 Z* ~8 c" ?# T x( Z j
BaseHDPath:m/44'/60'/0'/0/{account_index}
4 n% f" \* \8 V1 ?1 r* `! B1 a4 W
Listeningonlocalhost:8545
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
Windows9 f9 I9 ^5 J0 w4 r4 `
: `" h M! b6 Z" F$ L
安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)
( h. M& j; J8 {& Y
安装WindowsSDKforWindows
安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH( `( ^( ? K7 |' c# |! N
1 I3 w; R: R0 D; W- m& E" I
安装git如果你还没有安装并加入到PATH
安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径
s: G9 ~. v" t+ a4 S
下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS2017
* W6 X N* T+ Q$ M; `- n
执行命令npminstallganache-cliweb3@0.20.1solc9 i/ G5 h& |2 t: y; Z* T
SolidityContracts+ I- ?, s1 Z: m
; O, e: k% u G$ x! }& f
现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。+ E5 `. ]" O( C) p7 b+ f
我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:1 E8 E# r2 {2 q
一个构造函数,用来初始化一些候选者。
5 l: H( q& G1 _
一个用来投票的方法(对投票数加1)
一个返回候选者所获得的总票数的方法5 ^- @- y, [" I8 T+ J
当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。+ W- h7 g s/ [% J
pragmasolidity^0.4.18;+ V1 u/ i2 U3 H! i
, B4 f5 W! c9 f8 u0 g4 R. U1 @
contractVoting{1 |! M2 C% N# s! j
mapping(bytes32=>uint8)publicvotesReceived;1 m8 ~5 m7 U+ b0 |
bytes32[]publiccandidateList;% H F- P% J$ j! a3 s
4 k( |& n3 X) w& q- n( \* O
functionVoting(bytes32[]candidateNames)public{* u! m( H* \( B4 T
$ G4 Q& K) ~7 G2 v9 E) | o
candidateList=candidateNames;
}" v2 O' A2 P; }: T% y* [4 _
functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){
* X1 g$ |. c1 T# h9 I% h
require(validCandidate(candidate));- E( } E; Z6 S. N5 f/ H! h- d
returnvotesReceived[candidate];+ h8 Y; X. M/ h. ?8 B
+ H+ F. ]2 p- C
}- |6 c( s: N1 j
4 e8 Q6 _4 P. q6 }+ j
functionvoteForCandidate(bytes32candidate)public{6 @, t1 E: M; H5 |# q# C' n
require(validCandidate(candidate));
' c) n2 Y/ e, F9 H0 X8 d
votesReceived[candidate]+=1;
; U. c- [1 v! Y/ w2 r/ v7 s3 d
}7 ~5 L: H1 ]- Z V3 G5 C5 X% u
: |$ O/ g' E$ ^& z$ e( W* }
functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){
/ x, \9 k, u. L | ^5 l
for(uinti=0;i( h( A) p; R6 s
将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。
代码和解释/ ?) I- H" \, V# r* J$ z
Line1.我们必须指定代码将会哪个版本的编译器进行编译
Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。
Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。
$ y+ w! H) P$ F8 O% J/ v$ V1 \
Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。. U1 S: T, y0 Q, U9 E
你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。) x) F) D+ m0 O y3 d+ z2 u9 L( M G
你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。
编译智能合约1 o9 X! W5 [2 }" j+ K
我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。' D* ?/ j/ [4 `- B% Q+ x
: n0 ?- m. @3 ^4 ?& C/ ~
首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
2 m% N# ~2 V. @3 _5 v \; C
确保与此同时ganache已经在另一个窗口中运行; @% B% \8 o4 {4 R
. ~6 `2 `$ g& W T E
为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。6 ?+ X7 O8 H/ y6 ?
. E0 q* V" F" A9 V" {
$node
# L, k* ^- @* Y2 k/ t: k
Inthenodeconsole; g X9 _" Q4 I/ b. U0 s# g' F
>Web3=require('web3')
>web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));
>web3.eth.accounts0 J: `; b& U# t- T6 A& v" s- F
['0x5c252a0c0475f9711b56ab160a1999729eccce97'
3 v0 d* d) F, ^$ f, i' o
'0x353d310bed379b2d1df3b727645e200997016ba3'. q, `0 z ?" G
'0xa3ddc09b5e49d654a43e161cae3f865261cabd23'
'0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5'
' r( V9 }' T2 h" g. v: ]
'0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'
'0xda695959ff85f0581ca924e549567390a0034058'' Z; ^% O4 d+ w
'0xd4ee63452555a87048dcfe2a039208d113323790'% C. R# J# a& u/ f2 L2 i' C6 {6 C
0 Q# B+ x1 F0 q
'0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'
'0xba7ec95286334e8634e89760fab8d2ec1226bf42'
6 W, _) w" O' N/ s
'0x208e02303fe29be3698732e92ca32b88d80a2d36']7 K' V5 s) ]/ B' x
8 E3 Q- q6 r4 C4 e. _. r7 [
>code=fs.readFileSync('Voting.sol').toString()' l) |! f6 v+ \' ^, }6 ?9 W0 {
>solc=require('solc')
>compiledCode=solc.compile(code)7 T: x1 Q" I7 u n
. L( q5 N2 U+ ` Y7 @+ Y
当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:% m4 a# c$ q( V" S
* z& y" A/ D9 Z3 S: @4 o; ^% e* l
1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。1 h4 n: q. k$ H, h
2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。
教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人