以太坊教程:搭建环境、编写编译一个智能合约
dancing520
发表于 2022-11-6 21:10:54
659
0
0
以太坊是什么
以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机”EthereumVirtualMachine)来处理点对点合约。
以太坊的概念首次在2013至2014年间由程序员VitalikButerin,受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年通过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,仅次于比特币。6 f( |& f/ h5 d
以太坊区块链是什么?
以太坊区块链有2个主要组件:
3 J5 N3 ` Q& H
数据存储:网络中每笔交易都存储在区块链上。当你部署合约时,就是一笔交易。当你执行合约功能时,也是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向区块链中写入任何的无效数据,以太坊使用一个叫做工作量证明的算法来保证网络安全。- J+ n i% Q7 v3 C& a$ ]) `5 f
代码:就数据的层面而言,区块链就是存储交易。在以太坊的世界里,你可以通过一个叫Solidity的语言编写逻辑/应用代码(也就是智能合约)。然后用solidity编译器将代码编译为以太坊字节码,并将字节码部署到区块链上(也有一些其他的语言可以写合约,不过solidity是到目前为止用得最多也是相对更容易的选择)。所以,以太坊不仅仅会存储交易数据,它还会存储和执行智能合约代码。: q5 E' z- [5 S* i* G: i8 u0 P0 T4 @
可以简单的理解以太坊区块链的作用就是存储数据和代码,并在EVM(EthereumVirtualMachine,以太坊虚拟机)中执行代码。
# ]9 J0 f- x5 k# e& }
要准备的基础知识
为了进行以太坊开发,你应该对以下语言/技术有基本了解:
熟悉某种面向对象语言(如Python,Java,go)
HTML/CSS/Javascript
/ P" T0 X/ L# G; F( x
基本的命令行交互如Linuxshell命令
理解数据库的基本概念- J1 Z9 }" M6 ^( Y% [
" g2 `, Z9 {: E) a
为了构建以太坊去中心化应用即Dapp(Decentralizedapplication),以太坊有一个非常方便的JavaScript库即web3.js,你也可以在一些js框架中直接引入该库构建应用,比如react,angular,vue等。. Z. F Z4 |3 o7 V. x
" C9 T% N9 D, W1 P$ I A
示例:一个以太坊投票应用; C6 ~1 @+ i: R5 X" |
, I& Y3 I; b$ `% W& p3 d
以太坊教程示例中,我们将会构建一个简单的去中心化投票应用。所谓去中心化应用,就是一个不只存在于某一中心化服务器上的应用。在网络中成百上千的电脑上,会运行着非常多的应用副本,这使得它几乎不可能出现宕机的情况。你将会构建一个投票应用,在这个应用中,你可以初始化参与选举的候选者,并对候选者投票,而这些投票将会被记录在区块链上。你将会经历编写投票合约,部署到区块链并与之交互的整个过程。你将会了解什么是一个合约,将合约部署到区块链上并与之交互意味着什么。/ W, t2 d/ N7 Y: V0 x
本质上,区块链就像是一个分布式数据库,这个数据库维护了一个不断增长的记录链表。如果熟悉关系型数据库,你应该知道一张表里有很多行的数据。现在,对数据进行批(batch)量处理(比如每批100行),并将每个处理的批次相连。就可以形成一个区块链了!在区块链里,每个批次的数据就叫一个块(block),块里的每一行就叫一笔交易(transaction)。
现在,你对以太坊已经有了基本了解,我们可以开始构建投票的dapp了。这将会加强你对以太坊的认识,并且初略了解以太坊的功能。
以太坊开发环境搭建$ p( p4 l- g' z$ H8 {
; T9 i# [6 T: l$ J5 ^ _5 {( ]
Linux
示例是Ubuntu16.04下的学习环境搭建,你只需要成功安装了nodejs和npm,就可以继续项目的下一步了。" F1 M9 V! @4 ]; e
* x5 ^ j0 V$ J0 B! ^
我们通过npm安装ganache和web3包来为以太坊教程提供支撑。我们也需要安装solc来编译合约。
" |: T. n: M+ o) k) p' X6 R m
下面是安装过程:! b( m4 h5 [) _0 o5 F$ q
. x3 N+ H- |4 c
$sudoapt-getupdate
' d F2 d2 Q3 R$ l
$curl-sLhttps://deb.nodesource.com/setup_7.x-onodesource_setup.sh6 i& i) Q6 d$ z( H. ^9 ^
$sudobashnodesource_setup.sh
5 A, A1 ~5 D& Q
$sudoapt-getinstallnodejs/ }7 d. h5 c0 ^ ^
- l# Y1 |* @4 V/ C2 w! [' m0 g
$node--version
( k$ V# ^. p ~5 E( z3 k: l
v7.4.0' N4 M, }# V8 J' Z
$npm--version( T \/ K' Z9 x% u
4.0.5
2 I+ r! a* I$ t8 o
$mkdir-pethereum_voting_dapp/chapter1 j5 p9 s# c5 A) q0 ^5 J
% ?0 E% _9 J l1 K
$cdethereum_voting_dapp/chapter1, Q( Y% u: a, c: A
1 F5 h" r& M+ s: r8 M, g: v% f
$npminstallganache-cliweb3@0.20.1solc
# n1 R- v( L W9 s6 h3 ]' O" T6 i
$node_modules/.bin/ganache-cli* j# y* l9 f: G9 t U' c; H3 e
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到下面的输出。
GanacheCLIv6.0.3(ganache-core:2.0.2). g: n: N5 } F. a2 R
AvailableAccounts
==================
7 l* {* R! @ n
(0)0x5c252a0c0475f9711b56ab160a1999729eccce97
( @' z1 T: z" d; Q% a' W
(1)0x353d310bed379b2d1df3b727645e200997016ba3" c! { v, G8 `/ C: {# Y
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd23
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec58 p% d M; ^; i. `2 \' G
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd27986 [) D! u4 A, j8 Y0 }3 }1 s8 E
(5)0xda695959ff85f0581ca924e549567390a0034058# z+ P% D+ ^9 V, ~4 x3 Q
1 o4 X- N/ B m4 l( ?& S
(6)0xd4ee63452555a87048dcfe2a039208d113323790
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d141 ]( T, }) |. ] A! s3 k% ~
4 P+ v1 u6 x1 R* s1 g3 p4 r
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42: [/ D6 Q% N1 Q9 K7 C! {
K2 g. I3 T7 ?+ ~$ T9 R2 M
(9)0x208e02303fe29be3698732e92ca32b88d80a2d362 ^* O2 f' H2 m( k* M
PrivateKeys
==================5 F- w- }& t- ^7 _" y
9 g3 f) l2 R# H/ p& Y5 s
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b
" o4 `5 B- T8 B4 u$ t: C5 l
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99
* N: m$ z& u* D# W4 X K1 Q# h
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f354300 j( c- h. s; t- N# d, F
6 K% I2 O/ D; ?# \
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8, e( A9 ~9 P. z( O9 Y7 m2 x
+ A! K/ x+ y( l, p
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc7 A$ C. Y" G: ~, A3 a8 Y
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9; Z+ I6 c7 }3 o$ D8 z8 b+ J j; L1 D
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d/ Y% X5 W) m1 r, g
- N+ _- o' H) b5 B( m, i, b
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
8 M% d W6 Y" b7 Y7 L
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
HDWallet
==================
# P: @: H" i* | h
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
BaseHDPath:m/44'/60'/0'/0/{account_index}
2 Q7 B7 I4 t4 a% ^2 v, [
Listeningonlocalhost:8545. m2 n0 \! N5 n( Y
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
+ c( x3 u+ D1 S* ^# L2 F
MacOS3 k6 o* }- g$ L+ ^! u
如果你还没有安装homebrew,请按照https://brew.sh/的指示安装homebrew。homebrew是一个包管理器,它可以帮助我们安装开发所需的所有其他软件。按照下面的指示安装所有其他所需的包。% g/ w$ a' l$ `! Q( {
$brewupdate( g9 ~# k; l" i1 {" x
. e: c# `% P+ ~8 o* Y, w( R
$brewinstallnodejs8 p8 w5 b( U8 Z
$node--version; Q9 k# I1 u$ ? X
v7.10.0& x! k' t2 {9 C z0 I
- J9 }- q. X5 S" F) V' h8 O
$npm--version
4.2.0
$mkdir-pethereum_voting_dapp/chapter18 T! ^$ q9 V1 I& K
' F# O, Q5 D: F' X# p* Z
$cdethereum_voting_dapp/chapter1% a0 n8 S( N' o" ]; X3 O
$npminstallganache-cliweb3@0.20.1solc
$node_modules/.bin/ganache-cli4 H3 m# ` R* \
我们通过npm安装ganache和web3包。我们也需要安装solc来编译合约。+ x; h6 w5 k/ |% Y5 r/ U0 h; Q
如果安装成功,运行命令node_modules/.bin/ganache-cli,应该能够看到右图所示的输出。. x! ?: w' O6 X5 w; T) R5 u
- {1 W' O* P+ D1 H* T2 [4 A
GanacheCLIv6.0.3(ganache-core:2.0.2)
AvailableAccounts. T' {. q. ^ g* i& X- B5 f
==================+ @! B4 ?( m: X8 B& N0 _: J
: d! @$ u% Z( V. k" g; b- }, Q
(0)0x5c252a0c0475f9711b56ab160a1999729eccce97
6 E& B0 O4 J- n6 w! {; G
(1)0x353d310bed379b2d1df3b727645e200997016ba3
6 q( y' ?8 S, a$ ]
(2)0xa3ddc09b5e49d654a43e161cae3f865261cabd233 Y( y5 c' _; ?7 G
* P1 {- ?8 Z: E
(3)0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec55 e7 m) Y) @: |0 w2 q5 ^
0 w9 {3 H1 s+ u4 x
(4)0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798
: Q! c- y4 n# Z* x. e
(5)0xda695959ff85f0581ca924e549567390a0034058) [- a* N) C( i( v0 e4 j
(6)0xd4ee63452555a87048dcfe2a039208d113323790
(7)0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14
1 v3 z0 {' Q5 m, P0 g8 Q7 U
(8)0xba7ec95286334e8634e89760fab8d2ec1226bf42
(9)0x208e02303fe29be3698732e92ca32b88d80a2d36
+ b @9 O$ Y# T8 \; A! e/ @
PrivateKeys/ o( ?2 B: u9 u; J
==================, }& f5 `2 R+ h
(0)a6de9563d3db157ed9926a993559dc177be74a23fd88ff5776ff0505d21fed2b
d. a8 E4 h7 [
(1)17f71d31360fbafbc90cad906723430e9694daed3c24e1e9e186b4e3ccf4d603
(2)ad2b90ce116945c11eaf081f60976d5d1d52f721e659887fcebce5c81ee6ce99. X, `7 Q# V4 I" b* V$ @" B: T$ p
(3)68e2288df55cbc3a13a2953508c8e0457e1e71cd8ae62f0c78c3a5c929f35430) i0 y3 I7 f- J7 K
(4)9753b05bd606e2ffc65a190420524f2efc8b16edb8489e734a607f589f0b67a8/ U2 E" R* ?4 u) ~0 H1 F c+ u
+ b$ p% b" n, q+ \8 a, w! U
(5)6e8e8c468cf75fd4de0406a1a32819036b9fa64163e8be5bb6f7914ac71251cc
0 w9 J8 u* Z U* l- `
(6)c287c82e2040d271b9a4e071190715d40c0b861eb248d5a671874f3ca6d978a9
5 C5 G Y. E' ]0 ? o4 e% P
(7)cec41ef9ccf6cb3007c759bf3fce8ca485239af1092065aa52b703fd04803c9d
(8)c890580206f0bbea67542246d09ab4bef7eeaa22c3448dcb7253ac2414a5362a
(9)eb8841a5ae34ff3f4248586e73fcb274a7f5dd2dc07b352d2c4b71132b3c73f0
HDWallet
# w# S2 w( f: d" B# r/ G
==================
% w# z6 g4 o, k$ z% Y
Mnemonic:cancelbettershockladycapablemaincrunchalcoholderivealarmduckumbrella
! O4 s; g& p% z4 p
BaseHDPath:m/44'/60'/0'/0/{account_index}
8 M8 ~% u: I3 G% w
Listeningonlocalhost:8545
为了便于测试,ganache默认会创建10个账户,每个账户有100个以太。如果你还不懂什么是以太坊账户,把它想象成存钱的银行账户就可以了(以太(Ether,ETH)就是以太坊生态系统中的钱/货币)。你需要用这个账户创建交易,发送/接收以太。
0 r- {' }' P9 T6 d* J5 U7 F
Windows8 q0 V; B- O$ D9 Y9 X
安装VisualStudioCommunityEdition。如果你选择定制安装,那么至少应该安装VisualC++(目前的版本是VS2017)
1 r0 g/ C8 Y+ |9 Y( t1 G
安装WindowsSDKforWindows* f" s8 x% v( {. `, O" l
安装Python2.7如果你还没有安装的话,并且确保将它加入到环境变量PATH
+ _# O/ D8 v4 Q# I& }
安装git如果你还没有安装并加入到PATH
安装OpenSSL。确保选择了正确的安装包,并且只安装完整版(而不是轻装版)。你必须将OpenSSL安装到推荐安装的位置–不要改变安装路径, {* g% \/ B" N3 c4 y3 L4 [/ {
( u, l- e' L0 z' T$ {7 O5 ^
下载和安装nodev8.1.2。不推荐使用版本v6.11.0搭配VS20173 y0 Q: S2 \/ g+ M$ [, m r
执行命令npminstallganache-cliweb3@0.20.1solc
5 z3 t6 j; e6 x) Q# d& b+ G
SolidityContracts$ r& Z/ |% \$ M
现在已经安装好ganache并运行,我们将会开始编写第一个以太坊智能合约。& y" |" m8 d6 d% ], h9 f. g6 o5 Y
我们会使用solidity编程语言来编写合约。如果你熟悉面向对象编程,学习用solidity写合约应该非常简单。我们会写一个叫做Voting的合约(可以把合约看成是面对对象编程语言的一个类),这个合约有以下内容:6 e. p" Q C7 Q) @+ O
一个构造函数,用来初始化一些候选者。
一个用来投票的方法(对投票数加1)
一个返回候选者所获得的总票数的方法! {7 [3 C' n+ c( l3 F" h
当你把合约部署到区块链的时候,就会调用构造函数,并只调用一次。与web世界里每次部署代码都会覆盖旧代码不同,在区块链上部署的合约是不可改变的,也就是说,如果你更新合约并再次部署,旧的合约仍然会在区块链上存在,并且数据仍在。新的部署将会创建合约的一个新的实例。
pragmasolidity^0.4.18;
/ k3 g D6 A$ j$ ]) H2 U7 o; @
contractVoting{5 |* Q8 m& R$ n! ~
0 K0 M# ^' ~/ c4 g% h8 y( P- R9 V
mapping(bytes32=>uint8)publicvotesReceived;- k/ V% u' i. q5 R. P
4 I. C8 W& J) l/ h* D# C5 k
bytes32[]publiccandidateList;
functionVoting(bytes32[]candidateNames)public{
! N' i+ `% E+ T; d; z( B! f% f
candidateList=candidateNames;/ y$ W' s: i/ t
}, G! l# t1 N6 O
functiontotalVotesFor(bytes32candidate)viewpublicreturns(uint8){" I0 k! R+ h1 P* c# e
0 L: C# r% U$ y
require(validCandidate(candidate));. B$ s" G9 D3 x5 p, @
7 k" S% X7 Z+ |$ L( t
returnvotesReceived[candidate];
1 Q& A6 {1 a/ W! S5 C
}3 E* p' [4 G. U& u0 u7 J/ w, x. t
8 ~( B; g) z Q3 }1 a8 L1 ?9 ?. |
functionvoteForCandidate(bytes32candidate)public{
' c$ F2 W& I, A- t2 ~
require(validCandidate(candidate));
votesReceived[candidate]+=1;- u A, r; J: H5 T* X
}9 I/ O! t9 q2 o) v2 R$ h
functionvalidCandidate(bytes32candidate)viewpublicreturns(bool){4 G1 R' K' m9 F" H0 m8 e! k
for(uinti=0;i! r* a+ ^7 W/ b- h0 w
9 f* a/ A( B9 I) s0 R9 \
将右侧代码拷贝到一个叫做Voting.sol的文件中,并保存到chapter1目录下面。9 H6 @7 W; @7 X9 r9 a+ {
+ ]% e6 P/ j" J5 J
代码和解释
Line1.我们必须指定代码将会哪个版本的编译器进行编译
' @9 {8 B# y* V. y& d* J; m
Line3.mapping相当于一个关联数组或者是字典,是一个键值对。mappingvotesReceived的键是候选者的名字,类型为bytes32。mapping的值是一个未赋值的整型,存储的是投票数。
$ p3 }/ g5 f* R
Line4.在很多编程语言中,仅仅通过votesReceived.keys就可以获取所有的候选者姓名。但是,但是在solidity中没有这样的方法,所以我们必须单独管理一个候选者数组candidateList。
Line14.注意到votesReceived[key]有一个默认值0,所以你不需要将其初始化为0,直接加1即可。. ?# a9 }' k2 H: } s) X
- f" O3 ]2 p5 o
你也会注意到每个函数有个可见性说明符(visibilityspecifier)(比如本例中的public)。这意味着,函数可以从合约外调用。如果你不想要其他任何人调用这个函数,你可以把它设置为私有(private)函数。如果你不指定可见性,编译器会抛出一个警告。最近solidity编译器进行了一些改进,如果用户忘记了对私有函数进行标记导致了外部可以调用私有函数,编译器会捕获这个问题。这里可以看到所有的可见性说明符。
你也会在一些函数上看到一个修饰符view。它通常用来告诉编译器函数是只读的(也就是说,调用该函数,区块链状态并不会更新)。所有的修饰符都可以在这里看到。
1 \0 p# f( O& f
编译智能合约
我们将会使用上一节安装的solc库来编译代码。如果你还记得的话,之前我们提到过web3js是一个库,它能够让你通过RPC与区块链进行交互。我们将会在node控制台里用这个库部署合约,并与区块链进行交互。2 S' k4 m. T* u
2 J9 ?' M/ h4 q$ X) d5 R
首先,在终端中运行node进入node控制台,初始化web3对象,并向区块链查询获取所有的账户。
确保与此同时ganache已经在另一个窗口中运行% P3 l1 L& F7 C9 E) `3 f
, f0 b& W1 i# W* o+ Z6 w
为了编译合约,先从Voting.sol中加载代码并绑定到一个string类型的变量,然后像下边这样对合约进行编译。
$node
Inthenodeconsole- ^" w/ {4 P. T t
>Web3=require('web3')
0 |; Z5 E% L& d& }8 ~1 X
>web3=newWeb3(newWeb3.providers.HttpProvider("http://localhost:8545"));
$ p" E' O0 n1 H) H5 i
>web3.eth.accounts
['0x5c252a0c0475f9711b56ab160a1999729eccce97'7 e5 Y4 N+ @# ^/ ^
# e4 p+ f( Y$ v- t$ g! t
'0x353d310bed379b2d1df3b727645e200997016ba3'
# M0 O4 _( W+ I& Q4 M
'0xa3ddc09b5e49d654a43e161cae3f865261cabd23'
1 f% F9 Z) Q: R2 L
'0xa8a188c6d97ec8cf905cc1dd1cd318e887249ec5'; n7 T a6 @4 M
* k/ S( c# W5 y/ H) j3 r4 x+ u: {4 o
'0xc0aa5f8b79db71335dacc7cd116f357d7ecd2798'
( F$ y( Q' _$ B6 [% j% n# `# l6 X
'0xda695959ff85f0581ca924e549567390a0034058'
+ H: ]5 J& |/ C% d% E- H
'0xd4ee63452555a87048dcfe2a039208d113323790'+ U+ d9 _: n% d& E5 I5 _
& O/ R& y- |, y) d
'0xc60c8a7b752d38e35e0359e25a2e0f6692b10d14'0 ?* [" @4 E/ x
'0xba7ec95286334e8634e89760fab8d2ec1226bf42'* ~! I7 ~( H7 A7 {0 y
'0x208e02303fe29be3698732e92ca32b88d80a2d36']
>code=fs.readFileSync('Voting.sol').toString()8 ^! s# n c$ L. Q" P
>solc=require('solc')
>compiledCode=solc.compile(code)
2 \4 |) L# b/ P: s- d) E* _
当你成功地编译好合约,打印compiledCode对象(直接在node控制台输入compiledCode就可以看到内容),你会注意到有两个重要的字段,它们很重要,你必须要理解:" F/ i$ V# {9 J8 a, g% I
) m# o" T: D4 M4 t4 W
1.compiledCode.contracts[’:Voting’].bytecode:这就是Voting.sol编译好后的字节码。也是要部署到区块链上的代码。
2.compiledCode.contracts[’:Voting’].interface:这是一个合约的接口或者说模板(叫做abi定义),它告诉了用户在这个合约里有哪些方法。在未来无论何时你想要跟任意一个合约进行交互,你都会需要这个abi定义。你可以在这里看到ABI的更多内容。) z9 N1 I5 V9 d: E
9 t+ g9 J3 z+ ]
教程参考汇智网的DAPP开发入门教程,如果大家等不及博客更新,也可以直接访问这个以太坊教程。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人