Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
  智能合约开发是以太坊开发的核心,而代币合约的编写是智能合约开发的核心,用solidity开发一个代币合约的例子是学习以太坊开发智能合约时必须掌握的。
  n! g% {% O- U& s( ]
/ Z; _- ?' e6 `1 z- C  以太坊的应用被称为去中心化应用(DApp),DApp的开发主要包括两大部分:
+ b- X3 w% _+ Y( Y# c9 ~3 ]) E, c4 R6 O  D
  智能合约的开发% A9 M, l# z9 r

7 R- m1 D4 w" h0 L6 ]7 e7 `; I  用户界面的开发
2 |* d8 w9 M% V# R# y" v; ~! q2 @, _+ N
  在本文中,我们将介绍智能合约的开发语言solidity。
. p" w  f) W9 y5 \: x% d3 G; ~1 e, W% [5 L
  让我们先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节。
6 u! J9 \% _+ G$ |8 H' `
9 `, }& @- e9 z* Q" j4 F  
  1. contract SimpleStorage {% k- L: a1 q4 E7 q7 ^
  2.   uint storedData;# [7 L' g" f3 x% A  }, a7 V
  3.   function set(uint x) {
    5 B8 f, ]% b/ w
  4.       storedData = x;8 R. k  u4 p2 t5 X+ s
  5.   }
    8 ^( f6 C, r8 x- R; U; ~
  6.   function get() constant returns (uint retVal) {8 M# m* F; n" T. z
  7.        return storedData;
    % E0 `3 S- _; v8 `
  8.   }
    2 Y9 q4 o- S+ p5 m( p* H
  9.   }
复制代码

2 \0 q4 b# ?* M+ Z5 t: Y. X( f
& _+ u- t- }$ p' D* _2 _  在Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位于以太坊区块链上的一个特殊地址。
8 Q0 e9 @6 v8 |& O2 `7 m- o% W' A9 w* a7 T, h$ M  T
  uint storedData; 这行代码声明了一个状态变量,变量名为storedData,类型为 uint (256bits无符号整数)。你可以认为它就像数据库里面的一个存储单元,跟管理数据库一样,可以通过调用函数查询和修改它。在以太坊中,通常只有合约的拥有者才能这样做。在这个例子中,函数 set 和 get 分别用于修改和查询变量的值。( F4 R8 R; v. G5 J
! p1 \) b8 \' y/ R% L
  跟很多其他语言一样,访问状态变量时,不需要在前面增加 this. 这样的前缀。9 U( c# T2 I, D7 q5 u

4 @7 d0 n. l' x" E3 O  这个合约还无法做很多事情(受限于以太坊的基础设施),仅仅是允许任何人储存一个数字。而且世界上任何一个人都可以来存取这个数字,缺少一个(可靠的)方式来保护你发布的数字。任何人都可以调用set方法设置一个不同的数字覆盖你发布的数字。但是你的数字将会留存在区块链的历史上。稍后我们会学习如何增加一个存取限制,使得只有你才能修改这个数字。
4 S% a. x5 M0 G- n; \& h
. n2 e. m: J& Y  H1 T  编写代币合约
, D  K" K5 a# p7 U1 T# v6 n3 o6 ?9 }. J- _8 I- V: O& r
  接下来的合约将实现一个形式最简单的加密货币。任何人都可以发送货币给其他人,不需要注册用户名和密码,只要有一对以太坊的公私钥即可。) y6 o# V; i: f# ~+ c- _

$ Z/ S9 @0 ~  o" r4 G4 `  contract Coin {
+ K! k6 R8 \8 z4 s# t) k  //关键字“public”使变量能从合约外部访问。! a7 T8 j* t: m" A3 n
  address public minter;  E; O$ C4 V/ l- i# _, `, @
  mapping (address => uint) public balances;( i9 X8 }0 @0 V! b. ^0 L
  //事件让轻客户端能高效的对变化做出反应。; W+ L& T. T3 w
  event Sent(address from, address to, uint amount);4 B$ t+ e4 R: Z  ~# S+ E! a- b
  //这个构造函数的代码仅仅只在合约创建的时候被运行。6 @- f( }% U  Y9 S; K' i
  1.   function Coin() {- M/ V9 G+ t5 l8 r& D4 s( y
  2.   minter = msg.sender;/ u# a% M6 g! B, [
  3.   }
复制代码

  Q1 l3 g. u; p2 d  N2 b$ k' H' ?5 h" @
  1.   function mint(address receiver, uint amount) {' k" R" C6 Q' S" l8 P0 ]
  2.   if (msg.sender != minter) return;2 p: V8 S9 i. O& }- }0 u
  3.   balances[receiver] += amount;# A. V3 F; A# u
  4.   }
复制代码

+ e$ _6 L( o! A) @" n0 P' E% [4 ~# @- h* g
  function send(address receiver, uint amount) {8 O% _* [; k, O6 a2 J$ G) L( D
  if (balances[msg.sender]
& p' B. O! m4 I9 u, k( H/ z+ O1 U" }: @; ]
  这个合约引入了一些新的概念,让我们来逐个介绍。
5 f" f5 M' g3 ?. `
$ @( C! }" k+ }/ B  x& H  address public minter;`2 ^1 K; i5 s  P; X8 w/ _, I
2 [) j9 J0 s: Q9 i' p
  这行代码声明了一个可公开访问的状态变量,类型为address。address类型的值大小为160 bits,不支持任何算术操作。适用于存储合约的地址或其他人的公私钥。public关键字会自动为其修饰的状态变量生成访问函数。没有public关键字的变量将无法被其他合约访问。另外只有本合约内的代码才能写入。自动生成的函数如下:
3 @& f! F" Q4 S. f' O! p3 m1 z2 e- `: R8 |. k% |4 U& u# V
  function minter() returns (address) { return minter; }
! T- c2 p+ ]% ]0 S3 M* c1 E7 _, L$ o8 r
  当然我们自己增加一个这样的访问函数是行不通的。编译器会报错,指出这个函数与一个状态变量重名。
2 ]) E. I  c, K8 P: X5 y# R
) c7 w# ~: k+ Q: Y  下一行代码创建了一个public的状态变量,但是其类型更加复杂:
: a/ s3 h# ~7 g: n2 _; F5 ^3 D& U; f, K7 k3 `! b* L6 B
  mapping (address => uint) public balances;. v. r; x- s) s) @$ [$ `. A

* ], C% q" j! P; m7 E3 j  该类型将一些address映射到无符号整数。mapping可以被认为是一个哈希表,每一个可能的key对应的value被虚拟的初始化为全0.这个类比不是很严谨,对于一个mapping,无法获取一个包含其所有key或者value的链表。所以我们得自己记着添加了哪些东西到mapping中。更好的方式是维护一个这样的链表,或者使用其他更高级的数据类型。或者只在不受这个缺陷影响的场景中使用mapping,就像这个例子。在这个例子中由public关键字生成的访问函数将会更加复杂,其代码大致如下:( h8 `' q- h; \, R

- M$ E/ u/ w* D/ E$ S
  1.   function balances(address _account) returns (uint balance) {$ Y1 \! L) v1 M+ q8 }3 {
  2.   return balances[_account];1 o# p! i% N2 C) _! B2 Y" f
  3.   }
