Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
本以太坊教程主要是介绍:搭建一个开发环境、编写编译一个智能合约。, s! M! D7 q7 M  B

( T# |. j- f( F3 o9 M& T) C    以太坊是什么
. a! R5 i1 [+ v, K/ y9 j9 w/ a: U- o, X" B* V, u' R! C$ t5 Q
    以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。* s3 S7 f8 X% a; {; h6 ~

; Q! ?3 i0 y4 t0 v8 k6 ^( {    以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。
' v5 ~; m5 z* i4 T
, q. I9 C) {4 G( o7 M" U    以太坊区块链是什么?
9 j" q7 M7 f, l* |; c; q1 Z, z# P, }; w3 Q: h
    以太坊区块链有2个主要组件:* y& p" G' x# Z: @9 e
( ]& q  p& m* ]: t3 ?' X0 t
    数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。, x1 h9 I* c3 ^) u% M

& e1 e" ^" A3 T2 p. p. I    代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。; t7 _) Q  m/ A3 G3 P  F+ i

6 G7 M# X& w5 \# \# x0 h    可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。
9 X: p! l1 N) _1 W6 h# M
% Y0 |9 ?& A9 x4 ~1 x    要准备的基础知识
" u" S" `0 F* _, \4 \5 o$ Q- l' P
4 q( `/ r- f$ }8 P7 J    为了进行以太坊开发,你应该对以下语言/技术有基本了解:
. P2 q5 i, o7 n$ M0 G1 }* Z) u, B6 p' b
    熟悉某种面向对象语言(如Python,Java,go)
+ o7 x& J% G( d- X( p# A& B9 J1 M9 @6 }# ]
    HTML/CSS/Javascript
& k' ~3 v  {3 e5 u: R' |
6 P. r# w+ Z3 ~9 |- R: \    基本的命令行交互如Linuxshell命令
- a" P  m6 l% Y+ r/ Z
9 B5 @& L- J/ j& [    理解数据库的基本概念
2 b# c* p5 F. [) _  @/ b4 E
5 b9 V/ k9 m8 U+ V* @    为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。4 Q& n1 Q3 F8 ?
; D. ]# k8 V+ v7 O: Y6 `
    示例:一个以太坊投票应用
" [8 W$ e+ x2 R$ u8 u4 {
7 u0 W8 v) J& ~( e; v    以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。
- l( Q; j4 ~: D2 p+ x2 K( p! M8 J- @1 W/ ~' w& e
    本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。
, k  u9 V& O% \1 k- a$ r5 J
8 G; ?) [$ u& C9 P& \2 u    现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。( I; J: p4 v. T% |

. F8 K3 Y* h- Q    以太坊开发环境搭建
, y5 C4 C" v7 W# T  h1 S
/ f7 k3 |6 A4 N5 [1 h# u8 b( b    Linux# C/ ]  m) {( t7 V
: ^6 r- E0 ~+ {2 U8 _3 M" c
    示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。4 t9 u5 N5 k3 R* d1 M, I; y  a! C9 o/ w8 t

0 Y) q  s; p$ O    我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。9 P5 A* p' Y, r

7 k. ~" X1 c( V- E% P' U    下面是安装过程:8 X. E+ \" `2 Y) R

- k% v7 N: B5 t; K    $sudoapt-getupdate% W( b# w& K8 o* ]0 Z: t

% P) p- V) Y6 n$ M3 G    $curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh
% y' j- ~( \' [1 J( K; s* @$ I+ D
. |+ S' n; @8 B; t2 k. l8 K& I    $sudobashnodesource_setup.sh, m/ V0 X* {& h/ y

  U# d- m2 b3 g    $sudoapt-getinstallnodejs
0 C( F+ X. M- X9 U# a* P
( }0 p& F; o# K+ T/ o+ U    $node--version: R+ i  b; x! h) m8 ~; @  Z

( z8 g2 }9 y: F! n, W: u# ~    v7.4.0
: S3 f9 s7 A! h1 }# ^0 g0 ?7 I, t
    $npm--version
% I1 K) o! E) y! F9 Q
7 O4 p6 U7 Y- A  F* M    4.0.5
( M' N) g1 R7 C# h, S/ e3 I0 |  z7 E" S7 B+ ]( X
    $mkdir-pethereum_voting_dapp/chapter1# f, b; z, y5 M
' k' w/ e2 z8 I
    $cdethereum_voting_dapp/chapter1
1 O! `2 a; J4 `! z9 E& L- d# T( \$ `% I& m& g7 J
    $npminstallganache-cliweb3@0.20.1solc7 k3 r( @: }4 z4 c$ B4 o% V  X/ @" ?9 w

3 |( [% \4 M. T* @8 V" l9 m    $node_modules/.bin/ganache-cli
' b! W$ B* Y8 o: l# \& b- I
, m5 `' }+ e# \! [  K" _/ L1 X    如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。
4 I3 z$ m/ r+ i/ F* H8 W9 J
/ }2 R8 L4 N3 x- J, R5 k0 B! R) ^! r    GanacheCLIv6.0.3(ganache-core:2.0.2)
0 O* S  V# |% Z& P9 f: k' a9 N8 s3 @* R  t! v/ R
    AvailableAccounts
0 x/ [4 w9 f( N( s% L
. p5 i, c7 ~( m- u3 V1 ?    ==================% l. M5 G* X3 b3 _4 ~3 b8 {- {" a
: k  P% D' W0 a7 d; i
    (0)0x5c252a0c0475f9711b56ab160a1999729eccce97
1 b+ L3 v7 g3 j: j% y8 [0 i  A+ v
: b  p$ C4 ]  q4 c5 Y7 ?0 R  |, A    (1)0x353d310bed379b2d1df3b727645e200997016ba39 A$ u: K' n5 e) B- k
  l' P2 K9 q, W' L" I
    (2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23$ b& q6 P; c# V6 B) d' ]0 Y
0 G7 Z( H& n' W- k: Z
    (3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
3 ~5 F/ k% B" R; j2 i2 A
' X$ H' P4 d1 s! D    (4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
/ B: E# i4 B+ G5 I0 u" x* G+ U, k8 ^8 S3 V* r; y
    (5)0xda695959ff85f0581ca924e549567390a0034058
+ D8 O$ l1 \  A& s; O: v  d! j) f4 l% g5 [8 `* A/ R
    (6)0xd4ee63452555a87048dcfe2a039208d1133237902 e0 J3 o5 W8 {* H8 D$ G3 P

$ @$ X$ u' ^0 c2 w: a    (7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
" c3 x* b; ^- A3 H: u! h0 F+ r; j/ A5 p! S  g
    (8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
( W: W. A, v+ Y5 |
" S4 ]! v  r% f! q    (9)0x208e02303fe29be3698732e92ca32b88d80a2d36: f4 s# b  j: E1 X
9 |0 e* t4 m  a7 T% V
    PrivateKeys
# b8 T/ a! W2 p; r7 O; ?
: D8 q( c$ v0 X7 l( a3 z  b    ==================; p. r0 s  i$ U6 D( `0 @" B0 U- s

. Y" }  A( Z: X% L5 @    (0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b, W' ?% S+ y2 b5 e
, E9 {% w* c, q$ ~- P5 R
    (1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603! @8 h8 O8 Z5 {+ b

; I. @+ R2 K, r) U    (2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
: ]. C0 W1 M. V
. z2 e. u! [7 F8 ]2 A    (3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430
' @$ q5 ~) R0 F5 J% l6 {" B3 i# x6 P3 |" j7 e
    (4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8, h3 Y2 @# \  V; B

1 o- Y4 k2 b; l7 F& e" ~: a% \    (5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc- G% `9 C/ T% S
3 a6 W* U  _  `0 R1 \) f
    (6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9* w" J% n9 i$ m' v, ~
, h# G) J1 M- H$ \' R7 F: O/ ^
    (7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
0 w2 A* N4 u# Z! h) m  g7 M
, V+ q( T6 F+ n  b9 i% R( A5 Y    (8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
* m2 t* Q$ b. t: y3 w( s  D  c' T9 [' z# b" W1 R( C
    (9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
5 d8 b6 E5 L" ~1 \! G% q* }/ L! {& J$ T5 E
    HDWallet' W6 w/ ?: K* c$ S7 J: w! s
+ K% d/ R/ B, b/ R5 L) h& A- V/ A
    ==================! L! P4 W( I* t

( W9 @( V% s+ c    Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella& r7 c( z0 U6 g( M0 f: K5 ^
+ H4 w1 Z) N8 J5 R
    BaseHDPath:m/44'/60'/0'/0/{account_index}! p) E0 K8 s0 |4 M  y/ S# O
8 r, F+ T8 d  e6 O8 ~# [' a9 M
    Listeningonlocalhost:85452 _) w1 n) _! z* L/ t

# U" G4 R, w: m5 |5 [' w    为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
4 @+ D* b9 }* H6 R5 y
- w! k+ u4 e* `. J    MacOS
6 u) b! `! s: f" ]; I: p& Z% t( }; ~
    如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。$ I1 J1 n4 Q4 f1 k" O+ R: L$ K

+ O! o- J) J- V9 v9 B& k( \0 v    $brewupdate0 R! m5 L7 Z: D) l. c. L
  [9 H2 d& d  {- |
    $brewinstallnodejs3 t0 P' t3 j7 a0 p+ C

$ |' P  U( i, f. Z" I# c( U/ t    $node--version9 T, i/ t4 I6 c( \
. \5 z. @+ d2 U( i  x
    v7.10.0
& M2 `" U9 F2 g( y* w& K1 A
! ]$ Z. A$ H, g    $npm--version
3 d. ?4 U# M- I& r5 M# M- D. f4 l, t! G
    4.2.0& ?1 G7 N% N! B% `& i

6 w, g9 [/ z2 V    $mkdir-pethereum_voting_dapp/chapter1
9 n. ^2 P& p( C* G: f
  i, N* t; Y! z2 W6 Q: R8 k    $cdethereum_voting_dapp/chapter1
* \+ p: }, l9 _" ?. `. i" j
0 ]  F+ N, V  \& F1 U: h    $npminstallganache-cliweb3@0.20.1solc
' p# \! E- j& Z3 o  U
6 y2 ]! [1 s" ^4 n4 j+ Y    $node_modules/.bin/ganache-cli
' J# [" Y* `4 g: r- w5 n
( ~: c/ \5 E, P    我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。, Q) j- E1 Q( s* ]( X5 ~" [

, Q8 v9 r5 R* y$ P0 R7 Z' T5 D    如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。0 B! j" t# ?; E$ N, q* v5 Y

( c- M. o) g! ~( i! v& t0 M    GanacheCLIv6.0.3(ganache-core:2.0.2)3 P$ b- ?0 p/ s) J. e- f
* E" M8 q- @& I& t
    AvailableAccounts
3 d3 `# w/ S+ X8 s: G  i
+ z' t# ^) b/ z- G* E0 S1 A( s1 ]    ==================
! s3 Y* k5 y* ]% [1 G2 v0 D% F6 _6 x! p7 X2 {6 @
    (0)0x5c252a0c0475f9711b56ab160a1999729eccce97
( C4 l6 x/ x$ q" E7 U% Z+ y$ }* b6 K+ v2 U7 k; U
    (1)0x353d310bed379b2d1df3b727645e200997016ba3* S) {* m- D. d: r& e$ m

; |5 l2 z. b: {    (2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
5 b2 D7 ~1 D9 ^% d. V" y" o! i( `1 D% f
    (3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5- I$ M" @' t$ z4 Z% U
2 t, u9 U; F+ f3 T: ~
    (4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
. S2 f0 S4 D/ U# P) }& i( L) y
7 _9 [' R# M6 I7 A+ g    (5)0xda695959ff85f0581ca924e549567390a0034058
' S4 E& k: }" l7 t7 ^
* q3 y6 l$ V8 l7 a# H% }    (6)0xd4ee63452555a87048dcfe2a039208d113323790
* n5 i* V% i1 x; y; h# \! W- B( l  k4 F' f, j8 A* k' ]; J
    (7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
# ~! u9 I; x5 H" U! W1 Y
7 g) ^) s& Y- O    (8)0xba7ec95286334e8634e89760fab8d2ec1226bf42& J& `, A5 E, }) d" K2 c

, j" [0 z& W" _6 ~0 T7 z, `    (9)0x208e02303fe29be3698732e92ca32b88d80a2d36; f% D, e7 \6 X; h$ j& Q
+ d# s& ~+ z* l/ s- N0 y
    PrivateKeys
5 L2 P6 W1 H; j) b( g& b1 @1 o9 v% b8 C3 [! Y% C1 D9 G# Q( I
    ==================
7 ~8 o9 H; N5 P6 M  F& C. ~0 ]" x5 g
2 L, w, P5 a$ r( o# J* ]4 M$ J    (0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b* L% v& z5 k: C
9 {( |3 v+ V( K: A* W! o5 R: H
    (1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
$ f6 j# R( Z, N- g# |* p0 [  y# Z$ U; B' r; G
    (2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
7 l5 y. Q5 q# E$ X6 R! U/ m$ X5 T' \8 ]) B8 s% Y, m; e
    (3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430
8 f& ]$ q' C& o7 {
$ w/ r6 v) M* Z2 }% Q9 a    (4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
! J$ }7 [6 U9 \5 V0 g0 w& \) |6 p5 w7 R) C9 _
    (5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc4 Q: E5 ?' h5 `0 Q- i6 w1 e
, U# o0 R- h9 a* q8 c9 a
    (6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
6 X0 ?5 {  l: o$ V/ ]" H0 P7 L6 ]9 v) L$ g% _
    (7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d1 R0 J, N3 A7 y9 f$ x! t

- ~, @. v6 H/ q: b( _3 Z. w- n& s    (8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a3 L. N; [) O' b! Q

1 Z- m; V/ \  Q" T    (9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0( D: G4 D) W* p7 ]! n" r

2 L0 {, V% a5 B9 v  u* W    HDWallet
( d: f' ~; k$ s/ j4 F! v. k; }
3 x- F0 H. Y& v; a# h5 |    ==================7 ^+ J# }8 i' e" A$ u
7 T( M9 b- }' h$ v1 _6 s8 v8 G1 ~) M
    Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
& t  _' e# b& k2 w0 B8 `6 j
5 `' G8 e- h3 i. m7 C    BaseHDPath:m/44'/60'/0'/0/{account_index}# a: E  M) _; ^) B

0 M: j! G% K' V0 r    Listeningonlocalhost:8545
3 S; _8 v/ g' M# C' n6 c
8 _6 z4 v& k7 D* k/ S% f0 w    为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。) T5 O4 n- J5 w6 M2 g- i

, z$ U4 `5 E5 o5 Z    Windows
( _4 v& n- X% `/ _' O) w4 x) \* k. [) n
    安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)2 o. m4 f0 `4 p5 Q, ?: \% X3 e: @
. f9 T8 d3 a7 v8 ~
    安装WindowsSDKforWindows' D# R, r" u% v

; M$ e9 @9 r! t+ B    安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH
5 J; [- \7 J) s  k; ~5 \0 a( O- |; I* z
    安装git如果你还没有安装并加入到PATH) S/ I: S! {/ d9 Z
) J: F3 d' m, W$ Y: y
    安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径9 u0 e8 P- f" P6 p2 _. L

4 {/ j, G! ?% O1 N9 t; ]    下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS2017
2 u: A: q7 ^1 X4 V: J, w
0 s/ ~2 n8 c- F) w) g; {1 ]& f    执行命令npminstallganache-cliweb3@0.20.1solc
0 w+ S" f0 g( o* V; }2 `. s) I% g  Y0 l; ^& W  Q# H
    SolidityContracts
6 y) k: y% t( `. u- E. ]/ F( t0 X9 t, i$ H' A3 Q
    现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。
# J/ U8 {. _: O" c5 J- {
, w+ J# C2 M/ [    我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:
4 V: m' c3 G% L( H" e  @/ Y. I
$ K& r" m+ N5 b# `; U* ^    一个构造函数,用来初始化一些候选者。
2 D( ~2 w0 N1 _' K+ S/ z3 u$ K) p; R8 \1 c
    一个用来投票的方法(对投票数加1)
. |  U! ?- n) F9 l- }& Q( U' o: B' W* R7 h" l/ D
    一个返回候选者所获得的总票数的方法
8 n* Y; n' f$ g8 l$ H( W: E
8 ?7 B* d# B! l* l    当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。
* }' N0 M. |' S: t, S* d% q
4 r; @5 }! P+ u* w1 i    pragmasolidity^0.4.18;  D3 e* q' s# Y, R9 d

: P+ t- a2 `2 L) C# }' l    contractVoting{
/ @1 c1 x2 ^# b
: |: f& M0 |& C9 J) `    mapping(bytes32=>uint8)publicvotesReceived;
$ L" t5 Q+ t1 A0 \# Q2 [+ j* D9 F* G5 h
    bytes32[]publiccandidateList;( \% P" C; [1 T& Y+ j

# w/ \% a; N& m" T6 F    functionVoting(bytes32[]candidateNames)public{
  ~( g4 u0 r2 ?3 [; F7 n0 s8 k) F5 W- T) ]& [
    candidateList=candidateNames;; T4 U# d5 Z) H* i/ \7 @' d
# u& s' ?# U4 y% f! y
    }: C4 I- N. c+ O, ]) S
2 y# Y" ]$ Q5 \
    functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){
* s3 {  B! g0 q/ q
( j+ H1 `0 R1 j' Z    require(validCandidate(candidate));& G# e1 z0 J' h4 N+ \: h# ?

: c4 a4 }2 E+ H, V    returnvotesReceived[candidate];/ R  g) q8 e% `- k& h) P6 f5 k

- t: v5 [% H* t9 S6 M    }5 w4 t0 c0 Y5 f! s4 u7 Q

' @1 L; ~$ l/ J+ x6 O    functionvoteForCandidate(bytes32candidate)public{% \8 q4 a7 x* o/ |0 \* H# B1 k

0 Y8 D: b7 T2 c# u" _    require(validCandidate(candidate));
. i) e9 p9 p- P! S! O3 k
, R2 f. p. w/ r! @7 R( U    votesReceived[candidate]+=1;2 f! c; a. g) P1 c' l+ s, }

1 x8 ~9 d- k* I# s0 h    }
. r% b! c9 z4 ^7 M4 X' {; j6 L) j0 D1 c! ?  u; f
    functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){3 _* Y5 g! ]7 ]4 @9 F) A

( `+ h3 l' P  y5 ^" D4 f" x- Y) g    for(uinti=0;i
# g3 J1 x! w- q6 A; @- y% R3 G# v* {- H6 V% U1 p
    将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。& L4 {3 O6 a# `5 K

8 ^3 y- x9 d: [& V    代码和解释
" D# L: F8 q) {- ?6 q% l) u5 {6 c3 Q1 D7 i7 l. X
    Line1.我们必须指定代码将会哪个版本的编译器进行编译* Y# Q6 m6 `' B* Z  ~! N
1 K( T/ p2 _& F- E( S
    Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。6 z+ `( [1 u* X5 @+ L. u# v
" J3 W! a- _! K3 v
    Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。
, e8 M+ T" b0 O- g) s) D- L* H) ?7 f# {, x
    Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。: R! C1 z) T) S, k

8 X7 H: X; E4 F" F, u1 B    你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。
! r+ ]/ ?* o2 L: M+ V# {" O$ R$ T& A/ e- t0 q' \' e* w9 ]( O
    你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。! O: W5 C3 W: C1 m4 ]) G; y

/ p7 E+ L2 N! l% C" Y/ L    编译智能合约  P% h- o" R0 P% R8 N6 ]2 z; O+ E2 E
) A- c! z/ a& o
    我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。1 @8 X* C8 R: b5 E
/ t5 y; x0 h- o% L4 Z- F6 A
    首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
; L& i# e8 ?# K' o9 x; ~: h7 d* L1 k0 m6 m% r  o) V
    确保与此同时ganache已经在另一个窗口中运行0 Z/ l! r# L- \" Z

; ^/ O2 e& A7 P4 z" i7 H    为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。
' A4 H" H* H- f" g) F1 f* k! `$ }( s( @2 L, T
    $node) P1 B6 b# W6 [3 v! [& M
7 J, p5 \; c3 a4 J  p! \  F3 p3 W
    Inthenodeconsole
2 R8 W$ X# T; m
! o( e1 r* b/ I    >Web3=require('web3')0 H0 w8 @: R; \4 r2 x
1 o7 S1 B) ]& M9 c
    >web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));
4 f2 i$ C# g0 t) O# ]( N( b3 B' l( h3 [; O. C( d* @% N6 B
    >web3.eth.accounts
5 @* N& z' L8 j% t1 A! H5 G: Z9 p' X- ^" L  ^+ ]
    ['0x5c252a0c0475f9711b56ab160a1999729eccce97'. h% C) [. X$ ]3 c( T9 e

9 o/ a' P5 C) X/ t    '0x353d310bed379b2d1df3b727645e200997016ba3'* s3 G. c! s# F* }1 L6 s5 ~  _2 {

: r9 R! Y: |- K, D    '0xa3ddc09b5e49d654a43e161cae3f865261cabd23'7 p' m8 c$ F% c% I9 \$ O
1 |2 A" _- ]1 h+ J2 h- A! a' x
    '0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5'
: r# c: L; S/ q' M3 @- D
3 n" ^: y* r$ S4 z0 h2 |    '0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'4 T/ g$ u2 F% w- ?

& u4 ?; V7 M3 C$ I" I  Y; h7 ?    '0xda695959ff85f0581ca924e549567390a0034058'
9 l+ |2 X2 I$ m5 \+ W# k$ X6 z. p+ j, Q, r
    '0xd4ee63452555a87048dcfe2a039208d113323790'* p# B, z) T6 Z) W- N
- a7 V) s! t$ w. Z! j6 P; [% L
    '0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'
% w0 x  ~1 ^7 |
1 F9 B8 g$ |8 `0 W    '0xba7ec95286334e8634e89760fab8d2ec1226bf42'/ E4 ?! M$ u* m. p9 n

6 |& Q; {3 ?( W    '0x208e02303fe29be3698732e92ca32b88d80a2d36']
3 U1 e" t& @) M$ H; |) y
3 \* i. e9 o+ Y% e; o5 K1 \% k    >code=fs.readFileSync('Voting.sol').toString()
& W7 M( d2 G( y! l  u  n% B' u) P% D1 ~$ H
    >solc=require('solc')
! M% f+ R6 U. C: K& R4 ~# U) r, v
: a$ H3 g7 R/ k7 d  b    >compiledCode=solc.compile(code)
5 V& g/ Z. Y+ e2 S3 Q- z0 F: l
7 S- U! }  {1 E, i! J    当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:
# M; E( c8 ^: i- x; w0 X8 b
6 v, B* f! \) A4 n4 D    1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。
% T: R& u7 D4 O3 j. F
+ i! I$ l. @; \    2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。  ^  r' J. s4 [7 @+ J# P! k9 q: B& F1 e

  f0 T5 {' P7 @0 I    教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

dancing520 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    1