以太坊教程:搭建环境、编写编译一个智能合约
dancing520
发表于 2022-11-6 21:10:54
628
0
0
. r, W! W& Y4 q" P4 ~# p; u( k. @) U
以太坊是什么 X# |! o* v6 b# N2 ?* Z% X
4 u2 W# P. V* |
以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。# o" Q0 [3 f9 w2 U3 E* W
8 e# [$ f' y! A# s, W& `% W( M
以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。( W7 A2 f% J. \3 _# q6 F
. o1 E f* f2 K! i5 V4 z" D! y6 \* `
以太坊区块链是什么?
1 x# p/ Q3 h: _2 R# d
以太坊区块链有2个主要组件:7 |( q% W; \. Y4 V4 ]4 x
* _/ S |* `: @, z; t, _
数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。# o- F" b/ w! ?0 Y
; q* B0 u: a0 I& ~4 T4 J
代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。
" ~, _% Q: O) m
可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。
要准备的基础知识
为了进行以太坊开发,你应该对以下语言/技术有基本了解:
" `" e8 @, V8 {& Z: \
熟悉某种面向对象语言(如Python,Java,go)
6 E0 K: T3 i" X- | H
HTML/CSS/Javascript3 i5 P: @" K: R7 V. J3 `; t3 K2 M
基本的命令行交互如Linuxshell命令' W& n. z) d: ]) k8 i, H
理解数据库的基本概念9 \2 j# w7 {7 r6 a" ]
为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。7 t. G& m1 K9 @; o/ k6 u7 D* J
示例:一个以太坊投票应用1 R0 e9 p P9 U, \
" j& p4 I( h3 A1 d: C
以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。
本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。
现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。
) P' S1 N f6 n) _
以太坊开发环境搭建' }6 L8 b! S, ]% }' \
Linux# u+ J* K. X2 o. A9 o
; v8 v6 k, A( D% W
示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。& [( f; h5 Y2 S8 X; C$ Q
7 l5 T$ F- J( s5 n
我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。
下面是安装过程:
1 a- o4 w" w$ Y- ?3 d% Q3 a
$sudoapt-getupdate
$curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh1 n1 C2 v/ r7 l
# F4 n" S" S/ o& @
$sudobashnodesource_setup.sh; {# G: H1 c% \7 Z3 t. h+ `) X5 |
$sudoapt-getinstallnodejs
) v7 U5 P3 t+ H" y# ?( {& `
$node--version' R: u8 T& w1 j5 t
& [# `3 \7 J' F
v7.4.06 o( g* V6 F8 w
: l2 B8 C6 a2 s" W% U
$npm--version# H5 f$ [# J1 g- K" P# m! N
8 i2 j6 s9 w/ C' Q) |" M/ N
4.0.58 D5 H& _# m# u* q9 r: Z
$mkdir-pethereum_voting_dapp/chapter12 V& c8 X8 o) B
$cdethereum_voting_dapp/chapter1/ F0 x7 B. o& Y# v! b7 ` R& c
4 L+ I' F( n; Z/ K
$npminstallganache-cliweb3@0.20.1solc6 g; a0 F+ Q8 K0 L
$node_modules/.bin/ganache-cli
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。
1 Z7 O3 q1 p" B
GanacheCLIv6.0.3(ganache-core:2.0.2)
AvailableAccounts' t/ l: H" O6 I
f5 g$ t4 r2 o- a1 _
==================
(0)0x5c252a0c0475f9711b56ab160a1999729eccce97
# p8 V3 e4 ?2 f$ O& D& W
(1)0x353d310bed379b2d1df3b727645e200997016ba34 i5 M+ F) n1 \: ]" L
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5! ?" S3 I/ ]5 L" h3 q4 |
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd27987 l1 W" f- t+ G' d7 v
(5)0xda695959ff85f0581ca924e549567390a0034058
" j" L6 Y8 d5 c5 V
(6)0xd4ee63452555a87048dcfe2a039208d113323790
" I- c) C6 q H0 O
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
. H0 C X; w+ y, q7 J0 l
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36: Q5 @1 h# B" W* r" k1 H4 v+ T
PrivateKeys
==================" b$ b+ m/ z+ ]% Z! X( V
# b. `( Z: B. c
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b9 L; H: G# V l7 I
2 h4 m/ X Y( z% a) d
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f354306 a1 r% }+ ^4 o# d( ]( v
, u9 T9 ?! x( n
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
- @/ E9 l9 ?0 L
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9% H/ W7 ~0 V( |* @5 o" d
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a1 i; Y6 W. L7 i/ Y3 Y' N( B
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
; V8 `8 z" k/ T; `) t5 F% V9 s. x
HDWallet
& B" `" a2 h) H; t
==================
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
3 o, n% Z# F5 f
BaseHDPath:m/44'/60'/0'/0/{account_index}' j' @3 y: i) S6 D. G
Listeningonlocalhost:85450 n1 e+ P* v: E
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。- i& j3 N" l L/ G( U9 V' R7 f( t
MacOS3 B! a5 O2 U, x0 H6 {; U
: @# Z2 C: b) _
如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。
$brewupdate i8 e. O! e @) `$ h5 u2 z
$brewinstallnodejs
4 a/ |3 E4 X9 m( P& {7 O/ G& e
$node--version0 N( b- Z& t5 x1 j' \; `# Q
: c0 H4 S' ~# l! b
v7.10.0
3 M4 K4 {$ H5 ^) W) d
$npm--version
4.2.0- q* x9 n; Y/ Z! P- X& {
$mkdir-pethereum_voting_dapp/chapter10 M# [6 j4 z: N! y
$ ]. V% A, g& Z: N6 E# J3 r) D
$cdethereum_voting_dapp/chapter16 i. P2 u2 Z8 T% l6 l
$npminstallganache-cliweb3@0.20.1solc/ ~! S3 A- o: }" B4 q
5 M/ N2 p4 R, s4 L, w6 b
$node_modules/.bin/ganache-cli; p( X/ }5 ]6 Z0 @2 ~) Z) ^
我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。
/ C+ `0 H& e7 x4 r4 L, f
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。
$ j2 u r! W1 o
GanacheCLIv6.0.3(ganache-core:2.0.2)' M6 t) F6 }) \' w
AvailableAccounts
& f5 b' y+ i. P Z9 R C2 u1 R
==================+ h/ `! ~: F& J; @; N/ e
(0)0x5c252a0c0475f9711b56ab160a1999729eccce97
/ @9 X9 [2 M7 q" E
(1)0x353d310bed379b2d1df3b727645e200997016ba3& v6 }! V0 K* Q& V: O6 }
% H- u; D4 s9 w; e& [0 l+ g
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5
" z7 o6 P/ y [) s
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
(5)0xda695959ff85f0581ca924e549567390a00340582 b6 b, ^5 _3 A" e2 U+ C
(6)0xd4ee63452555a87048dcfe2a039208d113323790
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14* T n0 \: C% z5 d0 F' m* r5 L3 ~0 K) J
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
* r: L9 a* W$ H- Z! f8 H7 }/ Q
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36: E- v6 L1 \) P$ Y4 C7 U
3 n: f9 J% ^4 s2 z
PrivateKeys$ }* m, O1 R3 `6 o% Z" |5 s6 J
( v4 B6 H. P5 F
==================" T Q! Z: U, S* M4 Z
8 R. U2 y- d7 q! }3 u( N
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b! b. L" u* B" s0 @2 m
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
2 O* ^" O- l" Y- r* `. z, J( v
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f354305 W; Z1 p& c/ M3 B( Q
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8
4 a4 U; [5 g% P Y! Q- z; [, f
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
5 V0 U8 E+ W9 o+ D
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
$ S+ l' g/ y: i+ N& z& S2 ]
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a% _- E% I0 r' i! v. T/ H
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
" T6 N5 D' d5 d/ k+ p
HDWallet- M% `1 k4 x: w" k
# }, V/ X g6 O7 S6 A7 M
==================1 \9 p# y! M$ P
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
) ]* }1 l* J# ]. h& x
BaseHDPath:m/44'/60'/0'/0/{account_index}
% d% Y' |- Z; d: l1 f4 C5 x
Listeningonlocalhost:8545
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
Windows2 Z* e- o% C% o& h9 T
安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)" p* {1 C& {, _2 s9 G
0 z3 f6 a3 A5 V1 x
安装WindowsSDKforWindows
0 Y4 f* e8 F/ [* i' ~
安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH
安装git如果你还没有安装并加入到PATH
安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径
下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS2017
]4 Y' v I1 T; Y- } Y; H
执行命令npminstallganache-cliweb3@0.20.1solc/ g& A$ @5 R4 a9 `, I6 P8 i- w
$ ?; m3 F9 r$ L5 @ _
SolidityContracts1 r" ^ t: H9 ~$ J, q6 x/ |
现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。' A3 I7 s [) y( b" x
1 t, [" P5 b" ]1 Q8 b7 D. }7 @6 @3 O
我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:
2 T; h1 e. r; g3 W* i
一个构造函数,用来初始化一些候选者。
0 ]6 f. ?$ Z7 v5 X5 `$ B; ~
一个用来投票的方法(对投票数加1)* k9 @% s7 Y3 p. c! Q1 \0 ^
2 u1 Y, v% L! ^5 J& B
一个返回候选者所获得的总票数的方法
当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。* l, R! d; s+ s; F% G
pragmasolidity^0.4.18;* \3 P! s) Z# W1 y. g) J
contractVoting{
) ]4 |/ p) m1 \
mapping(bytes32=>uint8)publicvotesReceived;) ]- G% U x8 B& }
9 ?/ U0 A2 M5 [' [: b
bytes32[]publiccandidateList;
; `. X) _7 V9 D5 ^7 R: @) b
functionVoting(bytes32[]candidateNames)public{% s& Q) ?. @; o$ f2 }
8 ?" O7 b2 [- T5 q$ E' n J
candidateList=candidateNames;" W2 K9 x9 n. m2 d7 a" f
( B j2 E1 p+ f2 U0 F5 n
}; M: d! o5 ? \5 G2 g4 f4 ^9 N9 s
$ L y# s/ ~5 E2 f, u/ I
functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){
- O" D# K$ R: z5 s: S& \% C; s, y
require(validCandidate(candidate));
4 F; E7 n2 M/ K" N, H6 g* Y/ W
returnvotesReceived[candidate];' O" |$ f3 M* x* f, V
, X g1 q. y6 e; ~7 N: K& ]0 g
}
# b. ^( [" c1 T, v3 X
functionvoteForCandidate(bytes32candidate)public{: k" C' t7 m+ O9 a/ m3 Y& h3 m
require(validCandidate(candidate));
votesReceived[candidate]+=1;4 V6 O; L. N: P0 I& {
; g* s5 Q5 p2 h9 e4 A
}
functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){& s( `$ y5 t' k: l& ~9 g
for(uinti=0;i
K% ^6 [2 ]* f5 |2 _4 ~* v
将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。: u& K# u/ V0 L: p9 G K: F8 Z) ]3 C
( W, b' B. v4 T6 _/ R" Y' h( J
代码和解释
Line1.我们必须指定代码将会哪个版本的编译器进行编译
9 D/ Y! w" u n( F5 i
Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。* D3 j7 Q' J" o% ]: w3 ?
Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。9 R; G3 F( r' |; z) r( S3 T
Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。% j% q; L) l% T
你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。
你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。8 q3 P8 G/ ?4 G' E9 R2 ]
" b2 Q$ M( h- B) p
编译智能合约
我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。
首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
确保与此同时ganache已经在另一个窗口中运行. R0 G7 ?+ Z/ Z
为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。
/ I' A3 B& [; j2 V1 p8 E6 W. A
$node
Inthenodeconsole
>Web3=require('web3')
>web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));% J' y3 y' N1 N
6 v- M3 J; C# o6 Z+ C. H
>web3.eth.accounts% q5 E8 ^+ A8 l @ w
) @7 d4 o' t6 o
['0x5c252a0c0475f9711b56ab160a1999729eccce97'
'0x353d310bed379b2d1df3b727645e200997016ba3'
' M( \9 Q( w8 T1 T: e1 S4 b, E8 ]
'0xa3ddc09b5e49d654a43e161cae3f865261cabd23'
'0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5'. T; @1 j; a0 ^2 Z$ O9 D
3 u( ^" r5 d! A5 e. O
'0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'' z) |: C$ g9 @2 D! O# z
'0xda695959ff85f0581ca924e549567390a0034058'
'0xd4ee63452555a87048dcfe2a039208d113323790'
" L. \( _* A4 E; m, X. O( [1 U7 H$ C
'0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'; F3 T7 v2 T. W3 Z/ ^$ ]
'0xba7ec95286334e8634e89760fab8d2ec1226bf42'
'0x208e02303fe29be3698732e92ca32b88d80a2d36']/ \- t1 R4 J( @+ Y
1 r2 j2 j5 q7 ?9 X8 H8 I
>code=fs.readFileSync('Voting.sol').toString()
4 j1 u1 U I4 s7 z, n3 N
>solc=require('solc')' I( Z2 J z8 X8 d# S$ Z
>compiledCode=solc.compile(code)
当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:
1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。
3 {7 {* {) F8 ?1 b0 Z) `5 Y, T
2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。5 ]% Q0 d1 k+ k7 p
教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人