复制代码
7 T& v- f5 T, I- \

3 e4 M+ Y/ h4 B. l2 h9 b  我们可以很方便的通过这个函数查询某个特定账号的余额。
, q2 {# R% G* q" o" R: Q& ~
6 A2 @' B; s  y5 ~- m  event Sent(address from, address to, uint value);
$ j% T0 M: z* Q7 ^
4 J2 T" }- B5 U4 S: U4 v+ G! B  这行代码声明了一个“事件”。由send函数的最后一行代码触发。客户端(服务端应用也适用)可以以很低的开销来监听这些由区块链触发的事件。事件触发时,监听者会同时接收到from,to,value这些参数值,可以方便的用于跟踪交易。为了监听这个事件,你可以使用如下代码:
2 E6 I, W; }! E* d) ^- ?0 X; y- x" b" g) S! X7 e! [- j
  
  1. Coin.Sent().watch({}, '', function(error, result) {
    ! l+ t- m5 @- D' |4 @5 ]6 A  G* l
  2.   if (!error) {) E4 c, T3 v4 [+ f8 M8 _
  3.   console.log("Coin transfer: " + result.args.amount +
    8 s$ H0 X3 K" d5 ^5 U, _- ~
  4.   " coins were sent from " + result.args.from +
    : g5 h( x8 {3 D5 d) j3 U7 W
  5.   " to " + result.args.to + ".");
    / C9 p3 f" A$ o. _0 \7 A  @
  6.   console.log("Balances now:\n" +
    / V' \, `  ~! p& U( z
  7.   "Sender: " + Coin.balances.call(result.args.from) +
    * Q/ ^: L% }6 y6 J2 \8 f& L% p
  8.   "Receiver: " + Coin.balances.call(result.args.to));
    8 t( U% H- d0 E* l( n5 o
  9.   }
    / T( Z  r5 b1 m) O- C# [
  10.   }
复制代码
( L7 F3 m% r4 |
  o& z5 f% d7 L0 I0 G" }) \
  注意在客户端中是如何调用自动生成的 balances 函数的。  q6 [% }0 ]9 i% ~# L' G# C: e8 @

% P. O) S( c0 |& p: l; [  ~1 ~5 v  这里有个比较特殊的函数 Coin。它是一个构造函数,会在合约创建的时候运行,之后就无法被调用。它会永久得存储合约创建者的地址。msg(以及tx和block)是一个神奇的全局变量,它包含了一些可以被合约代码访问的属于区块链的属性。msg.sender 总是存放着当前函数的外部调用者的地址。
( a0 p' M$ X. F6 ]1 @8 r) V. j4 E& [! e0 Y0 F4 H7 y
  最后,真正被用户或者其他合约调用,用来完成本合约功能的函数是mint和send。如果合约创建者之外的其他人调用mint,什么都不会发生。而send可以被任何人(拥有一定数量的代币)调用,发送一些币给其他人。注意,当你通过该合约发送一些代币到某个地址,在区块链浏览器中查询该地址将什么也看不到。因为发送代币导致的余额变化只存储在该代币合约的数据存储中。通过事件我们可以很容易创建一个可以追踪你的新币交易和余额的“区块链浏览器”。2 ]8 A! O& `, r
+ D0 E+ Q( [; F3 ~" |1 E
  分享两个教程和一些免费资料给读者:
3 ~3 Z; Q# F* h' F8 n- Z4 y* d# M- }% H6 \# k5 v
  一个适合区块链新手的以太坊DApp开发教程:) X: E! e8 L& q1 B
: G  S0 T0 l5 B3 _
  http://xc.hubwiz.com/course/5a952991adb3847553d205d1
! P8 F; o2 V: o* D5 }4 b8 D$ {$ M2 m) f- x% r# T7 R& g3 K9 k
  一个用区块链、星际文件系统(IPFS)、Node.js和MongoDB来构建电商平台:
1 N% D7 h: Y' t, @5 l0 ]/ r* i& m
0 {7 Q) `0 f8 D  http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6+ o0 M* ^& @( l+ u7 b& ]5 s
5 G- J, p% d9 v4 W
  收集整理了一些免费区块链、以太坊技术开发相关的文件,有需要的可以下载,文件链接:' }1 H+ t3 h0 b" {8 u0 M& X
9 \4 h6 `3 u' [3 J9 l7 m+ Z: V% E5 Q

- P7 O: d6 H. _$ l
8 t. E. [# I1 ~2 f. R9 \  web3.js API官方文档中文版:https://pan.baidu.com/s/1hOV9hEzi7hFxJCL4LTvC6g' }7 T7 J4 F" K% q( R; d
3 [, v0 v% a3 z" X8 v# V# }  V. s
  以太坊官方文档中文版 :https://pan.baidu.com/s/1ktODJKLMBmkOsi8MPrpIJA$ Z( G6 a& F# X: G) j# z: l

: k! t" B7 |9 `5 s  以太坊白皮书中文版 :https://pan.baidu.com/s/1bzAFnzJ35hlQxJ2J4Oj-Ow
6 a2 o- q& a  G/ R, E% a) ?
7 P$ `# L, R3 C8 d# \  Solidity的官方文档中文版 :https://pan.baidu.com/s/18yp9XjEqAHpiFm2ZSCygHw
& e: E  _$ e8 f9 B
2 H" K; o! U4 y* l' S  Truffle的官方文档中文版 :https://pan.baidu.com/s/1y6SVd7lSLUHK21YF5FzIUQ
6 K' C* x7 X/ q( w( }2 J6 U+ u( S! c% \9 T! W; u
  C#区块链编程指南 :https://pan.baidu.com/s/1sJPLqp1eQqkG7jmxqwn3EA
0 G# p4 O" a6 ^- ?/ l# h! |$ s, `/ n, Z/ z
  区块链技术指南 :https://pan.baidu.com/s/13cJxAa80I6iMCczA04CZhg% C1 S3 C& t. R# s* C
" B! ?9 z" h% K, O
  精通比特币中文版 :https://pan.baidu.com/s/1lz6te3wcQuNJm28rFvBfxg
0 S. j3 V  K3 N7 w* k4 l
! ~9 R. A8 R" z' P  Node.js区块链开发 :https://pan.baidu.com/s/1Ldpn0DvJ5LgLqwix6eWgyg9 [* h" ^3 V- w6 A/ Q9 A! O

4 D; h9 J7 b" f( u0 o$ `+ T7 V# Q  geth使用指南文档中文版 :https://pan.baidu.com/s/1M0WxhmumF_fRqzt_cegnag4 V( f' D2 {; s3 [/ T* G
1 @) e6 T6 @9 B6 I- h7 n
  以太坊DApp开发环境搭建-Ubuntu : https://pan.baidu.com/s/10qL4q-uKooMehv9X2R1qSA) l# D; N. V0 W
4 G1 s; m2 ^& U' |" \
  以太坊DApp开发环境搭建-windows :https://pan.baidu.com/s/1cyYkhIJIFuI2oyxM9Ut0eA* \/ |2 `2 s& R  p  m6 n
. i8 P' D* K5 I' I, ?- x
  以太坊DApp开发私链搭建-Ubuntu : https://pan.baidu.com/s/1aBOFZT2bCjD2o0EILBWs-g
( R# N# V% u$ n8 i3 P- Z# s+ ]# C. W8 v; o& @  A2 d
  以太坊DApp开发私链搭建-windows :https://pan.baidu.com/s/10Y6F1cqUltZNN99aJv9kAA
- N2 B+ g- X" n1 X% ?6 q
) g5 w+ f7 J! V. E2 P; v. [% r7 B4 I; Y( L3 j( H

# l0 |5 J5 t, V1 y  T8 y6 o
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

天之涯神之兵米 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    15